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