//
// Copyright 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// MemoryProgramCache: Stores compiled and linked programs in memory so they don't
//   always have to be re-compiled. Can be used in conjunction with the platform
//   layer to warm up the cache from disk.

#include "libANGLE/MemoryProgramCache.h"

#include <GLSLANG/ShaderVars.h>
#include <anglebase/sha1.h>

#include "common/utilities.h"
#include "common/version.h"
#include "libANGLE/BinaryStream.h"
#include "libANGLE/Context.h"
#include "libANGLE/Uniform.h"
#include "libANGLE/histogram_macros.h"
#include "libANGLE/renderer/ProgramImpl.h"
#include "platform/Platform.h"

namespace gl
{

namespace
{
constexpr unsigned int kWarningLimit = 3;

void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
{
    stream->writeInt(var.type);
    stream->writeInt(var.precision);
    stream->writeString(var.name);
    stream->writeString(var.mappedName);
    stream->writeIntVector(var.arraySizes);
    stream->writeInt(var.staticUse);
    stream->writeInt(var.active);
    stream->writeString(var.structName);
    ASSERT(var.fields.empty());
}

void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
{
    var->type       = stream->readInt<GLenum>();
    var->precision  = stream->readInt<GLenum>();
    var->name       = stream->readString();
    var->mappedName = stream->readString();
    stream->readIntVector<unsigned int>(&var->arraySizes);
    var->staticUse  = stream->readBool();
    var->active     = stream->readBool();
    var->structName = stream->readString();
}

void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
{
    stream->writeInt(var.binding);
    stream->writeInt(var.dataSize);

    for (ShaderType shaderType : AllShaderTypes())
    {
        stream->writeInt(var.isActive(shaderType));
    }

    stream->writeInt(var.memberIndexes.size());
    for (unsigned int memberCounterIndex : var.memberIndexes)
    {
        stream->writeInt(memberCounterIndex);
    }
}

void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
{
    var->binding  = stream->readInt<int>();
    var->dataSize = stream->readInt<unsigned int>();

    for (ShaderType shaderType : AllShaderTypes())
    {
        var->setActive(shaderType, stream->readBool());
    }

    unsigned int numMembers = stream->readInt<unsigned int>();
    for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
    {
        var->memberIndexes.push_back(stream->readInt<unsigned int>());
    }
}

void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
{
    WriteShaderVar(stream, var);

    stream->writeInt(var.bufferIndex);
    stream->writeInt(var.blockInfo.offset);
    stream->writeInt(var.blockInfo.arrayStride);
    stream->writeInt(var.blockInfo.matrixStride);
    stream->writeInt(var.blockInfo.isRowMajorMatrix);
    stream->writeInt(var.blockInfo.topLevelArrayStride);
    stream->writeInt(var.topLevelArraySize);

    for (ShaderType shaderType : AllShaderTypes())
    {
        stream->writeInt(var.isActive(shaderType));
    }
}

void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
{
    LoadShaderVar(stream, var);

    var->bufferIndex                   = stream->readInt<int>();
    var->blockInfo.offset              = stream->readInt<int>();
    var->blockInfo.arrayStride         = stream->readInt<int>();
    var->blockInfo.matrixStride        = stream->readInt<int>();
    var->blockInfo.isRowMajorMatrix    = stream->readBool();
    var->blockInfo.topLevelArrayStride = stream->readInt<int>();
    var->topLevelArraySize             = stream->readInt<int>();

    for (ShaderType shaderType : AllShaderTypes())
    {
        var->setActive(shaderType, stream->readBool());
    }
}

void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
{
    stream->writeString(block.name);
    stream->writeString(block.mappedName);
    stream->writeInt(block.isArray);
    stream->writeInt(block.arrayElement);

    WriteShaderVariableBuffer(stream, block);
}

void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
{
    block->name         = stream->readString();
    block->mappedName   = stream->readString();
    block->isArray      = stream->readBool();
    block->arrayElement = stream->readInt<unsigned int>();

    LoadShaderVariableBuffer(stream, block);
}

class HashStream final : angle::NonCopyable
{
  public:
    std::string str() { return mStringStream.str(); }

    template <typename T>
    HashStream &operator<<(T value)
    {
        mStringStream << value << kSeparator;
        return *this;
    }

