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