Add GrResourceCache::purgeToMakeHeadroom
This function will be used by the resource allocator to figure out whether an allocation plan is feasible without committing to it. Bug: skia:10877 Change-Id: I135b7b80d53d9c3541d2fa0313d91d14a1d54eb2 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/394156 Commit-Queue: Adlai Holler <adlai@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com> Auto-Submit: Adlai Holler <adlai@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
022636b15a
commit
e1c8a38794
@ -124,7 +124,7 @@ public:
|
||||
/**
|
||||
* Retrieves the context that owns the object. Note that it is possible for
|
||||
* this to return NULL. When objects have been release()ed or abandon()ed
|
||||
* they no longer have an owning context. Destroying a GrContext
|
||||
* they no longer have an owning context. Destroying a GrDirectContext
|
||||
* automatically releases all its resources.
|
||||
*/
|
||||
const GrDirectContext* getContext() const;
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "src/gpu/GrResourceCache.h"
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include "include/gpu/GrDirectContext.h"
|
||||
#include "include/private/GrSingleOwner.h"
|
||||
#include "include/private/SkTo.h"
|
||||
@ -619,6 +620,40 @@ void GrResourceCache::purgeResourcesNotUsedSince(GrStdSteadyClock::time_point pu
|
||||
}
|
||||
}
|
||||
|
||||
bool GrResourceCache::purgeToMakeHeadroom(size_t desiredHeadroomBytes) {
|
||||
AutoValidate av(this);
|
||||
if (this->wouldFit(desiredHeadroomBytes)) {
|
||||
return true;
|
||||
}
|
||||
fPurgeableQueue.sort();
|
||||
|
||||
size_t headroom = this->overBudget() ? 0 : fMaxBytes - fBudgetedBytes;
|
||||
int purgeCnt = 0;
|
||||
for (int i = 0; i < fPurgeableQueue.count(); i++) {
|
||||
GrGpuResource* resource = fPurgeableQueue.at(i);
|
||||
headroom += resource->gpuMemorySize();
|
||||
if (headroom >= desiredHeadroomBytes) {
|
||||
purgeCnt = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (headroom < desiredHeadroomBytes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success! Release the resources.
|
||||
// Copy to array first so we don't mess with the queue.
|
||||
std::vector<GrGpuResource*> resources;
|
||||
resources.reserve(purgeCnt);
|
||||
for (int i = 0; i < purgeCnt; i++) {
|
||||
resources.push_back(fPurgeableQueue.at(i));
|
||||
}
|
||||
for (GrGpuResource* resource : resources) {
|
||||
resource->cacheAccess().release();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrResourceCache::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) {
|
||||
|
||||
const size_t tmpByteBudget = std::max((size_t)0, fBytes - bytesToPurge);
|
||||
|
@ -165,6 +165,11 @@ public:
|
||||
/** Purge all resources not used since the passed in time. */
|
||||
void purgeResourcesNotUsedSince(GrStdSteadyClock::time_point);
|
||||
|
||||
/** If it's possible to purge enough resources to get the provided amount of budget
|
||||
headroom, do so and return true. If it's not possible, do nothing and return false.
|
||||
*/
|
||||
bool purgeToMakeHeadroom(size_t desiredHeadroomBytes);
|
||||
|
||||
bool overBudget() const { return fBudgetedBytes > fMaxBytes; }
|
||||
|
||||
/**
|
||||
|
@ -1733,6 +1733,40 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GPUMemorySize, reporter, ctxInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PurgeToMakeHeadroom, reporter, ctxInfo) {
|
||||
constexpr size_t kTexSize = 16 * 16 * 4;
|
||||
|
||||
auto dContext = ctxInfo.directContext();
|
||||
dContext->setResourceCacheLimit(2 * kTexSize);
|
||||
auto resourceProvider = dContext->priv().resourceProvider();
|
||||
auto resourceCache = dContext->priv().getResourceCache();
|
||||
for (bool success : { true, false }) {
|
||||
reporter->push(SkString(success ? "success" : "failure"));
|
||||
|
||||
resourceCache->releaseAll();
|
||||
REPORTER_ASSERT(reporter, resourceCache->getBudgetedResourceBytes() == 0);
|
||||
|
||||
// Make one unpurgeable texture and one purgeable texture.
|
||||
auto lockedTex = make_normal_texture(resourceProvider, GrRenderable::kNo, {16, 16}, 1);
|
||||
REPORTER_ASSERT(reporter, lockedTex->gpuMemorySize() == kTexSize);
|
||||
|
||||
// N.b. this surface is renderable so "reuseScratchTextures = false" won't mess us up.
|
||||
auto purgeableTex = make_normal_texture(resourceProvider, GrRenderable::kYes, {16, 16}, 1);
|
||||
if (success) {
|
||||
purgeableTex = nullptr;
|
||||
}
|
||||
|
||||
size_t expectedPurgeable = success ? kTexSize : 0;
|
||||
REPORTER_ASSERT(reporter, expectedPurgeable == resourceCache->getPurgeableBytes(),
|
||||
"%zu vs %zu", expectedPurgeable, resourceCache->getPurgeableBytes());
|
||||
REPORTER_ASSERT(reporter, success == resourceCache->purgeToMakeHeadroom(kTexSize));
|
||||
size_t expectedBudgeted = success ? kTexSize : (2 * kTexSize);
|
||||
REPORTER_ASSERT(reporter, expectedBudgeted == resourceCache->getBudgetedResourceBytes(),
|
||||
"%zu vs %zu", expectedBudgeted, resourceCache->getBudgetedResourceBytes());
|
||||
reporter->pop();
|
||||
}
|
||||
}
|
||||
|
||||
#if GR_GPU_STATS
|
||||
DEF_GPUTEST_FOR_MOCK_CONTEXT(OverbudgetFlush, reporter, ctxInfo) {
|
||||
auto context = ctxInfo.directContext();
|
||||
|
Loading…
Reference in New Issue
Block a user