  private:
    static constexpr char kSeparator = ':';
    std::ostringstream mStringStream;
};

HashStream &operator<<(HashStream &stream, const Shader *shader)
{
    if (shader)
    {
        stream << shader->getSourceString().c_str() << shader->getSourceString().length()
               << shader->getCompilerResourcesString().c_str();
    }
    return stream;
}

HashStream &operator<<(HashStream &stream, const ProgramBindings &bindings)
{
    for (const auto &binding : bindings)
    {
        stream << binding.first << binding.second;
    }
    return stream;
}

HashStream &operator<<(HashStream &stream, const std::vector<std::string> &strings)
{
    for (const auto &str : strings)
    {
        stream << str;
    }
    return stream;
}

HashStream &operator<<(HashStream &stream, const std::vector<gl::VariableLocation> &locations)
{
    for (const auto &loc : locations)
    {
        stream << loc.index << loc.arrayIndex << loc.ignored;
    }
    return stream;
}

}  // anonymous namespace

MemoryProgramCache::MemoryProgramCache(egl::BlobCache &blobCache)
    : mBlobCache(blobCache), mIssuedWarnings(0)
{}

MemoryProgramCache::~MemoryProgramCache() {}

// static
angle::Result MemoryProgramCache::Deserialize(const Context *context,
                                              const Program *program,
                                              ProgramState *state,
                                              const uint8_t *binary,
                                              size_t length,
                                              InfoLog &infoLog)
{
    BinaryInputStream stream(binary, length);

    unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
    stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
    if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
        0)
    {
        infoLog << "Invalid program binary version.";
        return angle::Result::Incomplete;
    }

    int majorVersion = stream.readInt<int>();
    int minorVersion = stream.readInt<int>();
    if (majorVersion != context->getClientMajorVersion() ||
        minorVersion != context->getClientMinorVersion())
    {
        infoLog << "Cannot load program binaries across different ES context versions.";
        return angle::Result::Incomplete;
    }

    state->mComputeShaderLocalSize[0] = stream.readInt<int>();
    state->mComputeShaderLocalSize[1] = stream.readInt<int>();
    state->mComputeShaderLocalSize[2] = stream.readInt<int>();

    state->mGeometryShaderInputPrimitiveType  = stream.readEnum<PrimitiveMode>();
    state->mGeometryShaderOutputPrimitiveType = stream.readEnum<PrimitiveMode>();
    state->mGeometryShaderInvocations         = stream.readInt<int>();
    state->mGeometryShaderMaxVertices         = stream.readInt<int>();

    state->mNumViews = stream.readInt<int>();

    static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
                  "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
    state->mAttributesTypeMask.from_ulong(stream.readInt<uint32_t>());
    state->mAttributesMask = stream.readInt<gl::AttributesMask>();

