• 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 <anglebase/sha1.h>
17 #include "common/MemoryBuffer.h"
18 #include "common/hash_utils.h"
19 #include "libANGLE/Error.h"
20 #include "libANGLE/SizedMRUCache.h"
21 
22 namespace gl
23 {
24 class Context;
25 }  // namespace gl
26 
27 namespace egl
28 {
29 // 160-bit SHA-1 hash key used for hasing a program.  BlobCache opts in using fixed keys for
30 // simplicity and efficiency.
31 static constexpr size_t kBlobCacheKeyLength = angle::base::kSHA1Length;
32 using BlobCacheKey                          = std::array<uint8_t, kBlobCacheKeyLength>;
33 }  // namespace egl
34 
35 namespace std
36 {
37 template <>
38 struct hash<egl::BlobCacheKey>
39 {
40     // Simple routine to hash four ints.
41     size_t operator()(const egl::BlobCacheKey &key) const
42     {
43         return angle::ComputeGenericHash(key.data(), key.size());
44     }
45 };
46 }  // namespace std
47 
48 namespace egl
49 {
50 
51 bool CompressBlobCacheData(const size_t cacheSize,
52                            const uint8_t *cacheData,
53                            angle::MemoryBuffer *compressedData);
54 bool DecompressBlobCacheData(const uint8_t *compressedData,
55                              const size_t compressedSize,
56                              angle::MemoryBuffer *uncompressedData);
57 
58 class BlobCache final : angle::NonCopyable
59 {
60   public:
61     // 160-bit SHA-1 hash key used for hasing a program.  BlobCache opts in using fixed keys for
62     // simplicity and efficiency.
63     static constexpr size_t kKeyLength = kBlobCacheKeyLength;
64     using Key                          = BlobCacheKey;
65     class Value
66     {
67       public:
68         Value() : mPtr(nullptr), mSize(0) {}
69         Value(const uint8_t *ptr, size_t sz) : mPtr(ptr), mSize(sz) {}
70 
71         // A very basic struct to hold the pointer and size together.  The objects of this class
72         // don't own the memory.
73         const uint8_t *data() { return mPtr; }
74         size_t size() { return mSize; }
75 
76         const uint8_t &operator[](size_t pos) const
77         {
78             ASSERT(pos < mSize);
79             return mPtr[pos];
80         }
81 
82       private:
83         const uint8_t *mPtr;
84         size_t mSize;
85     };
86     enum class CacheSource
87     {
88         Memory,
89         Disk,
90     };
91 
92     explicit BlobCache(size_t maxCacheSizeBytes);
93     ~BlobCache();
94 
95     // Store a key-blob pair in the cache.  If application callbacks are set, the application cache
96     // will be used.  Otherwise the value is cached in this object.
97     void put(const BlobCache::Key &key, angle::MemoryBuffer &&value);
98 
99     // Store a key-blob pair in the application cache, only if application callbacks are set.
100     void putApplication(const BlobCache::Key &key, const angle::MemoryBuffer &value);
101 
102     // Store a key-blob pair in the cache without making callbacks to the application.  This is used
103     // to repopulate this object's cache on startup without generating callback calls.
104     void populate(const BlobCache::Key &key,
105                   angle::MemoryBuffer &&value,
106                   CacheSource source = CacheSource::Disk);
107 
108     // Check if the cache contains the blob corresponding to this key.  If application callbacks are
109     // set, those will be used.  Otherwise they key is looked up in this object's cache.
110     ANGLE_NO_DISCARD bool get(angle::ScratchBuffer *scratchBuffer,
111                               const BlobCache::Key &key,
112                               BlobCache::Value *valueOut,
113                               size_t *bufferSizeOut);
114 
115     // For querying the contents of the cache.
116     ANGLE_NO_DISCARD bool getAt(size_t index,
117                                 const BlobCache::Key **keyOut,
118                                 BlobCache::Value *valueOut);
119 
120     // Evict a blob from the binary cache.
121     void remove(const BlobCache::Key &key);
122 
123     // Empty the cache.
124     void clear() { mBlobCache.clear(); }
125 
126     // Resize the cache. Discards current contents.
127     void resize(size_t maxCacheSizeBytes) { mBlobCache.resize(maxCacheSizeBytes); }
128 
129     // Returns the number of entries in the cache.
130     size_t entryCount() const { return mBlobCache.entryCount(); }
131 
132     // Reduces the current cache size and returns the number of bytes freed.
133     size_t trim(size_t limit) { return mBlobCache.shrinkToSize(limit); }
134 
135     // Returns the current cache size in bytes.
136     size_t size() const { return mBlobCache.size(); }
137 
138     // Returns whether the cache is empty
139     bool empty() const { return mBlobCache.empty(); }
140 
141     // Returns the maximum cache size in bytes.
142     size_t maxSize() const { return mBlobCache.maxSize(); }
143 
144     void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
145 
146     bool areBlobCacheFuncsSet() const;
147 
148     bool isCachingEnabled() const { return areBlobCacheFuncsSet() || maxSize() > 0; }
149 
150   private:
151     // This internal cache is used only if the application is not providing caching callbacks
152     using CacheEntry = std::pair<angle::MemoryBuffer, CacheSource>;
153 
154     std::mutex mBlobCacheMutex;
155     angle::SizedMRUCache<BlobCache::Key, CacheEntry> mBlobCache;
156 
157     EGLSetBlobFuncANDROID mSetBlobFunc;
158     EGLGetBlobFuncANDROID mGetBlobFunc;
159 };
160 
161 }  // namespace egl
162 
163 #endif  // LIBANGLE_MEMORY_PROGRAM_CACHE_H_
164