• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 BlobCache::Key &key,
65                         angle::MemoryBuffer &&uncompressedValue,
66                         size_t *compressedSize);
67 
68     // Store a key-blob pair in the application cache, only if application callbacks are set.
69     void putApplication(const BlobCache::Key &key, const angle::MemoryBuffer &value);
70 
71     // Store a key-blob pair in the cache without making callbacks to the application.  This is used
72     // to repopulate this object's cache on startup without generating callback calls.
73     void populate(const BlobCache::Key &key,
74                   angle::MemoryBuffer &&value,
75                   CacheSource source = CacheSource::Disk);
76 
77     // Check if the cache contains the blob corresponding to this key.  If application callbacks are
78     // set, those will be used.  Otherwise they key is looked up in this object's cache.
79     [[nodiscard]] bool get(angle::ScratchBuffer *scratchBuffer,
80                            const BlobCache::Key &key,
81                            BlobCache::Value *valueOut);
82 
83     // For querying the contents of the cache.
84     [[nodiscard]] bool getAt(size_t index,
85                              const BlobCache::Key **keyOut,
86                              BlobCache::Value *valueOut);
87 
88     enum class GetAndDecompressResult
89     {
90         Success,
91         NotFound,
92         DecompressFailure,
93     };
94     [[nodiscard]] GetAndDecompressResult getAndDecompress(
95         angle::ScratchBuffer *scratchBuffer,
96         const BlobCache::Key &key,
97         size_t maxUncompressedDataSize,
98         angle::MemoryBuffer *uncompressedValueOut);
99 
100     // Evict a blob from the binary cache.
101     void remove(const BlobCache::Key &key);
102 
103     // Empty the cache.
clear()104     void clear() { mBlobCache.clear(); }
105 
106     // Resize the cache. Discards current contents.
resize(size_t maxCacheSizeBytes)107     void resize(size_t maxCacheSizeBytes) { mBlobCache.resize(maxCacheSizeBytes); }
108 
109     // Returns the number of entries in the cache.
entryCount()110     size_t entryCount() const { return mBlobCache.entryCount(); }
111 
112     // Reduces the current cache size and returns the number of bytes freed.
trim(size_t limit)113     size_t trim(size_t limit) { return mBlobCache.shrinkToSize(limit); }
114 
115     // Returns the current cache size in bytes.
size()116     size_t size() const { return mBlobCache.size(); }
117 
118     // Returns whether the cache is empty
empty()119     bool empty() const { return mBlobCache.empty(); }
120 
121     // Returns the maximum cache size in bytes.
maxSize()122     size_t maxSize() const { return mBlobCache.maxSize(); }
123 
124     void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
125 
126     bool areBlobCacheFuncsSet() const;
127 
isCachingEnabled()128     bool isCachingEnabled() const { return areBlobCacheFuncsSet() || maxSize() > 0; }
129 
getMutex()130     angle::SimpleMutex &getMutex() { return mBlobCacheMutex; }
131 
132   private:
133     // This internal cache is used only if the application is not providing caching callbacks
134     using CacheEntry = std::pair<angle::MemoryBuffer, CacheSource>;
135 
136     mutable angle::SimpleMutex mBlobCacheMutex;
137     angle::SizedMRUCache<BlobCache::Key, CacheEntry> mBlobCache;
138 
139     EGLSetBlobFuncANDROID mSetBlobFunc;
140     EGLGetBlobFuncANDROID mGetBlobFunc;
141 };
142 
143 }  // namespace egl
144 
145 #endif  // LIBANGLE_MEMORY_PROGRAM_CACHE_H_
146