    static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
                  "Too many vertex attribs for mask");
    state->mActiveAttribLocationsMask = stream.readInt<gl::AttributesMask>();

    unsigned int attribCount = stream.readInt<unsigned int>();
    ASSERT(state->mAttributes.empty());
    for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
    {
        sh::Attribute attrib;
        LoadShaderVar(&stream, &attrib);
        attrib.location = stream.readInt<int>();
        state->mAttributes.push_back(attrib);
    }

    unsigned int uniformCount = stream.readInt<unsigned int>();
    ASSERT(state->mUniforms.empty());
    for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
    {
        LinkedUniform uniform;
        LoadShaderVar(&stream, &uniform);

        uniform.bufferIndex                = stream.readInt<int>();
        uniform.blockInfo.offset           = stream.readInt<int>();
        uniform.blockInfo.arrayStride      = stream.readInt<int>();
        uniform.blockInfo.matrixStride     = stream.readInt<int>();
        uniform.blockInfo.isRowMajorMatrix = stream.readBool();

        uniform.typeInfo = &GetUniformTypeInfo(uniform.type);

        state->mUniforms.push_back(uniform);
    }

    const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
    ASSERT(state->mUniformLocations.empty());
    for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
         uniformIndexIndex++)
    {
        VariableLocation variable;
        stream.readInt(&variable.arrayIndex);
        stream.readInt(&variable.index);
        stream.readBool(&variable.ignored);

        state->mUniformLocations.push_back(variable);
    }

    unsigned int uniformBlockCount = stream.readInt<unsigned int>();
    ASSERT(state->mUniformBlocks.empty());
    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
         ++uniformBlockIndex)
    {
        InterfaceBlock uniformBlock;
        LoadInterfaceBlock(&stream, &uniformBlock);
        state->mUniformBlocks.push_back(uniformBlock);

        state->mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
    }

    unsigned int bufferVariableCount = stream.readInt<unsigned int>();
    ASSERT(state->mBufferVariables.empty());
    for (unsigned int index = 0; index < bufferVariableCount; ++index)
    {
        BufferVariable bufferVariable;
        LoadBufferVariable(&stream, &bufferVariable);
        state->mBufferVariables.push_back(bufferVariable);
    }

    unsigned int shaderStorageBlockCount = stream.readInt<unsigned int>();
    ASSERT(state->mShaderStorageBlocks.empty());
    for (unsigned int shaderStorageBlockIndex = 0;
         shaderStorageBlockIndex < shaderStorageBlockCount; ++shaderStorageBlockIndex)
    {
        InterfaceBlock shaderStorageBlock;
        LoadInterfaceBlock(&stream, &shaderStorageBlock);
        state->mShaderStorageBlocks.push_back(shaderStorageBlock);
    }

    unsigned int atomicCounterBufferCount = stream.readInt<unsigned int>();
    ASSERT(state->mAtomicCounterBuffers.empty());
    for (unsigned int bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
    {
        AtomicCounterBuffer atomicCounterBuffer;
        LoadShaderVariableBuffer(&stream, &atomicCounterBuffer);

        state->mAtomicCounterBuffers.push_back(atomicCounterBuffer);
    }

    unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();

    // Reject programs that use transform feedback varyings if the hardware cannot support them.
    if (transformFeedbackVaryingCount > 0 &&
        context->getWorkarounds().disableProgramCachingForTransformFeedback)
    {
        infoLog << "Current driver does not support transform feedback in binary programs.";
        return angle::Result::Incomplete;
    }

    ASSERT(state->mLinkedTransformFeedbackVaryings.empty());
    for (unsigned int transformFeedbackVaryingIndex = 0;
         transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
         ++transformFeedbackVaryingIndex)
    {
        sh::Varying varying;
        stream.readIntVector<unsigned int>(&varying.arraySizes);
        stream.readInt(&varying.type);
        stream.readString(&varying.name);

        GLuint arrayIndex = stream.readInt<GLuint>();

        state->mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
    }

    stream.readInt(&state->mTransformFeedbackBufferMode);

    unsigned int outputCount = stream.readInt<unsigned int>();
    ASSERT(state->mOutputVariables.empty());
    for (unsigned int outputIndex = 0; outputIndex < outputCount; ++outputIndex)
    {
        sh::OutputVariable output;
        LoadShaderVar(&stream, &output);
        output.location = stream.readInt<int>();
        output.index    = stream.readInt<int>();
        state->mOutputVariables.push_back(output);
    }

    unsigned int outputVarCount = stream.readInt<unsigned int>();
    ASSERT(state->mOutputLocations.empty());
    for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
    {
        VariableLocation locationData;
        stream.readInt(&locationData.arrayIndex);
        stream.readInt(&locationData.index);
        stream.readBool(&locationData.ignored);
        state->mOutputLocations.push_back(locationData);
    }

    unsigned int secondaryOutputVarCount = stream.readInt<unsigned int>();
    ASSERT(state->mSecondaryOutputLocations.empty());
    for (unsigned int outputIndex = 0; outputIndex < secondaryOutputVarCount; ++outputIndex)
    {
        VariableLocation locationData;
        stream.readInt(&locationData.arrayIndex);
        stream.readInt(&locationData.index);
        stream.readBool(&locationData.ignored);
        state->mSecondaryOutputLocations.push_back(locationData);
    }

    unsigned int outputTypeCount = stream.readInt<unsigned int>();
    for (unsigned int outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
    {
        state->mOutputVariableTypes.push_back(stream.readInt<GLenum>());
    }

    static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
                  "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
                  "into 32 bits each");
    state->mDrawBufferTypeMask.from_ulong(stream.readInt<uint32_t>());
    state->mActiveOutputVariables = stream.readInt<gl::DrawBufferMask>();

    unsigned int samplerRangeLow  = stream.readInt<unsigned int>();
    unsigned int samplerRangeHigh = stream.readInt<unsigned int>();
    state->mSamplerUniformRange   = RangeUI(samplerRangeLow, samplerRangeHigh);
    unsigned int samplerCount     = stream.readInt<unsigned int>();
    for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
    {
        TextureType textureType = stream.readEnum<TextureType>();
        SamplerFormat format    = stream.readEnum<SamplerFormat>();
        size_t bindingCount     = stream.readInt<size_t>();
        bool unreferenced       = stream.readBool();
        state->mSamplerBindings.emplace_back(textureType, format, bindingCount, unreferenced);
    }

    unsigned int imageRangeLow     = stream.readInt<unsigned int>();
    unsigned int imageRangeHigh    = stream.readInt<unsigned int>();
    state->mImageUniformRange      = RangeUI(imageRangeLow, imageRangeHigh);
    unsigned int imageBindingCount = stream.readInt<unsigned int>();
    for (unsigned int imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
    {
        unsigned int elementCount = stream.readInt<unsigned int>();
        ImageBinding imageBinding(elementCount);
        for (unsigned int i = 0; i < elementCount; ++i)
        {
            imageBinding.boundImageUnits[i] = stream.readInt<unsigned int>();
        }
        state->mImageBindings.emplace_back(imageBinding);
    }

    unsigned int atomicCounterRangeLow  = stream.readInt<unsigned int>();
    unsigned int atomicCounterRangeHigh = stream.readInt<unsigned int>();
    state->mAtomicCounterUniformRange   = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);

    static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
                  "Too many shader types");
    state->mLinkedShaderStages = ShaderBitSet(stream.readInt<uint8_t>());

    state->updateTransformFeedbackStrides();
    state->updateActiveSamplers();
    state->updateActiveImages();

    return program->getImplementation()->load(context, infoLog, &stream);
}

