1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2022 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // MemoryShaderCache: Stores compiled shader in memory so they don't
7*8975f5c5SAndroid Build Coastguard Worker // always have to be re-compiled. Can be used in conjunction with the platform
8*8975f5c5SAndroid Build Coastguard Worker // layer to warm up the cache from disk.
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/MemoryShaderCache.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include <GLSLANG/ShaderVars.h>
13*8975f5c5SAndroid Build Coastguard Worker #include <anglebase/sha1.h>
14*8975f5c5SAndroid Build Coastguard Worker
15*8975f5c5SAndroid Build Coastguard Worker #include "common/BinaryStream.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Compiler.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Debug.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Uniform.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/histogram_macros.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ShaderImpl.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "platform/PlatformMethods.h"
24*8975f5c5SAndroid Build Coastguard Worker
25*8975f5c5SAndroid Build Coastguard Worker namespace gl
26*8975f5c5SAndroid Build Coastguard Worker {
27*8975f5c5SAndroid Build Coastguard Worker
28*8975f5c5SAndroid Build Coastguard Worker namespace
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker // Limit decompressed programs to 5MB. If they're larger then this there is a good chance the data
31*8975f5c5SAndroid Build Coastguard Worker // is not what we expect. This limits the amount of memory we will allocate based on a binary blob
32*8975f5c5SAndroid Build Coastguard Worker // we believe is compressed data.
33*8975f5c5SAndroid Build Coastguard Worker static constexpr size_t kMaxUncompressedShaderSize = 5 * 1024 * 1024;
34*8975f5c5SAndroid Build Coastguard Worker } // namespace
35*8975f5c5SAndroid Build Coastguard Worker
MemoryShaderCache(egl::BlobCache & blobCache)36*8975f5c5SAndroid Build Coastguard Worker MemoryShaderCache::MemoryShaderCache(egl::BlobCache &blobCache) : mBlobCache(blobCache) {}
37*8975f5c5SAndroid Build Coastguard Worker
~MemoryShaderCache()38*8975f5c5SAndroid Build Coastguard Worker MemoryShaderCache::~MemoryShaderCache() {}
39*8975f5c5SAndroid Build Coastguard Worker
getShader(const Context * context,Shader * shader,const egl::BlobCache::Key & shaderHash,angle::JobResultExpectancy resultExpectancy)40*8975f5c5SAndroid Build Coastguard Worker egl::CacheGetResult MemoryShaderCache::getShader(const Context *context,
41*8975f5c5SAndroid Build Coastguard Worker Shader *shader,
42*8975f5c5SAndroid Build Coastguard Worker const egl::BlobCache::Key &shaderHash,
43*8975f5c5SAndroid Build Coastguard Worker angle::JobResultExpectancy resultExpectancy)
44*8975f5c5SAndroid Build Coastguard Worker {
45*8975f5c5SAndroid Build Coastguard Worker // If caching is effectively disabled, don't bother calculating the hash.
46*8975f5c5SAndroid Build Coastguard Worker if (!mBlobCache.isCachingEnabled(context))
47*8975f5c5SAndroid Build Coastguard Worker {
48*8975f5c5SAndroid Build Coastguard Worker return egl::CacheGetResult::NotFound;
49*8975f5c5SAndroid Build Coastguard Worker }
50*8975f5c5SAndroid Build Coastguard Worker
51*8975f5c5SAndroid Build Coastguard Worker angle::MemoryBuffer uncompressedData;
52*8975f5c5SAndroid Build Coastguard Worker const egl::BlobCache::GetAndDecompressResult result =
53*8975f5c5SAndroid Build Coastguard Worker mBlobCache.getAndDecompress(context, context->getScratchBuffer(), shaderHash,
54*8975f5c5SAndroid Build Coastguard Worker kMaxUncompressedShaderSize, &uncompressedData);
55*8975f5c5SAndroid Build Coastguard Worker switch (result)
56*8975f5c5SAndroid Build Coastguard Worker {
57*8975f5c5SAndroid Build Coastguard Worker case egl::BlobCache::GetAndDecompressResult::DecompressFailure:
58*8975f5c5SAndroid Build Coastguard Worker ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
59*8975f5c5SAndroid Build Coastguard Worker "Error decompressing shader binary data from cache.");
60*8975f5c5SAndroid Build Coastguard Worker mBlobCache.remove(shaderHash);
61*8975f5c5SAndroid Build Coastguard Worker return egl::CacheGetResult::NotFound;
62*8975f5c5SAndroid Build Coastguard Worker
63*8975f5c5SAndroid Build Coastguard Worker case egl::BlobCache::GetAndDecompressResult::NotFound:
64*8975f5c5SAndroid Build Coastguard Worker return egl::CacheGetResult::NotFound;
65*8975f5c5SAndroid Build Coastguard Worker
66*8975f5c5SAndroid Build Coastguard Worker case egl::BlobCache::GetAndDecompressResult::Success:
67*8975f5c5SAndroid Build Coastguard Worker if (shader->loadBinary(context, uncompressedData.data(),
68*8975f5c5SAndroid Build Coastguard Worker static_cast<int>(uncompressedData.size()), resultExpectancy))
69*8975f5c5SAndroid Build Coastguard Worker {
70*8975f5c5SAndroid Build Coastguard Worker return egl::CacheGetResult::Success;
71*8975f5c5SAndroid Build Coastguard Worker }
72*8975f5c5SAndroid Build Coastguard Worker
73*8975f5c5SAndroid Build Coastguard Worker // Cache load failed, evict.
74*8975f5c5SAndroid Build Coastguard Worker ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
75*8975f5c5SAndroid Build Coastguard Worker "Failed to load shader binary from cache.");
76*8975f5c5SAndroid Build Coastguard Worker mBlobCache.remove(shaderHash);
77*8975f5c5SAndroid Build Coastguard Worker return egl::CacheGetResult::Rejected;
78*8975f5c5SAndroid Build Coastguard Worker }
79*8975f5c5SAndroid Build Coastguard Worker
80*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
81*8975f5c5SAndroid Build Coastguard Worker return egl::CacheGetResult::NotFound;
82*8975f5c5SAndroid Build Coastguard Worker }
83*8975f5c5SAndroid Build Coastguard Worker
putShader(const Context * context,const egl::BlobCache::Key & shaderHash,const Shader * shader)84*8975f5c5SAndroid Build Coastguard Worker angle::Result MemoryShaderCache::putShader(const Context *context,
85*8975f5c5SAndroid Build Coastguard Worker const egl::BlobCache::Key &shaderHash,
86*8975f5c5SAndroid Build Coastguard Worker const Shader *shader)
87*8975f5c5SAndroid Build Coastguard Worker {
88*8975f5c5SAndroid Build Coastguard Worker // If caching is effectively disabled, don't bother serializing the shader.
89*8975f5c5SAndroid Build Coastguard Worker if (!mBlobCache.isCachingEnabled(context))
90*8975f5c5SAndroid Build Coastguard Worker {
91*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
92*8975f5c5SAndroid Build Coastguard Worker }
93*8975f5c5SAndroid Build Coastguard Worker
94*8975f5c5SAndroid Build Coastguard Worker angle::MemoryBuffer serializedShader;
95*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(shader->serialize(nullptr, &serializedShader));
96*8975f5c5SAndroid Build Coastguard Worker
97*8975f5c5SAndroid Build Coastguard Worker size_t compressedSize;
98*8975f5c5SAndroid Build Coastguard Worker if (!mBlobCache.compressAndPut(context, shaderHash, std::move(serializedShader),
99*8975f5c5SAndroid Build Coastguard Worker &compressedSize))
100*8975f5c5SAndroid Build Coastguard Worker {
101*8975f5c5SAndroid Build Coastguard Worker ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
102*8975f5c5SAndroid Build Coastguard Worker "Error compressing shader binary data for insertion into cache.");
103*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
104*8975f5c5SAndroid Build Coastguard Worker }
105*8975f5c5SAndroid Build Coastguard Worker
106*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
107*8975f5c5SAndroid Build Coastguard Worker }
108*8975f5c5SAndroid Build Coastguard Worker
clear()109*8975f5c5SAndroid Build Coastguard Worker void MemoryShaderCache::clear()
110*8975f5c5SAndroid Build Coastguard Worker {
111*8975f5c5SAndroid Build Coastguard Worker mBlobCache.clear();
112*8975f5c5SAndroid Build Coastguard Worker }
113*8975f5c5SAndroid Build Coastguard Worker
maxSize() const114*8975f5c5SAndroid Build Coastguard Worker size_t MemoryShaderCache::maxSize() const
115*8975f5c5SAndroid Build Coastguard Worker {
116*8975f5c5SAndroid Build Coastguard Worker return mBlobCache.maxSize();
117*8975f5c5SAndroid Build Coastguard Worker }
118*8975f5c5SAndroid Build Coastguard Worker
119*8975f5c5SAndroid Build Coastguard Worker } // namespace gl
120