• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Dawn Authors
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 #ifndef DAWNNATIVE_PERSISTENTCACHE_H_
16 #define DAWNNATIVE_PERSISTENTCACHE_H_
17 
18 #include "dawn_native/Error.h"
19 
20 #include <mutex>
21 #include <vector>
22 
23 namespace dawn_platform {
24     class CachingInterface;
25 }
26 
27 namespace dawn_native {
28 
29     using PersistentCacheKey = std::vector<uint8_t>;
30 
31     struct ScopedCachedBlob {
32         std::unique_ptr<uint8_t[]> buffer;
33         size_t bufferSize = 0;
34     };
35 
36     class DeviceBase;
37 
38     enum class PersistentKeyType { Shader };
39 
40     // This class should always be thread-safe as it is used in Create*PipelineAsync() where it is
41     // called asynchronously.
42     // The thread-safety of any access to mCache (the function LoadData() and StoreData()) is
43     // protected by mMutex.
44     class PersistentCache {
45       public:
46         PersistentCache(DeviceBase* device);
47 
48         // Combines load/store operations into a single call.
49         // If the load was successful, a non-empty blob is returned to the caller.
50         // Else, the creation callback |createFn| gets invoked with a callback
51         // |doCache| to store the newly created blob back in the cache.
52         //
53         // Example usage:
54         //
55         // ScopedCachedBlob cachedBlob = {};
56         // DAWN_TRY_ASSIGN(cachedBlob, GetOrCreate(key, [&](auto doCache)) {
57         //      // Create a new blob to be stored
58         //      doCache(newBlobPtr, newBlobSize); // store
59         // }));
60         //
61         template <typename CreateFn>
GetOrCreate(const PersistentCacheKey & key,CreateFn && createFn)62         ResultOrError<ScopedCachedBlob> GetOrCreate(const PersistentCacheKey& key,
63                                                     CreateFn&& createFn) {
64             // Attempt to load an existing blob from the cache.
65             ScopedCachedBlob blob = LoadData(key);
66             if (blob.bufferSize > 0) {
67                 return std::move(blob);
68             }
69 
70             // Allow the caller to create a new blob to be stored for the given key.
71             DAWN_TRY(createFn([this, key](const void* value, size_t size) {
72                 this->StoreData(key, value, size);
73             }));
74 
75             return std::move(blob);
76         }
77 
78       private:
79         // PersistentCache impl
80         ScopedCachedBlob LoadData(const PersistentCacheKey& key);
81         void StoreData(const PersistentCacheKey& key, const void* value, size_t size);
82 
83         dawn_platform::CachingInterface* GetPlatformCache();
84 
85         DeviceBase* mDevice = nullptr;
86 
87         std::mutex mMutex;
88         dawn_platform::CachingInterface* mCache = nullptr;
89     };
90 }  // namespace dawn_native
91 
92 #endif  // DAWNNATIVE_PERSISTENTCACHE_H_
93