// static
void MemoryProgramCache::Serialize(const Context *context,
                                   const gl::Program *program,
                                   angle::MemoryBuffer *binaryOut)
{
    BinaryOutputStream stream;

    stream.writeBytes(reinterpret_cast<const unsigned char *>(ANGLE_COMMIT_HASH),
                      ANGLE_COMMIT_HASH_SIZE);

    // nullptr context is supported when computing binary length.
    if (context)
    {
        stream.writeInt(context->getClientVersion().major);
        stream.writeInt(context->getClientVersion().minor);
    }
    else
    {
        stream.writeInt(2);
        stream.writeInt(0);
    }

    const auto &state = program->getState();

    const auto &computeLocalSize = state.getComputeShaderLocalSize();

    stream.writeInt(computeLocalSize[0]);
    stream.writeInt(computeLocalSize[1]);
    stream.writeInt(computeLocalSize[2]);

    ASSERT(state.mGeometryShaderInvocations >= 1 && state.mGeometryShaderMaxVertices >= 0);
    stream.writeEnum(state.mGeometryShaderInputPrimitiveType);
    stream.writeEnum(state.mGeometryShaderOutputPrimitiveType);
    stream.writeInt(state.mGeometryShaderInvocations);
    stream.writeInt(state.mGeometryShaderMaxVertices);

    stream.writeInt(state.mNumViews);

    static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
                  "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
    stream.writeInt(static_cast<int>(state.mAttributesTypeMask.to_ulong()));
    stream.writeInt(static_cast<int>(state.mAttributesMask.to_ulong()));

    stream.writeInt(state.getActiveAttribLocationsMask().to_ulong());

    stream.writeInt(state.getAttributes().size());
    for (const sh::Attribute &attrib : state.getAttributes())
    {
        WriteShaderVar(&stream, attrib);
        stream.writeInt(attrib.location);
    }

    stream.writeInt(state.getUniforms().size());
    for (const LinkedUniform &uniform : state.getUniforms())
    {
        WriteShaderVar(&stream, uniform);

        // FIXME: referenced

        stream.writeInt(uniform.bufferIndex);
        stream.writeInt(uniform.blockInfo.offset);
        stream.writeInt(uniform.blockInfo.arrayStride);
        stream.writeInt(uniform.blockInfo.matrixStride);
        stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
    }

    stream.writeInt(state.getUniformLocations().size());
    for (const auto &variable : state.getUniformLocations())
    {
        stream.writeInt(variable.arrayIndex);
        stream.writeIntOrNegOne(variable.index);
        stream.writeInt(variable.ignored);
    }

    stream.writeInt(state.getUniformBlocks().size());
    for (const InterfaceBlock &uniformBlock : state.getUniformBlocks())
    {
        WriteInterfaceBlock(&stream, uniformBlock);
    }

    stream.writeInt(state.getBufferVariables().size());
    for (const BufferVariable &bufferVariable : state.getBufferVariables())
    {
        WriteBufferVariable(&stream, bufferVariable);
    }

    stream.writeInt(state.getShaderStorageBlocks().size());
    for (const InterfaceBlock &shaderStorageBlock : state.getShaderStorageBlocks())
    {
        WriteInterfaceBlock(&stream, shaderStorageBlock);
    }

    stream.writeInt(state.mAtomicCounterBuffers.size());
    for (const auto &atomicCounterBuffer : state.mAtomicCounterBuffers)
    {
        WriteShaderVariableBuffer(&stream, atomicCounterBuffer);
    }

    // Warn the app layer if saving a binary with unsupported transform feedback.
    if (!state.getLinkedTransformFeedbackVaryings().empty() &&
        context->getWorkarounds().disableProgramCachingForTransformFeedback)
    {
        WARN() << "Saving program binary with transform feedback, which is not supported on this "
                  "driver.";
    }

    stream.writeInt(state.getLinkedTransformFeedbackVaryings().size());
    for (const auto &var : state.getLinkedTransformFeedbackVaryings())
    {
        stream.writeIntVector(var.arraySizes);
        stream.writeInt(var.type);
        stream.writeString(var.name);

        stream.writeIntOrNegOne(var.arrayIndex);
    }

    stream.writeInt(state.getTransformFeedbackBufferMode());

    stream.writeInt(state.getOutputVariables().size());
    for (const sh::OutputVariable &output : state.getOutputVariables())
    {
        WriteShaderVar(&stream, output);
        stream.writeInt(output.location);
        stream.writeInt(output.index);
    }

    stream.writeInt(state.getOutputLocations().size());
    for (const auto &outputVar : state.getOutputLocations())
    {
        stream.writeInt(outputVar.arrayIndex);
        stream.writeIntOrNegOne(outputVar.index);
        stream.writeInt(outputVar.ignored);
    }

    stream.writeInt(state.getSecondaryOutputLocations().size());
    for (const auto &outputVar : state.getSecondaryOutputLocations())
    {
        stream.writeInt(outputVar.arrayIndex);
        stream.writeIntOrNegOne(outputVar.index);
        stream.writeInt(outputVar.ignored);
    }

    stream.writeInt(state.mOutputVariableTypes.size());
    for (const auto &outputVariableType : state.mOutputVariableTypes)
    {
        stream.writeInt(outputVariableType);
    }

    static_assert(
        IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
        "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
    stream.writeInt(static_cast<int>(state.mDrawBufferTypeMask.to_ulong()));
    stream.writeInt(static_cast<int>(state.mActiveOutputVariables.to_ulong()));

    stream.writeInt(state.getSamplerUniformRange().low());
    stream.writeInt(state.getSamplerUniformRange().high());

    stream.writeInt(state.getSamplerBindings().size());
    for (const auto &samplerBinding : state.getSamplerBindings())
    {
        stream.writeEnum(samplerBinding.textureType);
        stream.writeEnum(samplerBinding.format);
        stream.writeInt(samplerBinding.boundTextureUnits.size());
        stream.writeInt(samplerBinding.unreferenced);
    }

    stream.writeInt(state.getImageUniformRange().low());
    stream.writeInt(state.getImageUniformRange().high());

    stream.writeInt(state.getImageBindings().size());
    for (const auto &imageBinding : state.getImageBindings())
    {
        stream.writeInt(imageBinding.boundImageUnits.size());
        for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
        {
            stream.writeInt(imageBinding.boundImageUnits[i]);
        }
    }

    stream.writeInt(state.getAtomicCounterUniformRange().low());
    stream.writeInt(state.getAtomicCounterUniformRange().high());

    stream.writeInt(state.getLinkedShaderStages().to_ulong());

    program->getImplementation()->save(context, &stream);

    ASSERT(binaryOut);
    binaryOut->resize(stream.length());
    memcpy(binaryOut->data(), stream.data(), stream.length());
}

// static
void MemoryProgramCache::ComputeHash(const Context *context,
                                     const Program *program,
                                     egl::BlobCache::Key *hashOut)
{
    // Compute the program hash. Start with the shader hashes and resource strings.
    HashStream hashStream;
    for (ShaderType shaderType : AllShaderTypes())
    {
        hashStream << program->getAttachedShader(shaderType);
    }

    // Add some ANGLE metadata and Context properties, such as version and back-end.
    hashStream << ANGLE_COMMIT_HASH << context->getClientMajorVersion()
               << context->getClientMinorVersion() << context->getString(GL_RENDERER);

    // Hash pre-link program properties.
    hashStream << program->getAttributeBindings() << program->getUniformLocationBindings()
               << program->getFragmentInputBindings()
               << program->getState().getTransformFeedbackVaryingNames()
               << program->getState().getTransformFeedbackBufferMode()
               << program->getState().getOutputLocations()
               << program->getState().getSecondaryOutputLocations();

    // Call the secure SHA hashing function.
    const std::string &programKey = hashStream.str();
    angle::base::SHA1HashBytes(reinterpret_cast<const unsigned char *>(programKey.c_str()),
                               programKey.length(), hashOut->data());
}

angle::Result MemoryProgramCache::getProgram(const Context *context,
                                             const Program *program,
                                             ProgramState *state,
                                             egl::BlobCache::Key *hashOut)
{
    ComputeHash(context, program, hashOut);
    egl::BlobCache::Value binaryProgram;
    if (get(context, *hashOut, &binaryProgram))
    {
        InfoLog infoLog;
        angle::Result result = Deserialize(context, program, state, binaryProgram.data(),
                                           binaryProgram.size(), infoLog);
        ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.ProgramCache.LoadBinarySuccess",
                                result == angle::Result::Continue);
        ANGLE_TRY(result);

        if (result == angle::Result::Continue)
            return angle::Result::Continue;

        // Cache load failed, evict.
        if (mIssuedWarnings++ < kWarningLimit)
        {
            WARN() << "Failed to load binary from cache: " << infoLog.str();

            if (mIssuedWarnings == kWarningLimit)
            {
                WARN() << "Reaching warning limit for cache load failures, silencing "
                          "subsequent warnings.";
            }
        }
        remove(*hashOut);
    }
    return angle::Result::Incomplete;
}

