/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/ResourceCache.h"

#include "include/private/SingleOwner.h"
#include "src/core/SkNoDestructor.h"
#include "src/core/SkRandom.h"
#include "src/core/SkTMultiMap.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/GlobalResourceStats.h"
#include "src/gpu/graphite/GraphiteResourceKey.h"
#include "src/gpu/graphite/ProxyCache.h"
#include "src/gpu/graphite/Resource.h"
#include "src/gpu/graphite/SharedContext.h"

#if defined(GPU_TEST_UTILS)
#include "src/gpu/graphite/Texture.h"
#endif

namespace skgpu::graphite {

#define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(fSingleOwner)

namespace {

static constexpr uint32_t kMaxUseToken = 0xFFFFFFFF;

// Singleton Resource subclass that provides a fixed address used to track the end of the return
// queue and when the resource cache is shutdown.
class Sentinel : public Resource {
public:
    static Resource* Get() {
        static SkNoDestructor<Sentinel> kSentinel{};
        return kSentinel.get();
    }

private:
    template <typename T>
    friend class ::SkNoDestructor;

    // We can pass in a null shared context here because the only instance that is ever created is
    // wrapped in SkNoDestructor, and we never actually use it as a Resource.
    Sentinel() : Resource(/*sharedContext=*/nullptr, Ownership::kOwned, /*gpuMemorySize=*/0) {}

    const char* getResourceType() const override { return "Sentinel"; }

