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