1 // Copyright (C) 2021 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "ShaderCache.h"
16 
17 #include "aemu/base/MruCache.h"
18 #include <string.h>
19 #include <cstdio>
20 
21 #include <map>
22 #include <vector>
23 
24 namespace {
25     using BlobCacheType = std::vector<uint8_t>;
26 
27     template <class K, class V>
28     class CacheObserver : android::base::MruCache<K, V>::MruCacheObserver {
29     public:
30         int count = 0;
CacheObserver(android::base::MruCache<K,V> * cacheReference)31         CacheObserver(android::base::MruCache<K, V>* cacheReference) {
32             mCacheRef = cacheReference;
33             cacheReference->setObserver(this);
34         }
35 
cacheChanged()36         void cacheChanged() override {
37             // TODO: This will dictate when we flatten the cache.
38         }
39 
40     private:
41         android::base::MruCache<K, V>* mCacheRef;
42     };
43 
44     template <class K, class V>
45     class CacheFlattener : public android::base::MruCache<K, V>::CacheFlattener {
46         using MruCache = std::map<typename android::base::MruCache<K, V>::template EntryWithSize<K>,
47             typename android::base::MruCache<K, V>::template EntryWithSize<V>>;
48 
49     public:
handleFlatten(MruCache & mCache,void * buf,size_t bufSize)50         void handleFlatten(MruCache &mCache, void* buf, size_t bufSize) {
51             // TODO: This will handle the actual serialization.
52         }
53     };
54 
55     CacheFlattener<BlobCacheType, BlobCacheType> testFlattener;
56     // 3200 is ~32MB of shaders, very rough estimate.
57     android::base::MruCache<BlobCacheType, BlobCacheType> mruCache(3200, &testFlattener);
58     CacheObserver<BlobCacheType, BlobCacheType> sss(&mruCache);
59 }
60 
SetBlob(const void * key,EGLsizeiANDROID keySize,const void * value,EGLsizeiANDROID valueSize)61 void SetBlob(const void* key, EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize) {
62     std::vector<uint8_t> keyVec(keySize);
63     memcpy(keyVec.data(), key, keySize);
64 
65     std::vector<uint8_t> valueVec(valueSize);
66     memcpy(valueVec.data(), value, valueSize);
67 
68     mruCache.put(keyVec, keySize, std::move(valueVec), valueSize);
69 }
70 
GetBlob(const void * key,EGLsizeiANDROID keySize,void * value,EGLsizeiANDROID valueSize)71 EGLsizeiANDROID GetBlob(const void* key, EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize) {
72     std::vector<uint8_t> keyVec(keySize);
73     memcpy(keyVec.data(), key, keySize);
74 
75     const std::vector<uint8_t> *result;
76     auto found = mruCache.get(keyVec, &result);
77 
78     if (!found) {
79         return 0;
80     }
81 
82     if (result->size() <= static_cast<size_t>(valueSize)) {
83         memcpy(value, result->data(), result->size());
84     }
85 
86     // If the size provided was too small, return the right size regardless.
87     return result->size();
88 }
89