• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/BinaryStream.h"
16 #include "common/utilities.h"
17 #include "libANGLE/Compiler.h"
18 #include "libANGLE/Context.h"
19 #include "libANGLE/Debug.h"
20 #include "libANGLE/Uniform.h"
21 #include "libANGLE/histogram_macros.h"
22 #include "libANGLE/renderer/ShaderImpl.h"
23 #include "platform/PlatformMethods.h"
24 
25 namespace gl
26 {
27 
MemoryShaderCache(egl::BlobCache & blobCache)28 MemoryShaderCache::MemoryShaderCache(egl::BlobCache &blobCache) : mBlobCache(blobCache) {}
29 
~MemoryShaderCache()30 MemoryShaderCache::~MemoryShaderCache() {}
31 
getShader(const Context * context,Shader * shader,const ShCompileOptions & compileOptions,const ShCompilerInstance & compilerInstance,const egl::BlobCache::Key & shaderHash)32 angle::Result MemoryShaderCache::getShader(const Context *context,
33                                            Shader *shader,
34                                            const ShCompileOptions &compileOptions,
35                                            const ShCompilerInstance &compilerInstance,
36                                            const egl::BlobCache::Key &shaderHash)
37 {
38     // If caching is effectively disabled, don't bother calculating the hash.
39     if (!mBlobCache.isCachingEnabled())
40     {
41         return angle::Result::Incomplete;
42     }
43 
44     angle::MemoryBuffer uncompressedData;
45     switch (mBlobCache.getAndDecompress(context->getScratchBuffer(), shaderHash, &uncompressedData))
46     {
47         case egl::BlobCache::GetAndDecompressResult::DecompressFailure:
48             ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
49                                "Error decompressing shader binary data from cache.");
50             return angle::Result::Incomplete;
51 
52         case egl::BlobCache::GetAndDecompressResult::NotFound:
53             return angle::Result::Incomplete;
54 
55         case egl::BlobCache::GetAndDecompressResult::GetSuccess:
56             angle::Result result = shader->loadBinary(context, uncompressedData.data(),
57                                                       static_cast<int>(uncompressedData.size()));
58 
59             {
60                 std::scoped_lock<std::mutex> lock(mHistogramMutex);
61                 ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.ShaderCache.LoadBinarySuccess",
62                                         result == angle::Result::Continue);
63             }
64             ANGLE_TRY(result);
65 
66             if (result == angle::Result::Continue)
67                 return angle::Result::Continue;
68 
69             // Cache load failed, evict.
70             ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
71                                "Failed to load shader binary from cache.");
72             mBlobCache.remove(shaderHash);
73             return angle::Result::Incomplete;
74     }
75 
76     UNREACHABLE();
77     return angle::Result::Incomplete;
78 }
79 
putShader(const Context * context,const egl::BlobCache::Key & shaderHash,const Shader * shader)80 angle::Result MemoryShaderCache::putShader(const Context *context,
81                                            const egl::BlobCache::Key &shaderHash,
82                                            const Shader *shader)
83 {
84     // If caching is effectively disabled, don't bother serializing the shader.
85     if (!mBlobCache.isCachingEnabled())
86     {
87         return angle::Result::Incomplete;
88     }
89 
90     angle::MemoryBuffer serializedShader;
91     ANGLE_TRY(shader->serialize(nullptr, &serializedShader));
92 
93     size_t compressedSize;
94     if (!mBlobCache.compressAndPut(shaderHash, std::move(serializedShader), &compressedSize))
95     {
96         ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
97                            "Error compressing shader binary data for insertion into cache.");
98         return angle::Result::Incomplete;
99     }
100 
101     {
102         std::scoped_lock<std::mutex> lock(mHistogramMutex);
103         ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ShaderCache.ShaderBinarySizeBytes",
104                                static_cast<int>(compressedSize));
105     }
106 
107     return angle::Result::Continue;
108 }
109 
clear()110 void MemoryShaderCache::clear()
111 {
112     mBlobCache.clear();
113 }
114 
maxSize() const115 size_t MemoryShaderCache::maxSize() const
116 {
117     return mBlobCache.maxSize();
118 }
119 
120 }  // namespace gl
121