tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MemoryShaderCache.cpp (5736B)


      1 //
      2 // Copyright 2022 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 // MemoryShaderCache: Stores compiled shader in memory so they don't
      7 //   always have to be re-compiled. Can be used in conjunction with the platform
      8 //   layer to warm up the cache from disk.
      9 
     10 #include "libANGLE/MemoryShaderCache.h"
     11 
     12 #include <GLSLANG/ShaderVars.h>
     13 #include <anglebase/sha1.h>
     14 
     15 #include "common/angle_version_info.h"
     16 #include "common/utilities.h"
     17 #include "libANGLE/BinaryStream.h"
     18 #include "libANGLE/Compiler.h"
     19 #include "libANGLE/Context.h"
     20 #include "libANGLE/Debug.h"
     21 #include "libANGLE/Uniform.h"
     22 #include "libANGLE/histogram_macros.h"
     23 #include "libANGLE/renderer/ShaderImpl.h"
     24 #include "platform/PlatformMethods.h"
     25 
     26 namespace gl
     27 {
     28 
     29 namespace
     30 {
     31 void ComputeHash(const Context *context,
     32                 const Shader *shader,
     33                 const ShCompileOptions &compileOptions,
     34                 const ShCompilerInstance &compilerInstance,
     35                 egl::BlobCache::Key *hashOut)
     36 {
     37    BinaryOutputStream hashStream;
     38    // Compute the shader hash. Start with the shader hashes and resource strings.
     39    hashStream.writeEnum(shader->getType());
     40    hashStream.writeString(shader->getSourceString());
     41 
     42    // Include the commit hash
     43    hashStream.writeString(angle::GetANGLECommitHash());
     44 
     45    hashStream.writeEnum(Compiler::SelectShaderSpec(context->getState()));
     46    hashStream.writeEnum(compilerInstance.getShaderOutputType());
     47    hashStream.writeBytes(reinterpret_cast<const uint8_t *>(&compileOptions),
     48                          sizeof(compileOptions));
     49 
     50    // Include the ShBuiltInResources, which represent the extensions and constants used by the
     51    // shader.
     52    const ShBuiltInResources resources = compilerInstance.getBuiltInResources();
     53    hashStream.writeBytes(reinterpret_cast<const uint8_t *>(&resources), sizeof(resources));
     54 
     55    // Call the secure SHA hashing function.
     56    const std::vector<uint8_t> &shaderKey = hashStream.getData();
     57    angle::base::SHA1HashBytes(shaderKey.data(), shaderKey.size(), hashOut->data());
     58 }
     59 }  // namespace
     60 
     61 MemoryShaderCache::MemoryShaderCache(egl::BlobCache &blobCache) : mBlobCache(blobCache) {}
     62 
     63 MemoryShaderCache::~MemoryShaderCache() {}
     64 
     65 angle::Result MemoryShaderCache::getShader(const Context *context,
     66                                           Shader *shader,
     67                                           const ShCompileOptions &compileOptions,
     68                                           const ShCompilerInstance &compilerInstance,
     69                                           egl::BlobCache::Key *hashOut)
     70 {
     71    // If caching is effectively disabled, don't bother calculating the hash.
     72    if (!mBlobCache.isCachingEnabled())
     73    {
     74        return angle::Result::Incomplete;
     75    }
     76 
     77    ComputeHash(context, shader, compileOptions, compilerInstance, hashOut);
     78 
     79    angle::MemoryBuffer uncompressedData;
     80    switch (mBlobCache.getAndDecompress(context->getScratchBuffer(), *hashOut, &uncompressedData))
     81    {
     82        case egl::BlobCache::GetAndDecompressResult::DecompressFailure:
     83            ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
     84                               "Error decompressing shader binary data from cache.");
     85            return angle::Result::Incomplete;
     86 
     87        case egl::BlobCache::GetAndDecompressResult::NotFound:
     88            return angle::Result::Incomplete;
     89 
     90        case egl::BlobCache::GetAndDecompressResult::GetSuccess:
     91            angle::Result result = shader->loadBinary(context, uncompressedData.data(),
     92                                                      static_cast<int>(uncompressedData.size()));
     93 
     94            {
     95                std::scoped_lock<std::mutex> lock(mHistogramMutex);
     96                ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.ShaderCache.LoadBinarySuccess",
     97                                        result == angle::Result::Continue);
     98            }
     99            ANGLE_TRY(result);
    100 
    101            if (result == angle::Result::Continue)
    102                return angle::Result::Continue;
    103 
    104            // Cache load failed, evict.
    105            ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
    106                               "Failed to load shader binary from cache.");
    107            mBlobCache.remove(*hashOut);
    108            return angle::Result::Incomplete;
    109    }
    110 
    111    UNREACHABLE();
    112    return angle::Result::Incomplete;
    113 }
    114 
    115 angle::Result MemoryShaderCache::putShader(const Context *context,
    116                                           const egl::BlobCache::Key &shaderHash,
    117                                           const Shader *shader)
    118 {
    119    // If caching is effectively disabled, don't bother serializing the shader.
    120    if (!mBlobCache.isCachingEnabled())
    121    {
    122        return angle::Result::Incomplete;
    123    }
    124 
    125    angle::MemoryBuffer serializedShader;
    126    ANGLE_TRY(shader->serialize(nullptr, &serializedShader));
    127 
    128    size_t compressedSize;
    129    if (!mBlobCache.compressAndPut(shaderHash, std::move(serializedShader), &compressedSize))
    130    {
    131        ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
    132                           "Error compressing shader binary data for insertion into cache.");
    133        return angle::Result::Incomplete;
    134    }
    135 
    136    {
    137        std::scoped_lock<std::mutex> lock(mHistogramMutex);
    138        ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ShaderCache.ShaderBinarySizeBytes",
    139                               static_cast<int>(compressedSize));
    140    }
    141 
    142    return angle::Result::Continue;
    143 }
    144 
    145 void MemoryShaderCache::clear()
    146 {
    147    mBlobCache.clear();
    148 }
    149 
    150 size_t MemoryShaderCache::maxSize() const
    151 {
    152    return mBlobCache.maxSize();
    153 }
    154 
    155 }  // namespace gl