bool MemoryProgramCache::get(const Context *context,
                             const egl::BlobCache::Key &programHash,
                             egl::BlobCache::Value *programOut)
{
    return mBlobCache.get(context->getScratchBuffer(), programHash, programOut);
}

bool MemoryProgramCache::getAt(size_t index,
                               const egl::BlobCache::Key **hashOut,
                               egl::BlobCache::Value *programOut)
{
    return mBlobCache.getAt(index, hashOut, programOut);
}

void MemoryProgramCache::remove(const egl::BlobCache::Key &programHash)
{
    mBlobCache.remove(programHash);
}

void MemoryProgramCache::putProgram(const egl::BlobCache::Key &programHash,
                                    const Context *context,
                                    const Program *program)
{
    angle::MemoryBuffer serializedProgram;
    Serialize(context, program, &serializedProgram);

    ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramBinarySizeBytes",
                           static_cast<int>(serializedProgram.size()));

    // TODO(syoussefi): to be removed.  Compatibility for Chrome until it supports
    // EGL_ANDROID_blob_cache. http://anglebug.com/2516
    auto *platform = ANGLEPlatformCurrent();
    platform->cacheProgram(platform, programHash, serializedProgram.size(),
                           serializedProgram.data());

    mBlobCache.put(programHash, std::move(serializedProgram));
}

void MemoryProgramCache::updateProgram(const Context *context, const Program *program)
{
    egl::BlobCache::Key programHash;
    ComputeHash(context, program, &programHash);
    putProgram(programHash, context, program);
}

void MemoryProgramCache::putBinary(const egl::BlobCache::Key &programHash,
                                   const uint8_t *binary,
                                   size_t length)
{
    // Copy the binary.
    angle::MemoryBuffer newEntry;
    newEntry.resize(length);
    memcpy(newEntry.data(), binary, length);

    // Store the binary.
    mBlobCache.populate(programHash, std::move(newEntry));
}

void MemoryProgramCache::clear()
{
    mBlobCache.clear();
    mIssuedWarnings = 0;
}

void MemoryProgramCache::resize(size_t maxCacheSizeBytes)
{
    mBlobCache.resize(maxCacheSizeBytes);
}

size_t MemoryProgramCache::entryCount() const
{
    return mBlobCache.entryCount();
}

size_t MemoryProgramCache::trim(size_t limit)
{
    return mBlobCache.trim(limit);
}

size_t MemoryProgramCache::size() const
{
    return mBlobCache.size();
}

size_t MemoryProgramCache::maxSize() const
{
    return mBlobCache.maxSize();
}

}  // namespace gl
