Hash :
166b72c9
        
        Author :
  
        
        Date :
2024-09-30T19:07:26
        
      
GL_ANGLE_blob_cache implementation. Bug: chromium:370538323 Change-Id: Ic51a951e78b48b315e36f518bcc39ff2d54660a6 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5900761 Reviewed-by: Cody Northrop <cnorthrop@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
//
// Copyright 2022 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.
//
// MemoryShaderCache: Stores compiled shader 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/MemoryShaderCache.h"
#include <GLSLANG/ShaderVars.h>
#include <anglebase/sha1.h>
#include "common/BinaryStream.h"
#include "common/utilities.h"
#include "libANGLE/Compiler.h"
#include "libANGLE/Context.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Uniform.h"
#include "libANGLE/histogram_macros.h"
#include "libANGLE/renderer/ShaderImpl.h"
#include "platform/PlatformMethods.h"
namespace gl
{
namespace
{
// Limit decompressed programs to 5MB. If they're larger then this there is a good chance the data
// is not what we expect. This limits the amount of memory we will allocate based on a binary blob
// we believe is compressed data.
static constexpr size_t kMaxUncompressedShaderSize = 5 * 1024 * 1024;
}  // namespace
MemoryShaderCache::MemoryShaderCache(egl::BlobCache &blobCache) : mBlobCache(blobCache) {}
MemoryShaderCache::~MemoryShaderCache() {}
egl::CacheGetResult MemoryShaderCache::getShader(const Context *context,
                                                 Shader *shader,
                                                 const egl::BlobCache::Key &shaderHash,
                                                 angle::JobResultExpectancy resultExpectancy)
{
    // If caching is effectively disabled, don't bother calculating the hash.
    if (!mBlobCache.isCachingEnabled(context))
    {
        return egl::CacheGetResult::NotFound;
    }
    angle::MemoryBuffer uncompressedData;
    const egl::BlobCache::GetAndDecompressResult result =
        mBlobCache.getAndDecompress(context, context->getScratchBuffer(), shaderHash,
                                    kMaxUncompressedShaderSize, &uncompressedData);
    switch (result)
    {
        case egl::BlobCache::GetAndDecompressResult::DecompressFailure:
            ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                               "Error decompressing shader binary data from cache.");
            mBlobCache.remove(shaderHash);
            return egl::CacheGetResult::NotFound;
        case egl::BlobCache::GetAndDecompressResult::NotFound:
            return egl::CacheGetResult::NotFound;
        case egl::BlobCache::GetAndDecompressResult::Success:
            if (shader->loadBinary(context, uncompressedData.data(),
                                   static_cast<int>(uncompressedData.size()), resultExpectancy))
            {
                return egl::CacheGetResult::Success;
            }
            // Cache load failed, evict.
            ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                               "Failed to load shader binary from cache.");
            mBlobCache.remove(shaderHash);
            return egl::CacheGetResult::Rejected;
    }
    UNREACHABLE();
    return egl::CacheGetResult::NotFound;
}
angle::Result MemoryShaderCache::putShader(const Context *context,
                                           const egl::BlobCache::Key &shaderHash,
                                           const Shader *shader)
{
    // If caching is effectively disabled, don't bother serializing the shader.
    if (!mBlobCache.isCachingEnabled(context))
    {
        return angle::Result::Continue;
    }
    angle::MemoryBuffer serializedShader;
    ANGLE_TRY(shader->serialize(nullptr, &serializedShader));
    size_t compressedSize;
    if (!mBlobCache.compressAndPut(context, shaderHash, std::move(serializedShader),
                                   &compressedSize))
    {
        ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                           "Error compressing shader binary data for insertion into cache.");
        return angle::Result::Continue;
    }
    return angle::Result::Continue;
}
void MemoryShaderCache::clear()
{
    mBlobCache.clear();
}
size_t MemoryShaderCache::maxSize() const
{
    return mBlobCache.maxSize();
}
}  // namespace gl