• Home
  • Raw
  • Download

Lines Matching full:resource

16 #include "src/gpu/graphite/Resource.h"
66 Resource* back = *(fNonpurgeableResources.end() - 1); in shutdown()
73 Resource* top = fPurgeableQueue.peek(); in shutdown()
82 void ResourceCache::insertResource(Resource* resource) { in insertResource() argument
84 SkASSERT(resource); in insertResource()
85 SkASSERT(!this->isInCache(resource)); in insertResource()
86 SkASSERT(!resource->wasDestroyed()); in insertResource()
87 SkASSERT(!resource->isPurgeable()); in insertResource()
88 SkASSERT(resource->key().isValid()); in insertResource()
91 SkASSERT(resource->ownership() == Ownership::kOwned); in insertResource()
95 // want to have them all returned before adding the budget for the new resource in case we need in insertResource()
96 // to purge things. However, if the new resource has a memory size of 0, then we just skip in insertResource()
97 // returning resources (which has overhead for each call) since the new resource won't be in insertResource()
99 if (resource->gpuMemorySize() > 0) { in insertResource()
103 resource->registerWithCache(sk_ref_sp(this)); in insertResource()
104 resource->refCache(); in insertResource()
108 this->setResourceTimestamp(resource, this->getNextTimestamp()); in insertResource()
109 resource->updateAccessTime(); in insertResource()
111 this->addToNonpurgeableArray(resource); in insertResource()
115 if (resource->key().shareable() == Shareable::kYes) { in insertResource()
116 fResourceMap.insert(resource->key(), resource); in insertResource()
119 if (resource->budgeted() == skgpu::Budgeted::kYes) { in insertResource()
120 fBudgetedBytes += resource->gpuMemorySize(); in insertResource()
126 Resource* ResourceCache::findAndRefResource(const GraphiteResourceKey& key, in findAndRefResource()
132 Resource* resource = fResourceMap.find(key); in findAndRefResource() local
133 if (!resource) { in findAndRefResource()
136 // So we only call it if we first failed to find a matching resource. in findAndRefResource()
138 resource = fResourceMap.find(key); in findAndRefResource()
141 if (resource) { in findAndRefResource()
143 SkASSERT(resource->budgeted() == skgpu::Budgeted::kYes); in findAndRefResource()
145 // If a resource is not shareable (i.e. scratch resource) then we remove it from the map in findAndRefResource()
147 fResourceMap.remove(key, resource); in findAndRefResource()
149 resource->makeUnbudgeted(); in findAndRefResource()
150 fBudgetedBytes -= resource->gpuMemorySize(); in findAndRefResource()
152 SkDEBUGCODE(resource->fNonShareableInCache = false;) in findAndRefResource()
157 this->refAndMakeResourceMRU(resource); in findAndRefResource()
163 // processReturnedResources, we delay calling it until now so we don't end up purging a resource in findAndRefResource()
173 return resource; in findAndRefResource()
176 void ResourceCache::refAndMakeResourceMRU(Resource* resource) { in refAndMakeResourceMRU() argument
177 SkASSERT(resource); in refAndMakeResourceMRU()
178 SkASSERT(this->isInCache(resource)); in refAndMakeResourceMRU()
180 if (this->inPurgeableQueue(resource)) { in refAndMakeResourceMRU()
182 this->removeFromPurgeableQueue(resource); in refAndMakeResourceMRU()
183 this->addToNonpurgeableArray(resource); in refAndMakeResourceMRU()
185 resource->initialUsageRef(); in refAndMakeResourceMRU()
187 this->setResourceTimestamp(resource, this->getNextTimestamp()); in refAndMakeResourceMRU()
191 bool ResourceCache::returnResource(Resource* resource, LastRemovedRef removedRef) { in returnResource() argument
199 SkASSERT(resource); in returnResource()
201 // When a non-shareable resource's CB and Usage refs are both zero, give it a chance prepare in returnResource()
204 if (resource->shouldDeleteASAP() == Resource::DeleteASAP::kNo && in returnResource()
205 resource->key().shareable() == Shareable::kNo && in returnResource()
207 resource->prepareForReturnToCache([resource] { resource->initialUsageRef(); }); in returnResource()
208 // Check if resource was re-ref'ed. In that case exit without adding to the queue. in returnResource()
209 if (resource->hasUsageRef()) { in returnResource()
214 // We only allow one instance of a Resource to be in the return queue at a time. We do this so in returnResource()
218 // decided to have multiple instances of a Resource. Even if an earlier returned instance of a in returnResource()
219 // Resource triggers that Resource to get purged from the cache, the Resource itself wouldn't in returnResource()
221 if (*resource->accessReturnIndex() >= 0) { in returnResource()
222 // If the resource is already in the return queue we promote the LastRemovedRef to be in returnResource()
225 SkASSERT(*resource->accessReturnIndex() < (int)fReturnQueue.size()); in returnResource()
226 fReturnQueue[*resource->accessReturnIndex()].second = removedRef; in returnResource()
232 SkASSERT(nextResource.first != resource); in returnResource()
236 fReturnQueue.push_back(std::make_pair(resource, removedRef)); in returnResource()
237 *resource->accessReturnIndex() = fReturnQueue.size() - 1; in returnResource()
238 resource->refCache(); in returnResource()
244 // so that we can drop the fReturnMutex. When we process a Resource we may need to grab its in processReturnedResources()
245 // UnrefMutex. This could cause a deadlock if on another thread the Resource has the UnrefMutex in processReturnedResources()
256 auto [resource, ref] = nextResource; in processReturnedResources()
257 SkASSERT(*resource->accessReturnIndex() >= 0); in processReturnedResources()
258 *resource->accessReturnIndex() = -1; in processReturnedResources()
270 auto [resource, ref] = nextResource; in processReturnedResources()
271 // We need this check here to handle the following scenario. A Resource is sitting in the in processReturnedResources()
272 // ReturnQueue (say from kUsage last ref) and the Resource still has a command buffer ref in processReturnedResources()
275 // thread. The Resource cannot be added to the ReturnQueue since the lock is held. Back in in processReturnedResources()
276 // the ResourceCache (we'll drop the ReturnMutex) and when we try to return the Resource we in processReturnedResources()
277 // will see that it is purgeable. If we are overbudget it is possible that the Resource gets in processReturnedResources()
279 // call will actually block here on the Resource's UnrefMutex which is held from the command in processReturnedResources()
283 // processReturnedResources the next time, we don't want this Resource added back into the in processReturnedResources()
284 // cache, thus we have the check here. The Resource will then get deleted when we call in processReturnedResources()
286 if (*resource->accessCacheIndex() != -1) { in processReturnedResources()
287 this->returnResourceToCache(resource, ref); in processReturnedResources()
290 resource->unrefCache(); in processReturnedResources()
295 void ResourceCache::returnResourceToCache(Resource* resource, LastRemovedRef removedRef) { in returnResourceToCache() argument
296 // A resource should not have been destroyed when placed into the return queue. Also before in returnResourceToCache()
299 // resources can be added. Thus we should not end up in a situation where a resource gets in returnResourceToCache()
301 SkASSERT(!resource->wasDestroyed()); in returnResourceToCache()
303 SkASSERT(this->isInCache(resource)); in returnResourceToCache()
305 if (resource->key().shareable() == Shareable::kYes) { in returnResourceToCache()
307 SkASSERT(fResourceMap.find(resource->key())); in returnResourceToCache()
309 SkDEBUGCODE(resource->fNonShareableInCache = true;) in returnResourceToCache()
310 fResourceMap.insert(resource->key(), resource); in returnResourceToCache()
311 if (resource->budgeted() == skgpu::Budgeted::kNo) { in returnResourceToCache()
312 resource->makeBudgeted(); in returnResourceToCache()
313 fBudgetedBytes += resource->gpuMemorySize(); in returnResourceToCache()
318 // If we weren't using multiple threads, it is ok to assume a resource that isn't purgeable must in returnResourceToCache()
320 // threads, it is possible that a resource became purgeable while we are in the middle of in returnResourceToCache()
321 // returning resources. For example, a resource could have 1 usage and 1 command buffer ref. We in returnResourceToCache()
322 // then unref the usage which puts the resource in the return queue. Then the ResourceCache in returnResourceToCache()
323 // thread locks the ReturnQueue as it returns the Resource. At this same time another thread in returnResourceToCache()
324 // unrefs the command buffer usage but can't add the Resource to the ReturnQueue as it is in returnResourceToCache()
326 // Resource (from the kUsage ref) to return it to the cache it will look like it is purgeable in returnResourceToCache()
327 // since all refs are zero. Thus we will move the Resource from the non purgeable to purgeable in returnResourceToCache()
328 // queue. Then later when we return the command buffer ref, the Resource will have already been in returnResourceToCache()
330 if (!resource->isPurgeable() || this->inPurgeableQueue(resource)) { in returnResourceToCache()
335 this->setResourceTimestamp(resource, this->getNextTimestamp()); in returnResourceToCache()
337 this->removeFromNonpurgeableArray(resource); in returnResourceToCache()
339 if (resource->shouldDeleteASAP() == Resource::DeleteASAP::kYes) { in returnResourceToCache()
340 this->purgeResource(resource); in returnResourceToCache()
342 resource->updateAccessTime(); in returnResourceToCache()
343 fPurgeableQueue.insert(resource); in returnResourceToCache()
348 void ResourceCache::addToNonpurgeableArray(Resource* resource) { in addToNonpurgeableArray() argument
350 *fNonpurgeableResources.append() = resource; in addToNonpurgeableArray()
351 *resource->accessCacheIndex() = index; in addToNonpurgeableArray()
354 void ResourceCache::removeFromNonpurgeableArray(Resource* resource) { in removeFromNonpurgeableArray() argument
355 int* index = resource->accessCacheIndex(); in removeFromNonpurgeableArray()
358 Resource* tail = *(fNonpurgeableResources.end() - 1); in removeFromNonpurgeableArray()
359 SkASSERT(fNonpurgeableResources[*index] == resource); in removeFromNonpurgeableArray()
366 void ResourceCache::removeFromPurgeableQueue(Resource* resource) { in removeFromPurgeableQueue() argument
367 fPurgeableQueue.remove(resource); in removeFromPurgeableQueue()
369 // flag for whether the Resource has been purged from the cache or not. So we need to make sure in removeFromPurgeableQueue()
371 *resource->accessCacheIndex() = -1; in removeFromPurgeableQueue()
374 bool ResourceCache::inPurgeableQueue(Resource* resource) const { in inPurgeableQueue()
375 SkASSERT(this->isInCache(resource)); in inPurgeableQueue()
376 int index = *resource->accessCacheIndex(); in inPurgeableQueue()
377 if (index < fPurgeableQueue.count() && fPurgeableQueue.at(index) == resource) { in inPurgeableQueue()
383 void ResourceCache::purgeResource(Resource* resource) { in purgeResource() argument
384 SkASSERT(resource->isPurgeable()); in purgeResource()
387 "size", resource->gpuMemorySize()); in purgeResource()
389 fResourceMap.remove(resource->key(), resource); in purgeResource()
391 if (resource->shouldDeleteASAP() == Resource::DeleteASAP::kNo) { in purgeResource()
392 SkASSERT(this->inPurgeableQueue(resource)); in purgeResource()
393 this->removeFromPurgeableQueue(resource); in purgeResource()
395 SkASSERT(!this->isInCache(resource)); in purgeResource()
398 fBudgetedBytes -= resource->gpuMemorySize(); in purgeResource()
399 resource->unrefCache(); in purgeResource()
412 Resource* resource = fPurgeableQueue.peek(); in purgeAsNeeded() local
413 SkASSERT(!resource->wasDestroyed()); in purgeAsNeeded()
414 SkASSERT(fResourceMap.find(resource->key())); in purgeAsNeeded()
416 if (resource->timestamp() == kMaxTimestamp) { in purgeAsNeeded()
417 // If we hit a resource that is at kMaxTimestamp, then we've hit the part of the in purgeAsNeeded()
420 SkASSERT(resource->gpuMemorySize() == 0); in purgeAsNeeded()
424 this->purgeResource(resource); in purgeAsNeeded()
459 SkTDArray<Resource*> nonZeroSizedResources; in purgeResources()
461 Resource* resource = fPurgeableQueue.at(i); in purgeResources() local
463 const skgpu::StdSteadyClock::time_point resourceTime = resource->lastAccessTime(); in purgeResources()
468 SkASSERT(resource->isPurgeable()); in purgeResources()
469 if (resource->gpuMemorySize() > 0) { in purgeResources()
470 *nonZeroSizedResources.append() = resource; in purgeResources()
497 SkTDArray<Resource*> sortedPurgeableResources; in getNextTimestamp()
520 // Correct the index in the nonpurgeable array stored on the resource post-sort. in getNextTimestamp()
550 void ResourceCache::setResourceTimestamp(Resource* resource, uint32_t timestamp) { in setResourceTimestamp() argument
552 if (resource->gpuMemorySize() == 0) { in setResourceTimestamp()
555 resource->setTimestamp(timestamp); in setResourceTimestamp()
569 const GraphiteResourceKey& ResourceCache::MapTraits::GetKey(const Resource& r) { in GetKey()
577 bool ResourceCache::CompareTimestamp(Resource* const& a, Resource* const& b) { in CompareTimestamp()
581 int* ResourceCache::AccessResourceIndex(Resource* const& res) { in AccessResourceIndex()
587 // Reduce the frequency of validations for large resource counts. in validate()
605 void update(Resource* resource) { in validate()
606 const GraphiteResourceKey& key = resource->key(); in validate()
610 SkASSERT(resource->hasCacheRef()); in validate()
614 SkASSERT(resource->ownership() == Ownership::kOwned); in validate()
621 if (resource->isUsableAsScratch()) { in validate()
623 SkASSERT(!resource->hasUsageRef()); in validate()
625 SkASSERT(fResourceMap->has(resource, key)); in validate()
626 SkASSERT(resource->budgeted() == skgpu::Budgeted::kYes); in validate()
628 SkASSERT(!fResourceMap->has(resource, key)); in validate()
632 SkASSERT(fResourceMap->has(resource, key)); in validate()
633 SkASSERT(resource->budgeted() == skgpu::Budgeted::kYes); in validate()
636 if (resource->budgeted() == skgpu::Budgeted::kYes) { in validate()
637 fBudgetedBytes += resource->gpuMemorySize(); in validate()
640 if (resource->gpuMemorySize() == 0) { in validate()
641 SkASSERT(resource->timestamp() == kMaxTimestamp); in validate()
643 SkASSERT(resource->timestamp() < kMaxTimestamp); in validate()
650 fResourceMap.foreach([&](const Resource& resource) { in validate() argument
651 SkASSERT(resource.isUsableAsScratch() || resource.key().shareable() == Shareable::kYes); in validate()
652 SkASSERT(resource.budgeted() == skgpu::Budgeted::kYes); in validate()
659 // we won't put a Resource into that queue unless all refs are zero. Thus there is no way for in validate()
660 // that resource to be made non-purgeable without going through the cache (which will switch in validate()
666 // queue yet. Its also possible that Resource hasn't been added to the ReturnQueue yet (thread in validate()
697 bool ResourceCache::isInCache(const Resource* resource) const { in isInCache()
698 int index = *resource->accessCacheIndex(); in isInCache()
702 if (index < fPurgeableQueue.count() && fPurgeableQueue.at(index) == resource) { in isInCache()
705 if (index < fNonpurgeableResources.size() && fNonpurgeableResources[index] == resource) { in isInCache()
708 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the cache."); in isInCache()
726 Resource* ResourceCache::topOfPurgeableQueue() { in topOfPurgeableQueue()