    void freeGpuData() override {}
};

}  // anonymous namespace

sk_sp<ResourceCache> ResourceCache::Make(SingleOwner* singleOwner,
                                         uint32_t recorderID,
                                         size_t maxBytes) {
    return sk_sp<ResourceCache>(new ResourceCache(singleOwner, recorderID, maxBytes));
}

ResourceCache::ResourceCache(SingleOwner* singleOwner, uint32_t recorderID, size_t maxBytes)
        : fMaxBytes(maxBytes)
        , fSingleOwner(singleOwner) {
    if (recorderID != SK_InvalidGenID) {
        fProxyCache = std::make_unique<ProxyCache>(recorderID);
    }
    // TODO: Maybe when things start using ResourceCache, then like Ganesh the compiler won't
    // complain about not using fSingleOwner in Release builds and we can delete this.
#if !defined(SK_DEBUG)
    (void)fSingleOwner;
#endif
}

ResourceCache::~ResourceCache() {
    // The ResourceCache must have been shutdown by the ResourceProvider before it is destroyed.
    SkASSERT(fReturnQueue.load(std::memory_order_acquire) == Sentinel::Get());
}

void ResourceCache::shutdown() {
    ASSERT_SINGLE_OWNER

    // At this point no more changes will happen to fReturnQueue or the resources within that
    // linked list. We do need to finish processing them for a graceful shutdown.
    this->processReturnedResources(Sentinel::Get());

    if (fProxyCache) {
        fProxyCache->purgeAll();
        // NOTE: any resources that would become purgeable or reusable from purging the proxy cache
        // are not added to the return queue and remain in the nonpurgeable array. Below their
        // cache ref will be removed, causing them to be deleted immediately.
    }

    while (!fNonpurgeableResources.empty()) {
        Resource* back = *(fNonpurgeableResources.end() - 1);
        SkASSERT(!back->wasDestroyed());
        this->removeFromNonpurgeableArray(back);

        if (back->budgeted() == Budgeted::kNo) {
            // Pretend it's being transitioned through becoming budgeted before we unref it
            GlobalResourceStats::RecordResourceBudgetChange(
                    back->isProtected(), back->gpuMemorySize(), Budgeted::kYes);
        }

        // Resources will delete themselves as needed, but record "purging" here
        GlobalResourceStats::RecordPurgeResource(back->isProtected(), back->gpuMemorySize());
        back->unrefCache();
    }

    while (fPurgeableQueue.count()) {
        Resource* top = fPurgeableQueue.peek();
        SkASSERT(!top->wasDestroyed());
        this->removeFromPurgeableQueue(top);

        // Resources will delete themselves as needed, but record "purging" here
        GlobalResourceStats::RecordPurgeResource(top->isProtected(), top->gpuMemorySize());
        top->unrefCache();
    }

    GlobalResourceStats::TraceStatsSummary(); // Record the completion of all the cleanup

    TRACE_EVENT_INSTANT0("skia.gpu.cache", TRACE_FUNC, TRACE_EVENT_SCOPE_THREAD);
}

void ResourceCache::insertResource(Resource* resource,
                                   const GraphiteResourceKey& key,
                                   Budgeted budgeted,
                                   Shareable shareable) {
    ASSERT_SINGLE_OWNER
    SkASSERT(resource);
    SkASSERT(key.isValid());
    SkASSERT(shareable == Shareable::kNo || budgeted == Budgeted::kYes);

    SkASSERT(!this->isInCache(resource));
    SkASSERT(!resource->wasDestroyed());
    SkASSERT(!resource->isPurgeable());
    SkASSERT(!resource->key().isValid());
    // All resources in the cache are owned. If we track wrapped resources in the cache we'll need
    // to update this check.
    SkASSERT(resource->ownership() == Ownership::kOwned);

    // Make sure we have the most accurate memory size for "memoryless" resources.
    resource->updateGpuMemorySize();

    // The reason to call processReturnedResources here is to get an accurate accounting of our
    // memory usage as some resources can go from unbudgeted to budgeted when they return. So we
    // want to have them all returned before adding the budget for the new resource in case we need
    // to purge things. However, if the new resource has a memory size of 0, then we just skip
    // returning resources (which has overhead for each call) since the new resource won't be
    // affecting whether we're over or under budget.
    if (resource->gpuMemorySize() > 0) {
        this->processReturnedResources();
    }

    resource->registerWithCache(sk_ref_sp(this), key, budgeted, shareable);

    // We must set the use token before adding to the array in case the token wraps and we wind
    // up iterating over all the resources that already have use tokens.
    this->setResourceUseToken(resource, this->getNextUseToken());
    resource->updateAccessTime();

    this->addToNonpurgeableArray(resource);

    SkDEBUGCODE(fCount++;)

    if (resource->shareable() != Shareable::kNo) {
        // Scratch and shareable resources are always available for reuse
        this->addToResourceMap(resource);
    }

    if (resource->budgeted() == Budgeted::kYes) {
        fBudgetedBytes += resource->gpuMemorySize();
    }

    GlobalResourceStats::RecordNewResource(
            resource->isProtected(), resource->gpuMemorySize(), resource->budgeted());

    this->purgeAsNeeded();
}

Resource* ResourceCache::findAndRefResource(const GraphiteResourceKey& key,
                                            Budgeted budgeted,
                                            Shareable shareable,
                                            std::string_view label,
                                            const ScratchResourceSet* unavailable) {
    ASSERT_SINGLE_OWNER

    SkASSERT(key.isValid());
    SkASSERT(shareable == Shareable::kNo || budgeted == Budgeted::kYes);
    SkASSERT(shareable != Shareable::kScratch || SkToBool(unavailable));

    auto shareablePredicate = [shareable, unavailable](Resource* r) {
        // If the resource is in fResourceMap then it's available, so a non-shareable state means
        // it really has no outstanding uses and can be converted to any other shareable state.
        // Otherwise, if it's available, it can only be reused with the same mode. Additionally,
        // for kScratch resources, they cannot already be in the `unavailable` set passed in.
        return (r->shareable() == Shareable::kNo || r->shareable() == shareable) &&
               (shareable != Shareable::kScratch || !unavailable->contains(r));
    };

    Resource* resource = fResourceMap.find(key, shareablePredicate);
    if (!resource) {
        // The main reason to call processReturnedResources in this call is to see if there are any
        // resources that we could match with the key. However, there is overhead into calling it.
        // So we only call it if we first failed to find a matching resource.
        if (this->processReturnedResources()) {
            resource = fResourceMap.find(key, shareablePredicate);
        }
    }
    if (resource) {
        // All resources we pull out of the cache for use should be budgeted
        SkASSERT(resource->budgeted() == Budgeted::kYes);
        SkASSERT(resource->key() == key);

        if (shareable == Shareable::kNo) {
            // If the returned resource is no longer shareable then we remove it from the map so
            // that it isn't found again.
            SkASSERT(resource->shareable() == Shareable::kNo);
            this->removeFromResourceMap(resource);
            if (budgeted == Budgeted::kNo) {
                resource->setBudgeted(Budgeted::kNo);
                fBudgetedBytes -= resource->gpuMemorySize();
                GlobalResourceStats::RecordResourceBudgetChange(
                        resource->isProtected(), resource->gpuMemorySize(), Budgeted::kNo);
            }
            // It is safe to update non-shareable resources when returning them from the cache.
            resource->setLabel(label);
            resource->synchronizeBackendLabel();
        } else {
            // Shareable and scratch resources should never be requested as non-budgeted
            SkASSERT(budgeted == Budgeted::kYes);

            // TODO(b/387505250): Eventually, scratch resource label updates will be uniquely
            // handled per the threadsafe label update model outlined in Resource.h. For now,
            // maintain original functionality by allowing label reassignment here.
            if (shareable == Shareable::kScratch) {
                resource->setLabel(label);
                resource->synchronizeBackendLabel();
            } else {
                // Shareable resource labels should never change after initial creation.
                SkASSERT(shareable == Shareable::kYes && resource->getLabel() == label);
            }

            resource->setShareable(shareable);
        }
        this->refAndMakeResourceMRU(resource);
        this->validate();
    }

    // processReturnedResources may have added resources back into our budget if they were being
    // using in an SkImage or SkSurface previously. However, instead of calling purgeAsNeeded in
    // processReturnedResources, we delay calling it until now so we don't end up purging a resource
    // we're looking for in this function.
    //
    // We could avoid calling this if we didn't return any resources from processReturnedResources.
    // However, when not overbudget purgeAsNeeded is very cheap. When overbudget there may be some
    // really niche usage patterns that could cause us to never actually return resources to the
    // cache, but still be overbudget due to shared resources. So to be safe we just always call it
    // here.
    this->purgeAsNeeded();

    return resource;
}

void ResourceCache::refAndMakeResourceMRU(Resource* resource) {
    SkASSERT(resource);
    SkASSERT(this->isInCache(resource));

    if (this->inPurgeableQueue(resource)) {
        // It's about to become unpurgeable.
        this->removeFromPurgeableQueue(resource);
        this->addToNonpurgeableArray(resource);
    }
    resource->initialUsageRef();

    this->setResourceUseToken(resource, this->getNextUseToken());
    this->validate();
}

void ResourceCache::forceProcessReturnedResources() {
    ASSERT_SINGLE_OWNER
    this->processReturnedResources();
}

bool ResourceCache::returnResource(Resource* resource) {
    SkASSERT(resource && resource->cache() == this);
    // We only allow one instance of a Resource to be in the return queue at a time but it should
    // have already added a return queue ref.
    SkASSERT(!resource->inReturnQueue() && resource->hasReturnQueueRef());

    // Check once with a relaxed load to try and minimize the amount of wasted preparation work if
    // the cache is already shutdown.
    Resource* oldHeadPtr = fReturnQueue.load(std::memory_order_relaxed);
    if (oldHeadPtr == Sentinel::Get()) {
        return false;
    }

    // When a non-shareable resource's CB and Usage refs are both zero, give it a chance to prepare
    // itself to be reused. On Dawn/WebGPU we use this to remap kXferCpuToGpu buffers asynchronously
    // so that they are already mapped before they come out of the cache again.
    if (resource->shouldDeleteASAP() == Resource::DeleteASAP::kNo &&
        resource->requiresPrepareForReturnToCache()) {
        // If we get here, we know the usage ref count is 0, so the only way for that to increase
        // again is if the Resource triggers the initial usage ref in the callback.
        struct TakeRefContext {
            Resource* resource;
            SkDEBUGCODE(bool takeRefActuallyCalled = false;)
        } ctx = {resource};
        bool takeRefCalled = resource->prepareForReturnToCache([](void* ctx) {
                // This adds a usage ref AND removes the return queue ref. When returnResource()
                // returns true, the cache takes responsibility for releasing the return queue ref.
                // If we returned false from returnResource() when the resource invokes the takeRef
                // function, there's a gap between when the resource can be used on another thread
                // and when this thread removes the return queue ref. If the resource's new usage
                // ref is removed on the other thread before this thread were to remove the return
                // queue ref, it would end up skipping the return.
                //
                // By immediately unreffing the return queue ref before the resource can be exposed
                // to another thread, the resource will always be able to be re-returned when the
                // async work completes.
                //
                // Since prepareForReturnToCache() can only be used with resources that require
                // purgeability for reusability, and it is non-shareable, the only ref that can
                // change off thread is the resource's cache ref if the cache is simultaneously
                // shutdown.
                //
                // Adding the usage ref first ensures the resource won't be disposed of early. When
                // the resource is prepared, it will come through returnResource() again but should
                // return false from prepareForReturnToCache() so that cache shutdown is detected.
                // This can add unnecessary preparation work for resources that won't ever be used,
                // but keeps the preparation logic relatively simple w/o needing a mutex.
                auto* context = static_cast<TakeRefContext*>(ctx);
                context->resource->initialUsageRef();
                context->resource->unrefReturnQueue();

                SkDEBUGCODE(context->takeRefActuallyCalled = true;
            )}, &ctx);

        SkASSERT(takeRefCalled == ctx.takeRefActuallyCalled);
        if (takeRefCalled) {
            // Return 'true' here because we've removed the return queue ref already and don't
            // want Resource to try and do that again. But since we added an initial ref, this
            // resource will be re-returned once the async prepare-for-return work has finished.
            return true;
        }
    }

    // Set the newly returned resource to be the head of the list, with its next pointer holding
    // the old head. If the head has changed between the assignment of the next pointer, we repeat
    // because it means there was a simultaneous return or the cache was shutdown.
    do {
        oldHeadPtr = fReturnQueue.load(std::memory_order_acquire);
        if (oldHeadPtr == Sentinel::Get()) {
            // Once the cache is shutdown, it can never be re-opened and we don't want to actually
            // return this resource.
            resource->setNextInReturnQueue(nullptr);
            return false;
        } else {
            // If oldHeadPtr is null, this resource will be the tail of the return queue as it grows
            // so set it's next pointer to the sentinel so that nullity can be used to test for
            // being in the queue or not.
            resource->setNextInReturnQueue(oldHeadPtr ? oldHeadPtr : Sentinel::Get());
        }
    } while(!fReturnQueue.compare_exchange_weak(oldHeadPtr, resource,
                                                std::memory_order_release,
                                                std::memory_order_relaxed));

    // Once we've got here, it means that `resource` has been atomically included in the return
    // queue. At this point, fReturnQueue's head value may or may not be `resource`, depending on if
    // another thread has added another resource or processed the return queue, but in either event,
    // `resource` will be visible to that thread.
    return true;
}

bool ResourceCache::processReturnedResources(Resource* queueHead) {
    SkASSERT(queueHead == nullptr || queueHead == Sentinel::Get());
    // We need to move the returned Resources off of the ReturnQueue before we start processing them
    // so that we can manipulate the resources without blocking subsequent returns on other threads.
    Resource* oldQueue = fReturnQueue.exchange(queueHead, std::memory_order_acq_rel);

    // Can't un-shutdown the cache
    SkASSERT(oldQueue != Sentinel::Get() || queueHead == Sentinel::Get());

    int returnCount = 0;
    // Stop if we encounter null or the sentinel address (either the list is empty, the cache is
    // shutdown, or we reached the tail returned resource that had next set to the sentinel).
    while (oldQueue && oldQueue != Sentinel::Get()) {
        returnCount++;
        oldQueue = this->processReturnedResource(oldQueue);
    }

    TRACE_EVENT_INSTANT1("skia.gpu.cache", TRACE_FUNC, TRACE_EVENT_SCOPE_THREAD,
                         "count", returnCount);
    return returnCount > 0;
}

Resource* ResourceCache::processReturnedResource(Resource* resource) {
    // A resource should not have been destroyed when placed into the return queue. Also before
    // purging any resources from the cache itself, it should always empty the queue first. When the
    // cache releases/abandons all of its resources, it first invalidates the return queue so no new
    // resources can be added. Thus we should not end up in a situation where a resource gets
    // destroyed after it was added to the return queue.
    SkASSERT(!resource->wasDestroyed());
    SkASSERT(this->isInCache(resource));

    const auto [isReusable, isPurgeable, next] = resource->unrefReturnQueue();

    if (resource->shareable() != Shareable::kNo) {
        // Shareable resources should still be discoverable in the resource map
        SkASSERT(fResourceMap.has(resource, resource->key()));
        SkASSERT(resource->isAvailableForReuse());

        // Reset the resource's sharing mode so that any shareable request can use it (e.g. now that
        // no more usages that required it to be scratch/shareable are held, the underlying resource
        // can be used in a non-shareable manner the next time it's fetched from the cache). We can
        // only change the shareable state when there are no outstanding usage refs. Because this
        // resource was shareable, it remained in fResourceMap and could have a new usage ref before
        // a prior return event was processed from the return queue. However, when a shareable ref
        // has no usage refs, this is the only thread that can add an initial usage ref so it is
        // safe to adjust its shareable type
        if (isReusable) {
            resource->setShareable(Shareable::kNo);
        }
    } else if (isReusable) {
        // Non-shareable resources are removed from the resource map when they are given out by the
        // cache. A resource is returned for either becoming reusable (needs to be added to the
        // resource map) or becoming purgeable (needs to be moved to the purgeable queue). Becoming
        // purgeable always implies becoming reusable, so as long as a previous return hasn't put it
        // into the resource map already, we do that now.
        if (!resource->isAvailableForReuse()) {
            SkASSERT(!fResourceMap.has(resource, resource->key()));
            this->addToResourceMap(resource);

            if (resource->budgeted() == Budgeted::kNo) {
                resource->setBudgeted(Budgeted::kYes);
                fBudgetedBytes += resource->gpuMemorySize();
                GlobalResourceStats::RecordResourceBudgetChange(
                        resource->isProtected(), resource->gpuMemorySize(), Budgeted::kYes);
            }
        }

        SkASSERT(fResourceMap.has(resource, resource->key()));
        SkASSERT(resource->isAvailableForReuse());
        // Since the resource should be non-shareable available as scratch, there are no outstanding
        // refs that would make this assert not thread safe.
        SkASSERT(resource->isUsableAsScratch());
    } else {
        // This was a stale entry in the return queue, which can arise when a Resource becomes
        // reusable while it has outstanding command buffer refs. If the timing is right, the
        // command buffer ref can be removed so the resource is purgeable (and goes back into the
        // queue to be processed from non-purgeable to purgeable), but immediately after, the cache
        // thread can add a usage ref. By the next time the return queue is processed, the resource
        // is neither purgeable nor reusable.
        SkASSERT(!fResourceMap.has(resource, resource->key()));
        SkASSERT(!resource->isAvailableForReuse());
        // At an instanteous moment, this resource should not be considered usable as scratch, but
        // we cannot assert !isUsableAsScratch() because the other threads that are holding the
        // extra refs described above can just as easily drop them between this assert and the last
        // call to unrefReturnQueue() that put us into this branch.
    }

    // Update GPU budget now that the budget policy is up to date. Some GPU resources may have their
    // actual memory amount change over time so update periodically.
    size_t oldSize = resource->gpuMemorySize();
    resource->updateGpuMemorySize();
    if (oldSize != resource->gpuMemorySize()) {
        if (resource->budgeted() == Budgeted::kYes) {
            fBudgetedBytes -= oldSize;
            fBudgetedBytes += resource->gpuMemorySize();
        }
        GlobalResourceStats::RecordResourceUpdatedSize(
                resource->isProtected(), resource->gpuMemorySize(), oldSize, resource->budgeted());
    }

    this->setResourceUseToken(resource, this->getNextUseToken());

    // If the resource was not purgeable at the time the return queue ref was released, the
    // resource should still be in the non-purgeable array from when it was originally given
    // out. Another thread may have already removed the last refs keeping it non-purgeable by
    // the time this thread reachs this line but that will only have re-added it to the return
    // queue. The cache stores the resource based on its purgeability at the time of releasing
    // the return queue ref. Any subsequent return due to becoming purgeable will complete
    // moving the resource from the non-purgeable array to the purgeable queue.
    SkASSERT(this->inNonpurgeableArray(resource));
    if (!isPurgeable) {
        this->validate();
        return next;
    }

    // Since the resource is purgeable, there are no external refs that can add new refs to make
    // it non-purgeable at this point. Only the current cache thread has that ability so we can
    // safely continue moving the resource from non-purgeable to purgeable without worrying about
    // another state change.
    this->removeFromNonpurgeableArray(resource);

    if (resource->shouldDeleteASAP() == Resource::DeleteASAP::kYes) {
        this->purgeResource(resource);
    } else {
        // We don't purge this resource immediately even if we are overbudget. This allows later
        // purgeAsNeeded() calls to prioritize deleting less-recently-used Resources first.
        resource->updateAccessTime();
        fPurgeableQueue.insert(resource);
        fPurgeableBytes += resource->gpuMemorySize();
        GlobalResourceStats::RecordResourcePurgeable(
                resource->isProtected(), resource->gpuMemorySize());
    }
    this->validate();

    return next;
}

void ResourceCache::addToResourceMap(Resource* resource) {
    SkASSERT(this->isInCache(resource));
    SkASSERT(!resource->isAvailableForReuse());
    SkASSERT(!fResourceMap.has(resource, resource->key()));
    fResourceMap.insert(resource->key(), resource);
    resource->setAvailableForReuse(true);
}

void ResourceCache::removeFromResourceMap(Resource* resource) {
    SkASSERT(this->isInCache(resource));
    SkASSERT(resource->isAvailableForReuse());
    SkASSERT(fResourceMap.has(resource, resource->key()));
    fResourceMap.remove(resource->key(), resource);
    resource->setAvailableForReuse(false);
}

void ResourceCache::addToNonpurgeableArray(Resource* resource) {
    SkASSERT(!this->inNonpurgeableArray(resource));

    int index = fNonpurgeableResources.size();
    *fNonpurgeableResources.append() = resource;
    *resource->accessCacheIndex() = index;
}

void ResourceCache::removeFromNonpurgeableArray(Resource* resource) {
    SkASSERT(this->inNonpurgeableArray(resource));

    int* index = resource->accessCacheIndex();
    // Fill the hole we will create in the array with the tail object, adjust its index, and
    // then pop the array
    Resource* tail = *(fNonpurgeableResources.end() - 1);
    SkASSERT(fNonpurgeableResources[*index] == resource);
    fNonpurgeableResources[*index] = tail;
    *tail->accessCacheIndex() = *index;
    fNonpurgeableResources.pop_back();
    *index = -1;
}

void ResourceCache::removeFromPurgeableQueue(Resource* resource) {
    SkASSERT(this->inPurgeableQueue(resource));

    fPurgeableQueue.remove(resource);
    fPurgeableBytes -= resource->gpuMemorySize();
    GlobalResourceStats::RecordResourceNonpurgeable(
            resource->isProtected(), resource->gpuMemorySize());
    // SkTDPQueue will set the index back to -1 in debug builds, but we are using the index as a
    // flag for whether the Resource has been purged from the cache or not. So we need to make sure
    // it always gets set.
    *resource->accessCacheIndex() = -1;
}

bool ResourceCache::inPurgeableQueue(const Resource* resource) const {
    int index = *resource->accessCacheIndex();
    return index >= 0 && index < fPurgeableQueue.count() &&
           fPurgeableQueue.at(index) == resource;
}

#if defined(SK_DEBUG)

bool ResourceCache::inNonpurgeableArray(const Resource* resource) const {
    int index = *resource->accessCacheIndex();
    return index >= 0 && index < fNonpurgeableResources.size() &&
           fNonpurgeableResources[index] == resource;
}

bool ResourceCache::isInCache(const Resource* resource) const {
    if (this->inPurgeableQueue(resource) || this->inNonpurgeableArray(resource)) {
        SkASSERT(resource->cache() == this);
        SkASSERT(resource->hasCacheRef());
        return true;
    }
    // Resource index should have been set to -1 if the resource is not in the cache
    SkASSERT(*resource->accessCacheIndex() == -1);
    // Don't assert that the resource has no cache ref, as the ResourceCache asserts this is false
    // before it removes its cache ref in the event that that was the last resource keeping it alive
    return false;
}

#endif // SK_DEBUG

void ResourceCache::purgeResource(Resource* resource) {
    SkASSERT(resource->isPurgeable());

    TRACE_EVENT_INSTANT1("skia.gpu.cache", TRACE_FUNC, TRACE_EVENT_SCOPE_THREAD,
                         "size", resource->gpuMemorySize());

    this->removeFromResourceMap(resource);

    if (resource->shouldDeleteASAP() == Resource::DeleteASAP::kNo) {
        SkASSERT(this->inPurgeableQueue(resource));
        this->removeFromPurgeableQueue(resource);
    }

    SkASSERT(!this->isInCache(resource));
    // Unbudgeted resources always transition through becoming reusable and budgeted before they
    // are purged.
    SkASSERT(resource->budgeted() == Budgeted::kYes);
    fBudgetedBytes -= resource->gpuMemorySize();
    GlobalResourceStats::RecordPurgeResource(resource->isProtected(), resource->gpuMemorySize());
    resource->unrefCache();
}

void ResourceCache::purgeAsNeeded() {
    ASSERT_SINGLE_OWNER

    if (this->overbudget() && fProxyCache) {
        fProxyCache->freeUniquelyHeld();

        // After the image cache frees resources we need to return those resources to the cache
        this->processReturnedResources();
    }
    while (this->overbudget() && fPurgeableQueue.count()) {
        Resource* resource = fPurgeableQueue.peek();
        SkASSERT(!resource->wasDestroyed());
        SkASSERT(fResourceMap.has(resource, resource->key()));

        if (resource->lastUseToken() == kMaxUseToken) {
            // If we hit a resource that is at kMaxUseToken, then we've hit the part of the
            // purgeable queue with all zero sized resources. We don't want to actually remove those
            // so we just break here.
            SkASSERT(resource->gpuMemorySize() == 0);
            break;
        }

        this->purgeResource(resource);
    }

    this->validate();
}

void ResourceCache::purgeResourcesNotUsedSince(
        StdSteadyClock::time_point purgeTime,
        std::optional<StdSteadyClock::time_point> quitPurgingTime) {
    ASSERT_SINGLE_OWNER
    this->purgeResources(&purgeTime, quitPurgingTime);
}

void ResourceCache::purgeResources() {
    ASSERT_SINGLE_OWNER
    this->purgeResources(/*purgeTime=*/nullptr, /*quitPurgingTime=*/std::nullopt);
}

void ResourceCache::purgeResources(const StdSteadyClock::time_point* purgeTime,
                                   std::optional<StdSteadyClock::time_point> quitPurgingTime) {
    TRACE_EVENT0("skia.gpu.cache", TRACE_FUNC);
    if (fProxyCache) {
        fProxyCache->purgeProxiesNotUsedSince(purgeTime, quitPurgingTime);
    }
    this->processReturnedResources();

    auto time_remains_before_stop_time = [&]() {
        return !quitPurgingTime.has_value() ||
               skgpu::StdSteadyClock::now() < quitPurgingTime.value();
    };

    // Early out if the very first item is too new to purge to avoid sorting the queue when
    // nothing will be deleted or if we have somehow already exceeded the time limit for purging.
    if (fPurgeableQueue.count() &&
        purgeTime &&
        fPurgeableQueue.peek()->lastAccessTime() >= *purgeTime) {
        return;
    }
    if (!time_remains_before_stop_time()) {
        return;
    }

    // Sort the queue
    fPurgeableQueue.sort();

    // Make a list of the scratch resources to delete
    SkTDArray<Resource*> resourcesToPurge;
    for (int i = 0; i < fPurgeableQueue.count(); i++) {
        Resource* resource = fPurgeableQueue.at(i);

        const skgpu::StdSteadyClock::time_point resourceTime = resource->lastAccessTime();
        if (purgeTime && resourceTime >= *purgeTime) {
            // scratch or not, all later iterations will be too recently used to purge.
            break;
        }
        SkASSERT(resource->isPurgeable());
        *resourcesToPurge.append() = resource;
    }

    // Delete the scratch resources. This must be done as a separate pass to avoid messing up the
    // sorted order of the queue.
    for (int i = 0; i < resourcesToPurge.size(); i++) {
        this->purgeResource(resourcesToPurge[i]);
        if (!time_remains_before_stop_time()) {
            break;
        }
    }

    // Since we called process returned resources at the start of this call, we could still end up
    // over budget even after purging resources based on purgeTime. So we call purgeAsNeeded at the
    // end here. Not limited by latest purge end time - purging to not go over memory budget takes
    // precedence.
    this->purgeAsNeeded();
}

uint32_t ResourceCache::getNextUseToken() {
    // If we wrap then all the existing resources will appear older than any resources that get
    // a token after the wrap. We wrap one value early when we reach kMaxUseToken so that we
    // can continue to use kMaxUseToken as a special case for zero sized resources.
    if (fUseToken == kMaxUseToken) {
        fUseToken = 0;
        int count = this->getResourceCount();
        if (count) {
            // Reset all the tokens. We sort the resources by their use token and then assign
            // sequential tokens beginning with 0. This is O(n*lg(n)) but it should be very rare.
            SkTDArray<Resource*> sortedPurgeableResources;
            sortedPurgeableResources.reserve(fPurgeableQueue.count());

            while (fPurgeableQueue.count()) {
                *sortedPurgeableResources.append() = fPurgeableQueue.peek();
                fPurgeableQueue.pop();
            }

            SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end(), CompareUseToken);

            // Pick resources out of the purgeable and non-purgeable arrays based on lowest
            // use token and assign new tokens.
            int currP = 0;
            int currNP = 0;
            while (currP < sortedPurgeableResources.size() &&
                   currNP < fNonpurgeableResources.size()) {
                uint32_t tsP = sortedPurgeableResources[currP]->lastUseToken();
                uint32_t tsNP = fNonpurgeableResources[currNP]->lastUseToken();
                SkASSERT(tsP != tsNP);
                if (tsP < tsNP) {
                    this->setResourceUseToken(sortedPurgeableResources[currP++], fUseToken++);
                } else {
                    // Correct the index in the nonpurgeable array stored on the resource post-sort.
                    *fNonpurgeableResources[currNP]->accessCacheIndex() = currNP;
                    this->setResourceUseToken(fNonpurgeableResources[currNP++], fUseToken++);
                }
            }

            // The above loop ended when we hit the end of one array. Finish the other one.
            while (currP < sortedPurgeableResources.size()) {
                this->setResourceUseToken(sortedPurgeableResources[currP++], fUseToken++);
            }
            while (currNP < fNonpurgeableResources.size()) {
                *fNonpurgeableResources[currNP]->accessCacheIndex() = currNP;
                this->setResourceUseToken(fNonpurgeableResources[currNP++], fUseToken++);
            }

            // Rebuild the queue.
            for (int i = 0; i < sortedPurgeableResources.size(); ++i) {
                fPurgeableQueue.insert(sortedPurgeableResources[i]);
            }

            this->validate();
            SkASSERT(count == this->getResourceCount());

            // count should be the next use token we return.
            SkASSERT(fUseToken == SkToU32(count));
        }
    }
    return fUseToken++;
}

