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