1 /* 2 * Copyright 2022 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef skgpu_graphite_ResourceCache_DEFINED 9 #define skgpu_graphite_ResourceCache_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "include/private/base/SkMutex.h" 13 #include "include/private/base/SkTArray.h" 14 #include "src/base/SkTDPQueue.h" 15 #include "src/core/SkTHash.h" 16 #include "src/core/SkTMultiMap.h" 17 #include "src/gpu/graphite/ResourceTypes.h" 18 19 #include <vector> 20 21 namespace skgpu { 22 class SingleOwner; 23 } 24 25 namespace skgpu::graphite { 26 27 class GraphiteResourceKey; 28 class Resource; 29 30 class ResourceCache : public SkRefCnt { 31 public: 32 static sk_sp<ResourceCache> Make(SingleOwner*); 33 ~ResourceCache() override; 34 35 ResourceCache(const ResourceCache&) = delete; 36 ResourceCache(ResourceCache&&) = delete; 37 ResourceCache& operator=(const ResourceCache&) = delete; 38 ResourceCache& operator=(ResourceCache&&) = delete; 39 40 // Returns the number of resources. getResourceCount()41 int getResourceCount() const { 42 return fPurgeableQueue.count() + fNonpurgeableResources.size(); 43 } 44 45 void insertResource(Resource*); 46 47 // Find a resource that matches a key. 48 Resource* findAndRefResource(const GraphiteResourceKey& key, skgpu::Budgeted); 49 50 // This is a thread safe call. If it fails the ResourceCache is no longer valid and the 51 // Resource should clean itself up if it is the last ref. 52 bool returnResource(Resource*, LastRemovedRef); 53 54 // Called by the ResourceProvider when it is dropping its ref to the ResourceCache. After this 55 // is called no more Resources can be returned to the ResourceCache (besides those already in 56 // the return queue). Also no new Resources can be retrieved from the ResourceCache. 57 void shutdown(); 58 59 #if GRAPHITE_TEST_UTILS forceProcessReturnedResources()60 void forceProcessReturnedResources() { this->processReturnedResources(); } 61 62 // Returns the numbers of Resources that can currently be found in the cache. This includes all 63 // shared Resources and all non-shareable resources that have been returned to the cache. 64 int numFindableResources() const; 65 #endif 66 67 private: 68 ResourceCache(SingleOwner*); 69 70 // All these private functions are not meant to be thread safe. We don't check for is single 71 // owner in them as we assume that has already been checked by the public api calls. 72 void refAndMakeResourceMRU(Resource*); 73 void addToNonpurgeableArray(Resource* resource); 74 void removeFromNonpurgeableArray(Resource* resource); 75 void removeFromPurgeableQueue(Resource* resource); 76 77 void processReturnedResources(); 78 void returnResourceToCache(Resource*, LastRemovedRef); 79 80 uint32_t getNextTimestamp(); 81 82 bool inPurgeableQueue(Resource*) const; 83 84 #ifdef SK_DEBUG 85 bool isInCache(const Resource* r) const; 86 void validate() const; 87 #else validate()88 void validate() const {} 89 #endif 90 91 struct MapTraits { 92 static const GraphiteResourceKey& GetKey(const Resource& r); 93 94 static uint32_t Hash(const GraphiteResourceKey& key); OnFreeMapTraits95 static void OnFree(Resource*) {} 96 }; 97 typedef SkTMultiMap<Resource, GraphiteResourceKey, MapTraits> ResourceMap; 98 99 static bool CompareTimestamp(Resource* const& a, Resource* const& b); 100 static int* AccessResourceIndex(Resource* const& res); 101 102 using PurgeableQueue = SkTDPQueue<Resource*, CompareTimestamp, AccessResourceIndex>; 103 using ResourceArray = SkTDArray<Resource*>; 104 105 // Whenever a resource is added to the cache or the result of a cache lookup, fTimestamp is 106 // assigned as the resource's timestamp and then incremented. fPurgeableQueue orders the 107 // purgeable resources by this value, and thus is used to purge resources in LRU order. 108 uint32_t fTimestamp = 0; 109 PurgeableQueue fPurgeableQueue; 110 ResourceArray fNonpurgeableResources; 111 112 SkDEBUGCODE(int fCount = 0;) 113 114 ResourceMap fResourceMap; 115 116 SingleOwner* fSingleOwner = nullptr; 117 118 bool fIsShutdown = false; 119 120 SkMutex fReturnMutex; 121 using ReturnQueue = std::vector<std::pair<Resource*, LastRemovedRef>>; 122 ReturnQueue fReturnQueue SK_GUARDED_BY(fReturnMutex); 123 }; 124 125 } // namespace skgpu::graphite 126 127 #endif // skgpu_graphite_ResourceCache_DEFINED 128