void ResourceCache::setResourceUseToken(Resource* resource, uint32_t token) {
    // We always set the use token for zero-sized resources to be kMaxUseToken
    if (resource->gpuMemorySize() == 0) {
        token = kMaxUseToken;
    }
    resource->setLastUseToken(token);
}

void ResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
    ASSERT_SINGLE_OWNER

    // There is no need to process the return queue here. Resources in the queue are still in
    // either the purgeable queue or the nonpurgeable resources list (likely to be moved to the
    // purgeable queue). However, the Resource's own ref counts are used to report its purgeable
    // state to the memory dump, which is accurate without draining the return queue.

    for (int i = 0; i < fNonpurgeableResources.size(); ++i) {
        fNonpurgeableResources[i]->dumpMemoryStatistics(traceMemoryDump, false);
    }
    for (int i = 0; i < fPurgeableQueue.count(); ++i) {
        fPurgeableQueue.at(i)->dumpMemoryStatistics(traceMemoryDump, true);
    }
}

void ResourceCache::setMaxBudget(size_t bytes) {
    fMaxBytes = bytes;
    this->processReturnedResources();
    this->purgeAsNeeded();
}

////////////////////////////////////////////////////////////////////////////////

#if defined(SK_DEBUG)
void ResourceCache::validate() const {
    // Reduce the frequency of validations for large resource counts.
    static SkRandom gRandom;
    int mask = (SkNextPow2(fCount + 1) >> 5) - 1;
    if (~mask && (gRandom.nextU() & mask)) {
        return;
    }

    struct Stats {
        int fShareable;
        int fScratch;
        size_t fBudgetedBytes;
        size_t fPurgeableBytes;
        const ResourceMap* fResourceMap;
        const PurgeableQueue* fPurgeableQueue;

        Stats(const ResourceCache* cache) {
            memset(this, 0, sizeof(*this));
            fResourceMap = &cache->fResourceMap;
            fPurgeableQueue = &cache->fPurgeableQueue;
        }

        void update(Resource* resource) {
            const GraphiteResourceKey& key = resource->key();
            SkASSERT(key.isValid());

            // All resources in the cache are owned. If we track wrapped resources in the cache
            // we'll need to update this check.
            SkASSERT(resource->ownership() == Ownership::kOwned);

            if (resource->shareable() == Shareable::kYes) {
                SkASSERT(resource->isAvailableForReuse());
                SkASSERT(fResourceMap->has(resource, key));
                SkASSERT(resource->budgeted() == Budgeted::kYes);
                ++fShareable;
            } else if (resource->isAvailableForReuse()) {
                // We track scratch resources (either non-shareable with no refs that are returned,
                // or explicitly scratch shared) separately from fully shareable.
                SkASSERT(resource->isUsableAsScratch());
                SkASSERT(fResourceMap->has(resource, key));
                ++fScratch;
            } else {
                // This should be a non-shareable resource that isn't available for reuse.
                SkASSERT(resource->shareable() == Shareable::kNo);
                SkASSERT(!fResourceMap->has(resource, key));
            }

            if (resource->budgeted() == Budgeted::kYes) {
                fBudgetedBytes += resource->gpuMemorySize();
            }

            if (resource->gpuMemorySize() == 0) {
                SkASSERT(resource->lastUseToken() == kMaxUseToken);
            } else {
                SkASSERT(resource->lastUseToken() < kMaxUseToken);
            }

            int index = *resource->accessCacheIndex();
            if (index < fPurgeableQueue->count() && fPurgeableQueue->at(index) == resource) {
                SkASSERT(resource->isPurgeable());
                fPurgeableBytes += resource->gpuMemorySize();
            }
        }
    };

    {
        int count = 0;
        fResourceMap.foreach([&](const Resource& resource) {
            SkASSERT(resource.isUsableAsScratch() || resource.shareable() == Shareable::kYes);
            SkASSERT(resource.budgeted() == Budgeted::kYes);
            SkASSERT(resource.isAvailableForReuse());
            SkASSERT(this->isInCache(&resource));
            count++;
        });
        SkASSERT(count == fResourceMap.count());
    }

    // In the below checks we can assert that anything in the purgeable queue is purgeable because
    // we won't put a Resource into that queue unless all refs are zero. Thus there is no way for
    // that resource to be made non-purgeable without going through the cache (which will switch
    // queues back to non-purgeable).
    //
    // However, we can't say the same for things in the non-purgeable array. It is possible that
    // Resources have removed all their refs (thus technically become purgeable) but have not been
    // processed back into the cache yet. Thus we may not have moved resources to the purgeable
    // queue yet. Its also possible that Resource hasn't been added to the ReturnQueue yet (thread
    // paused between unref and adding to ReturnQueue) so we can't even make asserts like not
    // purgeable or is in ReturnQueue.
    Stats stats(this);
    for (int i = 0; i < fNonpurgeableResources.size(); ++i) {
        SkASSERT(this->isInCache(fNonpurgeableResources[i]));
        SkASSERT(*fNonpurgeableResources[i]->accessCacheIndex() == i);
        SkASSERT(!fNonpurgeableResources[i]->wasDestroyed());
        SkASSERT(!this->inPurgeableQueue(fNonpurgeableResources[i]));
        stats.update(fNonpurgeableResources[i]);
    }
    bool firstPurgeableIsSizeZero = false;
    for (int i = 0; i < fPurgeableQueue.count(); ++i) {
        if (i == 0) {
            firstPurgeableIsSizeZero = (fPurgeableQueue.at(0)->gpuMemorySize() == 0);
        }
        if (firstPurgeableIsSizeZero) {
            // If the first purgeable item (i.e. least recently used) is sized zero, then all other
            // purgeable resources must also be sized zero since they should all have a use token of
            // kMaxUseToken.
            SkASSERT(fPurgeableQueue.at(i)->gpuMemorySize() == 0);
        }
        SkASSERT(this->isInCache(fPurgeableQueue.at(i)));
        SkASSERT(fPurgeableQueue.at(i)->isPurgeable());
        SkASSERT(*fPurgeableQueue.at(i)->accessCacheIndex() == i);
        SkASSERT(!fPurgeableQueue.at(i)->wasDestroyed());
        stats.update(fPurgeableQueue.at(i));
    }

    SkASSERT((stats.fScratch + stats.fShareable) == fResourceMap.count());
    SkASSERT(stats.fBudgetedBytes == fBudgetedBytes);
    SkASSERT(stats.fPurgeableBytes == fPurgeableBytes);
}

#endif // SK_DEBUG

#if defined(GPU_TEST_UTILS)

int ResourceCache::numFindableResources() const {
    return fResourceMap.count();
}

Resource* ResourceCache::topOfPurgeableQueue() {
    if (!fPurgeableQueue.count()) {
        return nullptr;
    }
    return fPurgeableQueue.peek();
}

void ResourceCache::visitTextures(
        const std::function<void(const Texture*, bool purgeable)>& func) const {
    for (int i = 0; i < fNonpurgeableResources.size(); ++i) {
        if (const Texture* tex = fNonpurgeableResources[i]->asTexture()) {
            func(tex, /* purgeable= */ false);
        }
    }
    for (int i = 0; i < fPurgeableQueue.count(); ++i) {
        if (const Texture* tex = fPurgeableQueue.at(i)->asTexture()) {
            func(tex, /* purgeable= */ true);
        }
    }
}

#endif // defined(GPU_TEST_UTILS)

} // namespace skgpu::graphite
