xref: /aosp_15_r20/external/angle/src/libANGLE/BlobCache.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2018 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 // BlobCache: Stores compiled and linked programs 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 #ifndef LIBANGLE_BLOB_CACHE_H_
11*8975f5c5SAndroid Build Coastguard Worker #define LIBANGLE_BLOB_CACHE_H_
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker #include <array>
14*8975f5c5SAndroid Build Coastguard Worker #include <cstring>
15*8975f5c5SAndroid Build Coastguard Worker 
16*8975f5c5SAndroid Build Coastguard Worker #include "common/SimpleMutex.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Error.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/SizedMRUCache.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/angletypes.h"
20*8975f5c5SAndroid Build Coastguard Worker 
21*8975f5c5SAndroid Build Coastguard Worker namespace gl
22*8975f5c5SAndroid Build Coastguard Worker {
23*8975f5c5SAndroid Build Coastguard Worker class Context;
24*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
25*8975f5c5SAndroid Build Coastguard Worker 
26*8975f5c5SAndroid Build Coastguard Worker namespace egl
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker 
29*8975f5c5SAndroid Build Coastguard Worker // Used by MemoryProgramCache and MemoryShaderCache, this result indicates whether program/shader
30*8975f5c5SAndroid Build Coastguard Worker // cache load from blob was successful.
31*8975f5c5SAndroid Build Coastguard Worker enum class CacheGetResult
32*8975f5c5SAndroid Build Coastguard Worker {
33*8975f5c5SAndroid Build Coastguard Worker     // Binary blob was found and is valid
34*8975f5c5SAndroid Build Coastguard Worker     Success,
35*8975f5c5SAndroid Build Coastguard Worker     // Binary blob was not found
36*8975f5c5SAndroid Build Coastguard Worker     NotFound,
37*8975f5c5SAndroid Build Coastguard Worker     // Binary blob was found, but was rejected due to errors (corruption, version mismatch, etc)
38*8975f5c5SAndroid Build Coastguard Worker     Rejected,
39*8975f5c5SAndroid Build Coastguard Worker };
40*8975f5c5SAndroid Build Coastguard Worker 
41*8975f5c5SAndroid Build Coastguard Worker class BlobCache final : angle::NonCopyable
42*8975f5c5SAndroid Build Coastguard Worker {
43*8975f5c5SAndroid Build Coastguard Worker   public:
44*8975f5c5SAndroid Build Coastguard Worker     // 160-bit SHA-1 hash key used for hasing a program.  BlobCache opts in using fixed keys for
45*8975f5c5SAndroid Build Coastguard Worker     // simplicity and efficiency.
46*8975f5c5SAndroid Build Coastguard Worker     static constexpr size_t kKeyLength = angle::kBlobCacheKeyLength;
47*8975f5c5SAndroid Build Coastguard Worker     using Key                          = angle::BlobCacheKey;
48*8975f5c5SAndroid Build Coastguard Worker     using Value                        = angle::BlobCacheValue;
49*8975f5c5SAndroid Build Coastguard Worker     enum class CacheSource
50*8975f5c5SAndroid Build Coastguard Worker     {
51*8975f5c5SAndroid Build Coastguard Worker         Memory,
52*8975f5c5SAndroid Build Coastguard Worker         Disk,
53*8975f5c5SAndroid Build Coastguard Worker     };
54*8975f5c5SAndroid Build Coastguard Worker 
55*8975f5c5SAndroid Build Coastguard Worker     explicit BlobCache(size_t maxCacheSizeBytes);
56*8975f5c5SAndroid Build Coastguard Worker     ~BlobCache();
57*8975f5c5SAndroid Build Coastguard Worker 
58*8975f5c5SAndroid Build Coastguard Worker     // Store a key-blob pair in the cache.  If application callbacks are set, the application cache
59*8975f5c5SAndroid Build Coastguard Worker     // will be used.  Otherwise the value is cached in this object.
60*8975f5c5SAndroid Build Coastguard Worker     void put(const gl::Context *context, const BlobCache::Key &key, angle::MemoryBuffer &&value);
61*8975f5c5SAndroid Build Coastguard Worker 
62*8975f5c5SAndroid Build Coastguard Worker     // Store a key-blob pair in the cache, but compress the blob before insertion. Returns false if
63*8975f5c5SAndroid Build Coastguard Worker     // compression fails, returns true otherwise.
64*8975f5c5SAndroid Build Coastguard Worker     bool compressAndPut(const gl::Context *context,
65*8975f5c5SAndroid Build Coastguard Worker                         const BlobCache::Key &key,
66*8975f5c5SAndroid Build Coastguard Worker                         angle::MemoryBuffer &&uncompressedValue,
67*8975f5c5SAndroid Build Coastguard Worker                         size_t *compressedSize);
68*8975f5c5SAndroid Build Coastguard Worker 
69*8975f5c5SAndroid Build Coastguard Worker     // Store a key-blob pair in the application cache, only if application callbacks are set.
70*8975f5c5SAndroid Build Coastguard Worker     void putApplication(const gl::Context *context,
71*8975f5c5SAndroid Build Coastguard Worker                         const BlobCache::Key &key,
72*8975f5c5SAndroid Build Coastguard Worker                         const angle::MemoryBuffer &value);
73*8975f5c5SAndroid Build Coastguard Worker 
74*8975f5c5SAndroid Build Coastguard Worker     // Store a key-blob pair in the cache without making callbacks to the application.  This is used
75*8975f5c5SAndroid Build Coastguard Worker     // to repopulate this object's cache on startup without generating callback calls.
76*8975f5c5SAndroid Build Coastguard Worker     void populate(const BlobCache::Key &key,
77*8975f5c5SAndroid Build Coastguard Worker                   angle::MemoryBuffer &&value,
78*8975f5c5SAndroid Build Coastguard Worker                   CacheSource source = CacheSource::Disk);
79*8975f5c5SAndroid Build Coastguard Worker 
80*8975f5c5SAndroid Build Coastguard Worker     // Check if the cache contains the blob corresponding to this key.  If application callbacks are
81*8975f5c5SAndroid Build Coastguard Worker     // set, those will be used.  Otherwise they key is looked up in this object's cache.
82*8975f5c5SAndroid Build Coastguard Worker     [[nodiscard]] bool get(const gl::Context *context,
83*8975f5c5SAndroid Build Coastguard Worker                            angle::ScratchBuffer *scratchBuffer,
84*8975f5c5SAndroid Build Coastguard Worker                            const BlobCache::Key &key,
85*8975f5c5SAndroid Build Coastguard Worker                            BlobCache::Value *valueOut);
86*8975f5c5SAndroid Build Coastguard Worker 
87*8975f5c5SAndroid Build Coastguard Worker     // For querying the contents of the cache.
88*8975f5c5SAndroid Build Coastguard Worker     [[nodiscard]] bool getAt(size_t index,
89*8975f5c5SAndroid Build Coastguard Worker                              const BlobCache::Key **keyOut,
90*8975f5c5SAndroid Build Coastguard Worker                              BlobCache::Value *valueOut);
91*8975f5c5SAndroid Build Coastguard Worker 
92*8975f5c5SAndroid Build Coastguard Worker     enum class GetAndDecompressResult
93*8975f5c5SAndroid Build Coastguard Worker     {
94*8975f5c5SAndroid Build Coastguard Worker         Success,
95*8975f5c5SAndroid Build Coastguard Worker         NotFound,
96*8975f5c5SAndroid Build Coastguard Worker         DecompressFailure,
97*8975f5c5SAndroid Build Coastguard Worker     };
98*8975f5c5SAndroid Build Coastguard Worker     [[nodiscard]] GetAndDecompressResult getAndDecompress(
99*8975f5c5SAndroid Build Coastguard Worker         const gl::Context *context,
100*8975f5c5SAndroid Build Coastguard Worker         angle::ScratchBuffer *scratchBuffer,
101*8975f5c5SAndroid Build Coastguard Worker         const BlobCache::Key &key,
102*8975f5c5SAndroid Build Coastguard Worker         size_t maxUncompressedDataSize,
103*8975f5c5SAndroid Build Coastguard Worker         angle::MemoryBuffer *uncompressedValueOut);
104*8975f5c5SAndroid Build Coastguard Worker 
105*8975f5c5SAndroid Build Coastguard Worker     // Evict a blob from the binary cache.
106*8975f5c5SAndroid Build Coastguard Worker     void remove(const BlobCache::Key &key);
107*8975f5c5SAndroid Build Coastguard Worker 
108*8975f5c5SAndroid Build Coastguard Worker     // Empty the cache.
clear()109*8975f5c5SAndroid Build Coastguard Worker     void clear() { mBlobCache.clear(); }
110*8975f5c5SAndroid Build Coastguard Worker 
111*8975f5c5SAndroid Build Coastguard Worker     // Resize the cache. Discards current contents.
resize(size_t maxCacheSizeBytes)112*8975f5c5SAndroid Build Coastguard Worker     void resize(size_t maxCacheSizeBytes) { mBlobCache.resize(maxCacheSizeBytes); }
113*8975f5c5SAndroid Build Coastguard Worker 
114*8975f5c5SAndroid Build Coastguard Worker     // Returns the number of entries in the cache.
entryCount()115*8975f5c5SAndroid Build Coastguard Worker     size_t entryCount() const { return mBlobCache.entryCount(); }
116*8975f5c5SAndroid Build Coastguard Worker 
117*8975f5c5SAndroid Build Coastguard Worker     // Reduces the current cache size and returns the number of bytes freed.
trim(size_t limit)118*8975f5c5SAndroid Build Coastguard Worker     size_t trim(size_t limit) { return mBlobCache.shrinkToSize(limit); }
119*8975f5c5SAndroid Build Coastguard Worker 
120*8975f5c5SAndroid Build Coastguard Worker     // Returns the current cache size in bytes.
size()121*8975f5c5SAndroid Build Coastguard Worker     size_t size() const { return mBlobCache.size(); }
122*8975f5c5SAndroid Build Coastguard Worker 
123*8975f5c5SAndroid Build Coastguard Worker     // Returns whether the cache is empty
empty()124*8975f5c5SAndroid Build Coastguard Worker     bool empty() const { return mBlobCache.empty(); }
125*8975f5c5SAndroid Build Coastguard Worker 
126*8975f5c5SAndroid Build Coastguard Worker     // Returns the maximum cache size in bytes.
maxSize()127*8975f5c5SAndroid Build Coastguard Worker     size_t maxSize() const { return mBlobCache.maxSize(); }
128*8975f5c5SAndroid Build Coastguard Worker 
129*8975f5c5SAndroid Build Coastguard Worker     void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
130*8975f5c5SAndroid Build Coastguard Worker 
131*8975f5c5SAndroid Build Coastguard Worker     bool areBlobCacheFuncsSet() const;
132*8975f5c5SAndroid Build Coastguard Worker 
133*8975f5c5SAndroid Build Coastguard Worker     bool isCachingEnabled(const gl::Context *context) const;
134*8975f5c5SAndroid Build Coastguard Worker 
getMutex()135*8975f5c5SAndroid Build Coastguard Worker     angle::SimpleMutex &getMutex() { return mBlobCacheMutex; }
136*8975f5c5SAndroid Build Coastguard Worker 
137*8975f5c5SAndroid Build Coastguard Worker   private:
138*8975f5c5SAndroid Build Coastguard Worker     size_t callBlobGetCallback(const gl::Context *context,
139*8975f5c5SAndroid Build Coastguard Worker                                const void *key,
140*8975f5c5SAndroid Build Coastguard Worker                                size_t keySize,
141*8975f5c5SAndroid Build Coastguard Worker                                void *value,
142*8975f5c5SAndroid Build Coastguard Worker                                size_t valueSize);
143*8975f5c5SAndroid Build Coastguard Worker 
144*8975f5c5SAndroid Build Coastguard Worker     // This internal cache is used only if the application is not providing caching callbacks
145*8975f5c5SAndroid Build Coastguard Worker     using CacheEntry = std::pair<angle::MemoryBuffer, CacheSource>;
146*8975f5c5SAndroid Build Coastguard Worker 
147*8975f5c5SAndroid Build Coastguard Worker     mutable angle::SimpleMutex mBlobCacheMutex;
148*8975f5c5SAndroid Build Coastguard Worker     angle::SizedMRUCache<BlobCache::Key, CacheEntry> mBlobCache;
149*8975f5c5SAndroid Build Coastguard Worker 
150*8975f5c5SAndroid Build Coastguard Worker     EGLSetBlobFuncANDROID mSetBlobFunc;
151*8975f5c5SAndroid Build Coastguard Worker     EGLGetBlobFuncANDROID mGetBlobFunc;
152*8975f5c5SAndroid Build Coastguard Worker };
153*8975f5c5SAndroid Build Coastguard Worker 
154*8975f5c5SAndroid Build Coastguard Worker }  // namespace egl
155*8975f5c5SAndroid Build Coastguard Worker 
156*8975f5c5SAndroid Build Coastguard Worker #endif  // LIBANGLE_MEMORY_PROGRAM_CACHE_H_
157