Add unit tests for vertexData in the thread-safe cache
Bug: 1108408
Change-Id: Ia984324d559bb33bfe668a44ee93c6e39fc47685
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/329419
Reviewed-by: Adlai Holler <adlai@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/tests/GrThreadSafeCacheTest.cpp b/tests/GrThreadSafeCacheTest.cpp
index 9f39daa..0f18573 100644
--- a/tests/GrThreadSafeCacheTest.cpp
+++ b/tests/GrThreadSafeCacheTest.cpp
@@ -8,14 +8,21 @@
#include "include/core/SkCanvas.h"
#include "include/core/SkDeferredDisplayListRecorder.h"
#include "include/core/SkSurfaceCharacterization.h"
+#include "include/private/SkMalloc.h"
+#include "src/gpu/GrDefaultGeoProcFactory.h"
#include "src/gpu/GrDirectContextPriv.h"
+#include "src/gpu/GrGpu.h"
+#include "src/gpu/GrMemoryPool.h"
+#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
+#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/GrThreadSafeCache.h"
#include "tests/Test.h"
#include "tests/TestUtils.h"
+#include "tools/gpu/ProxyUtils.h"
#include <thread>
@@ -40,17 +47,31 @@
SkBudgeted::kYes);
}
-static void create_key(GrUniqueKey* key, int wh, int id) {
- static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
- GrUniqueKey::Builder builder(key, kDomain, 1);
+static void create_view_key(GrUniqueKey* key, int wh, int id) {
+ static const GrUniqueKey::Domain kViewDomain = GrUniqueKey::GenerateDomain();
+ GrUniqueKey::Builder builder(key, kViewDomain, 1);
builder[0] = wh;
builder.finish();
if (id != kNoID) {
key->setCustomData(SkData::MakeWithCopy(&id, sizeof(id)));
}
-};
+}
+static void create_vert_key(GrUniqueKey* key, int wh, int id) {
+ static const GrUniqueKey::Domain kVertDomain = GrUniqueKey::GenerateDomain();
+ GrUniqueKey::Builder builder(key, kVertDomain, 1);
+ builder[0] = wh;
+ builder.finish();
+
+ if (id != kNoID) {
+ key->setCustomData(SkData::MakeWithCopy(&id, sizeof(id)));
+ }
+}
+
+// When testing views we create a bitmap that covers the entire screen and has an inset blue rect
+// atop a field of white.
+// When testing verts we clear the background to white and simply draw an inset blur rect.
static SkBitmap create_bitmap(int wh) {
SkBitmap bitmap;
@@ -89,10 +110,12 @@
SkAssertResult(fDst->characterize(&characterization));
fRecorder1 = std::make_unique<SkDeferredDisplayListRecorder>(characterization);
- this->ddlCanvas1()->clear(SkColors::kGreen);
+ this->ddlCanvas1()->clear(SkColors::kWhite);
fRecorder2 = std::make_unique<SkDeferredDisplayListRecorder>(characterization);
- this->ddlCanvas2()->clear(SkColors::kRed);
+ this->ddlCanvas2()->clear(SkColors::kWhite);
+
+ fDst->getCanvas()->clear(SkColors::kWhite);
}
~TestHelper() {
@@ -131,13 +154,19 @@
GrThreadSafeCache* threadSafeCache() { return fDContext->priv().threadSafeCache(); }
const GrThreadSafeCache* threadSafeCache() const { return fDContext->priv().threadSafeCache(); }
+ typedef void (TestHelper::*addAccessFP)(SkCanvas*, int wh, int id,
+ bool failLookUp, bool failFillingIn);
+ typedef bool (TestHelper::*checkFP)(SkCanvas*, int wh,
+ int expectedHits, int expectedMisses,
+ int expectedNumRefs, int expectedID);
+
// Add a draw on 'canvas' that will introduce a ref on the 'wh' view
- void accessCachedView(SkCanvas* canvas,
- int wh,
- int id = kNoID,
- bool failLookup = false,
- bool failFillingIn = false) {
- GrRecordingContext* rContext = canvas->recordingContext();
+ void addViewAccess(SkCanvas* canvas,
+ int wh,
+ int id = kNoID,
+ bool failLookup = false,
+ bool failFillingIn = false) {
+ auto rContext = canvas->recordingContext();
auto view = AccessCachedView(rContext, this->threadSafeCache(),
wh, failLookup, failFillingIn, id, &fStats);
@@ -163,40 +192,41 @@
// Besides checking that the number of refs and cache hits and misses are as expected, this
// method also validates that the unique key doesn't appear in any of the other caches.
- bool checkView(SkCanvas* canvas, int wh, int hits, int misses, int numRefs, int expectedID) {
- if (fStats.fCacheHits != hits || fStats.fCacheMisses != misses) {
+ bool checkView(SkCanvas* canvas, int wh,
+ int expectedHits, int expectedMisses, int expectedNumRefs, int expectedID) {
+ if (fStats.fCacheHits != expectedHits || fStats.fCacheMisses != expectedMisses) {
SkDebugf("Hits E: %d A: %d --- Misses E: %d A: %d\n",
- hits, fStats.fCacheHits, misses, fStats.fCacheMisses);
+ expectedHits, fStats.fCacheHits, expectedMisses, fStats.fCacheMisses);
return false;
}
GrUniqueKey key;
- create_key(&key, wh, kNoID);
+ create_view_key(&key, wh, kNoID);
auto threadSafeCache = this->threadSafeCache();
- auto [view, data] = threadSafeCache->findWithData(key);
+ auto [view, xtraData] = threadSafeCache->findWithData(key);
if (!view.proxy()) {
return false;
}
if (expectedID < 0) {
- if (data) {
+ if (xtraData) {
return false;
}
} else {
- if (!data) {
+ if (!xtraData) {
return false;
}
- const int* cachedID = static_cast<const int*>(data->data());
+ const int* cachedID = static_cast<const int*>(xtraData->data());
if (*cachedID != expectedID) {
return false;
}
}
- if (!view.proxy()->refCntGreaterThan(numRefs+1) || // +1 for 'view's ref
- view.proxy()->refCntGreaterThan(numRefs+2)) {
+ if (!view.proxy()->refCntGreaterThan(expectedNumRefs+1) || // +1 for 'view's ref
+ view.proxy()->refCntGreaterThan(expectedNumRefs+2)) {
return false;
}
@@ -232,6 +262,64 @@
return true;
}
+ // Add a draw on 'canvas' that will introduce a ref on a 'wh' vertex data
+ void addVertAccess(SkCanvas* canvas,
+ int wh,
+ int id = kNoID,
+ bool failLookup = false,
+ bool failFillingIn = false);
+
+ bool checkVert(SkCanvas* canvas, int wh,
+ int expectedHits, int expectedMisses, int expectedNumRefs, int expectedID) {
+ if (fStats.fCacheHits != expectedHits || fStats.fCacheMisses != expectedMisses) {
+ SkDebugf("Hits E: %d A: %d --- Misses E: %d A: %d\n",
+ expectedHits, fStats.fCacheHits, expectedMisses, fStats.fCacheMisses);
+ return false;
+ }
+
+ GrUniqueKey key;
+ create_vert_key(&key, wh, kNoID);
+
+ auto threadSafeCache = this->threadSafeCache();
+
+ auto [vertData, xtraData] = threadSafeCache->findVertsWithData(key);
+ if (!vertData) {
+ return false;
+ }
+
+ if (expectedID < 0) {
+ if (xtraData) {
+ return false;
+ }
+ } else {
+ if (!xtraData) {
+ return false;
+ }
+
+ const int* cachedID = static_cast<const int*>(xtraData->data());
+ if (*cachedID != expectedID) {
+ return false;
+ }
+ }
+
+ if (!vertData->refCntGreaterThan(expectedNumRefs+1) || // +1 for 'vertData's ref
+ vertData->refCntGreaterThan(expectedNumRefs+2)) {
+ return false;
+ }
+
+ {
+ auto resourceProvider = fDContext->priv().resourceProvider();
+ sk_sp<GrGpuBuffer> buffer = resourceProvider->findByUniqueKey<GrGpuBuffer>(key);
+ if (buffer) {
+ // the buffer holding the vertex data in this cache should never be discoverable
+ // in the resource cache
+ return false;
+ }
+ }
+
+ return true;
+ }
+
bool checkImage(skiatest::Reporter* reporter, sk_sp<SkSurface> s) {
SkBitmap actual;
@@ -301,6 +389,198 @@
std::unique_ptr<SkDeferredDisplayListRecorder> fRecorder2;
};
+class GrThreadSafeVertexTestOp : public GrDrawOp {
+public:
+ DEFINE_OP_CLASS_ID
+
+ static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* rContext, TestHelper::Stats* stats,
+ int wh, int id, bool failLookup, bool failFillingIn) {
+ GrOpMemoryPool* pool = rContext->priv().opMemoryPool();
+
+ return pool->allocate<GrThreadSafeVertexTestOp>(rContext, stats, wh, id,
+ failLookup, failFillingIn);
+ }
+
+private:
+ friend class GrOpMemoryPool; // for ctor
+
+ GrThreadSafeVertexTestOp(GrRecordingContext* rContext, TestHelper::Stats* stats, int wh, int id,
+ bool failLookup, bool failFillingIn)
+ : INHERITED(ClassID())
+ , fStats(stats)
+ , fWH(wh)
+ , fID(id)
+ , fFailFillingIn(failFillingIn) {
+ this->setBounds(SkRect::MakeIWH(fWH, fWH), HasAABloat::kNo, IsHairline::kNo);
+
+ // Normally we wouldn't add a ref to the vertex data at this point. However, it is
+ // needed in this unit test to get the ref counts on the uniquely keyed resources
+ // to be as expected.
+ this->findOrCreateVertices(rContext, failLookup, fFailFillingIn);
+ }
+
+ const char* name() const override { return "GrThreadSafeVertexTestOp"; }
+ FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
+ GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
+ bool hasMixedSampledCoverage, GrClampType) override {
+ return GrProcessorSet::EmptySetAnalysis();
+ }
+
+ GrProgramInfo* createProgramInfo(const GrCaps* caps,
+ SkArenaAlloc* arena,
+ const GrSurfaceProxyView* writeView,
+ GrAppliedClip&& appliedClip,
+ const GrXferProcessor::DstProxyView& dstProxyView,
+ GrXferBarrierFlags renderPassXferBarriers) const {
+ using namespace GrDefaultGeoProcFactory;
+
+ Color color({ 0.0f, 0.0f, 1.0f, 1.0f });
+
+ auto gp = MakeForDeviceSpace(arena, color,
+ Coverage::kSolid_Type,
+ LocalCoords::kUnused_Type,
+ SkMatrix::I());
+
+ return sk_gpu_test::CreateProgramInfo(caps, arena, writeView,
+ std::move(appliedClip), dstProxyView,
+ gp, SkBlendMode::kSrcOver,
+ GrPrimitiveType::kTriangleStrip,
+ renderPassXferBarriers);
+ }
+
+ GrProgramInfo* createProgramInfo(GrOpFlushState* flushState) const {
+ return this->createProgramInfo(&flushState->caps(),
+ flushState->allocator(),
+ flushState->writeView(),
+ flushState->detachAppliedClip(),
+ flushState->dstProxyView(),
+ flushState->renderPassBarriers());
+ }
+
+ void findOrCreateVertices(GrRecordingContext* rContext, bool failLookup, bool failFillingIn) {
+
+ if (!fVertexData) {
+ auto threadSafeViewCache = rContext->priv().threadSafeCache();
+
+ if (rContext->asDirectContext()) {
+ // The vertex variant doesn't have a correlate to lazyProxies but increment this
+ // here to make the unit tests happy.
+ ++fStats->fNumLazyCreations;
+ }
+
+ GrUniqueKey key;
+ create_vert_key(&key, fWH, fID);
+
+ // We can "fail the lookup" to simulate a threaded race condition
+ auto [cachedVerts, data] = threadSafeViewCache->findVertsWithData(key);
+ if (cachedVerts && !failLookup) {
+ fVertexData = cachedVerts;
+ ++fStats->fCacheHits;
+ return;
+ }
+
+ ++fStats->fCacheMisses;
+ if (!rContext->asDirectContext()) {
+ ++fStats->fNumSWCreations;
+ }
+
+ constexpr size_t kVertSize = sizeof(SkPoint);
+ SkPoint* verts = static_cast<SkPoint*>(sk_malloc_throw(4 * kVertSize));
+
+ verts[0].set(10.0f, 10.0f);
+ verts[1].set(fWH-10.0f, 10.0f);
+ verts[2].set(10.0f, fWH-10.0f);
+ verts[3].set(fWH-10.0f, fWH-10.0f);
+
+ fVertexData = GrThreadSafeCache::MakeVertexData(verts, 4, kVertSize);
+
+ auto [tmpV, tmpD] = threadSafeViewCache->addVertsWithData(key, fVertexData);
+ if (tmpV != fVertexData) {
+ // Someone beat us to creating the vertex data. Use that version.
+ fVertexData = tmpV;
+ }
+ }
+
+ if (auto dContext = rContext->asDirectContext(); dContext && !fVertexData->gpuBuffer()) {
+ auto rp = dContext->priv().resourceProvider();
+
+ if (!failFillingIn) {
+ ++fStats->fNumHWCreations;
+
+ sk_sp<GrGpuBuffer> tmp = rp->createBuffer(fVertexData->size(),
+ GrGpuBufferType::kVertex,
+ kStatic_GrAccessPattern,
+ fVertexData->vertices());
+ fVertexData->setGpuBuffer(std::move(tmp));
+ }
+ }
+ }
+
+ void onPrePrepare(GrRecordingContext* rContext,
+ const GrSurfaceProxyView* writeView,
+ GrAppliedClip* clip,
+ const GrXferProcessor::DstProxyView& dstProxyView,
+ GrXferBarrierFlags renderPassXferBarriers) override {
+ SkArenaAlloc* arena = rContext->priv().recordTimeAllocator();
+
+ // This is equivalent to a GrOpFlushState::detachAppliedClip
+ GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
+
+ fProgramInfo = this->createProgramInfo(rContext->priv().caps(), arena, writeView,
+ std::move(appliedClip), dstProxyView,
+ renderPassXferBarriers);
+
+ rContext->priv().recordProgramInfo(fProgramInfo);
+
+ // This is now a noop (bc it is always called in the ctor) but is where we would normally
+ // create the vertices.
+ this->findOrCreateVertices(rContext, false, fFailFillingIn);
+ }
+
+ void onPrepare(GrOpFlushState* flushState) override {
+ auto dContext = flushState->gpu()->getContext();
+
+ // This call site is not a noop bc this op could've been created on with DDL context
+ // and, therefore, could be lacking a gpu-side buffer
+ this->findOrCreateVertices(dContext, false, fFailFillingIn);
+ }
+
+ void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
+ if (!fVertexData || !fVertexData->gpuBuffer()) {
+ return;
+ }
+
+ if (!fProgramInfo) {
+ fProgramInfo = this->createProgramInfo(flushState);
+ }
+
+ flushState->bindPipeline(*fProgramInfo, SkRect::MakeIWH(fWH, fWH));
+ flushState->bindBuffers(nullptr, nullptr, fVertexData->refGpuBuffer());
+ flushState->draw(4, 0);
+ }
+
+ TestHelper::Stats* fStats;
+ int fWH;
+ int fID;
+ bool fFailFillingIn;
+
+ sk_sp<GrThreadSafeCache::VertexData> fVertexData;
+ GrProgramInfo* fProgramInfo = nullptr;
+
+ using INHERITED = GrDrawOp;
+};
+
+void TestHelper::addVertAccess(SkCanvas* canvas,
+ int wh, int id,
+ bool failLookup, bool failFillingIn) {
+ auto rContext = canvas->recordingContext();
+ auto rtc = canvas->internal_private_accessTopLayerRenderTargetContext();
+
+ rtc->priv().testingOnly_addDrawOp(GrThreadSafeVertexTestOp::Make(rContext,
+ &fStats, wh, id,
+ failLookup, failFillingIn));
+}
+
GrSurfaceProxyView TestHelper::CreateViewOnCpu(GrRecordingContext* rContext,
int wh,
Stats* stats) {
@@ -349,7 +629,7 @@
bool failLookup, bool failFillingIn, int id,
Stats* stats) {
GrUniqueKey key;
- create_key(&key, wh, id);
+ create_view_key(&key, wh, id);
if (GrDirectContext* dContext = rContext->asDirectContext()) {
// The gpu thread gets priority over the recording threads. If the gpu thread is first,
@@ -410,17 +690,20 @@
}
}
-// Case 1: ensure two DDL recorders share the view
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache1, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+// Case 1: ensure two DDL recorders share the view/vertexData
+static void test_1(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH, 1);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
+ TestHelper helper(dContext);
- helper.accessCachedView(helper.ddlCanvas2(), kImageWH, 2);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, /*id*/ 1));
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 1, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
+
+ (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, 2, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, /*id*/ 1));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 0);
@@ -431,21 +714,33 @@
helper.checkImage(reporter, helper.snap2());
}
-// Case 2: ensure that, if the direct context version wins, it is reused by the DDL recorders
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache2, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache1View, reporter, ctxInfo) {
+ test_1(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
- helper.accessCachedView(helper.liveCanvas(), kImageWH, 1);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache1Verts, reporter, ctxInfo) {
+ test_1(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH, 2);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, /*id*/ 1));
+// Case 2: ensure that, if the direct context version wins, its result is reused by the
+// DDL recorders
+static void test_2(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
- helper.accessCachedView(helper.ddlCanvas2(), kImageWH, 3);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
- /*hits*/ 2, /*misses*/ 1, /*refs*/ 3, /*id*/ 1));
+ TestHelper helper(dContext);
+
+ (helper.*addAccess)(helper.liveCanvas(), kImageWH, 1, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
+
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 2, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, /*id*/ 1));
+
+ (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, 3, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
+ /*hits*/ 2, /*misses*/ 1, /*refs*/ 3, /*id*/ 1));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
@@ -457,17 +752,28 @@
helper.checkImage(reporter, helper.snap2());
}
-// Case 3: ensure that, if the cpu-version wins, it is reused by the direct context
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache3, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache2View, reporter, ctxInfo) {
+ test_2(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH, 1);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache2Verts, reporter, ctxInfo) {
+ test_2(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
- helper.accessCachedView(helper.liveCanvas(), kImageWH, 2);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, /*id*/ 1));
+// Case 3: ensure that, if the cpu-version wins, its result is reused by the direct context
+static void test_3(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
+
+ TestHelper helper(dContext);
+
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 1, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
+
+ (helper.*addAccess)(helper.liveCanvas(), kImageWH, 2, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, /*id*/ 1));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
@@ -478,18 +784,30 @@
helper.checkImage(reporter, helper.snap1());
}
-// Case 4: ensure that, if two DDL recorders get in a race, they still end up sharing a single view
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache3View, reporter, ctxInfo) {
+ test_3(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH, 1);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache3Verts, reporter, ctxInfo) {
+ test_3(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
+// Case 4: ensure that, if two DDL recorders get in a race, they still end up sharing a single
+// view/vertexData
+static void test_4(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
+
+ TestHelper helper(dContext);
+
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 1, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
static const bool kFailLookup = true;
- helper.accessCachedView(helper.ddlCanvas2(), kImageWH, 2, kFailLookup);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
- /*hits*/ 0, /*misses*/ 2, /*refs*/ 2, /*id*/ 1));
+ (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, 2, kFailLookup, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
+ /*hits*/ 0, /*misses*/ 2, /*refs*/ 2, /*id*/ 1));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 0);
@@ -500,14 +818,25 @@
helper.checkImage(reporter, helper.snap2());
}
-// Case 4.5: check that, if a live rendering and a DDL recording get into a race, the live
-// rendering takes precedence.
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_5, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4View, reporter, ctxInfo) {
+ test_4(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
- helper.accessCachedView(helper.liveCanvas(), kImageWH, 1);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4Verts, reporter, ctxInfo) {
+ test_4(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
+// Case 4.5: check that, if a live rendering and a DDL recording get into a race, the live
+// rendering takes precedence.
+static void test_4_5(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
+
+ TestHelper helper(dContext);
+
+ (helper.*addAccess)(helper.liveCanvas(), kImageWH, 1, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
@@ -515,9 +844,9 @@
REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);
static const bool kFailLookup = true;
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH, 2, kFailLookup);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 0, /*misses*/ 2, /*refs*/ 2, /*id*/ 1));
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 2, kFailLookup, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 0, /*misses*/ 2, /*refs*/ 2, /*id*/ 1));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
@@ -528,17 +857,28 @@
helper.checkImage(reporter, helper.snap1());
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_5View, reporter, ctxInfo) {
+ test_4_5(ctxInfo.directContext(), reporter,
+ &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_5Verts, reporter, ctxInfo) {
+ test_4_5(ctxInfo.directContext(), reporter,
+ &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
// Case 4.75: check that, if a live rendering fails to generate the content needed to instantiate
// its lazy proxy, life goes on
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_75, reporter, ctxInfo) {
- auto dContext = ctxInfo.directContext();
+static void test_4_75(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
TestHelper helper(dContext);
static const bool kFailFillingIn = true;
- helper.accessCachedView(helper.liveCanvas(), kImageWH, kNoID, false, kFailFillingIn);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+ (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, kFailFillingIn);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
@@ -548,8 +888,8 @@
dContext->flush();
dContext->submit(true);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 0, kNoID));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
@@ -557,78 +897,113 @@
REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_75View, reporter, ctxInfo) {
+ test_4_75(ctxInfo.directContext(), reporter,
+ &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_75Verts, reporter, ctxInfo) {
+ test_4_75(ctxInfo.directContext(), reporter,
+ &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
// Case 5: ensure that expanding the map works (esp. wrt custom data)
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache5, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+static void test_5(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
+
+ TestHelper helper(dContext);
auto threadSafeCache = helper.threadSafeCache();
int size = 16;
- helper.accessCachedView(helper.ddlCanvas1(), size, /*id*/ size);
+ (helper.*addAccess)(helper.ddlCanvas1(), size, /*id*/ size, false, false);
size_t initialSize = threadSafeCache->approxBytesUsedForHash();
while (initialSize == threadSafeCache->approxBytesUsedForHash()) {
size *= 2;
- helper.accessCachedView(helper.ddlCanvas1(), size, /*id*/ size);
+ (helper.*addAccess)(helper.ddlCanvas1(), size, /*id*/ size, false, false);
}
for (int i = 16; i <= size; i *= 2) {
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(),
- /*wh*/ i,
- /*hits*/ 0,
- /*misses*/ threadSafeCache->numEntries(),
- /*refs*/ 1,
- /*id*/ i));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(),
+ /*wh*/ i,
+ /*hits*/ 0,
+ /*misses*/ threadSafeCache->numEntries(),
+ /*refs*/ 1,
+ /*id*/ i));
}
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache5View, reporter, ctxInfo) {
+ test_5(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache5Verts, reporter, ctxInfo) {
+ test_5(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
// Case 6: Check on dropping refs. In particular, that the cache has its own ref to keep
-// the backing resource alive and locked.
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache6, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+// the backing resource alive and locked.
+static void test_6(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
+ TestHelper helper(dContext);
+
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
- REPORTER_ASSERT(reporter, helper.checkView(nullptr, kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
- helper.accessCachedView(helper.ddlCanvas2(), kImageWH);
+ (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, kNoID, false, false);
sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
- REPORTER_ASSERT(reporter, helper.checkView(nullptr, kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
ddl1 = nullptr;
- REPORTER_ASSERT(reporter, helper.checkView(nullptr, kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 1, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 1, kNoID));
ddl2 = nullptr;
- REPORTER_ASSERT(reporter, helper.checkView(nullptr, kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 0, kNoID));
// The cache still has its ref
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
- REPORTER_ASSERT(reporter, helper.checkView(nullptr, kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 0, kNoID));
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache6View, reporter, ctxInfo) {
+ test_6(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache6Verts, reporter, ctxInfo) {
+ test_6(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}
// Case 7: Check that invoking dropAllRefs and dropUniqueRefs directly works as expected; i.e.,
-// dropAllRefs removes everything while dropUniqueRefs is more measured.
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache7, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+// dropAllRefs removes everything while dropUniqueRefs is more measured.
+static void test_7(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
+ TestHelper helper(dContext);
+
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
- REPORTER_ASSERT(reporter, helper.checkView(nullptr, kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
- helper.accessCachedView(helper.ddlCanvas2(), 2*kImageWH);
+ (helper.*addAccess)(helper.ddlCanvas2(), 2*kImageWH, kNoID, false, false);
sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
- REPORTER_ASSERT(reporter, helper.checkView(nullptr, 2*kImageWH,
- /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(nullptr, 2*kImageWH,
+ /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);
@@ -639,8 +1014,8 @@
helper.threadSafeCache()->dropUniqueRefs(nullptr);
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
- REPORTER_ASSERT(reporter, helper.checkView(nullptr, 2*kImageWH,
- /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(nullptr, 2*kImageWH,
+ /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
helper.threadSafeCache()->dropAllRefs();
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 0);
@@ -648,31 +1023,42 @@
ddl2 = nullptr;
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache7View, reporter, ctxInfo) {
+ test_7(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache7Verts, reporter, ctxInfo) {
+ test_7(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
// Case 8: This checks that GrContext::abandonContext works as expected wrt the thread
// safe cache. This simulates the case where we have one DDL that has finished
// recording but one still recording when the abandonContext fires.
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache8, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+static void test_8(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
- helper.accessCachedView(helper.liveCanvas(), kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+ TestHelper helper(dContext);
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
+ (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
- helper.accessCachedView(helper.ddlCanvas2(), kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
- /*hits*/ 2, /*misses*/ 1, /*refs*/ 3, kNoID));
+ (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
+ /*hits*/ 2, /*misses*/ 1, /*refs*/ 3, kNoID));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);
- ctxInfo.directContext()->abandonContext(); // This should exercise dropAllRefs
+ dContext->abandonContext(); // This should exercise dropAllRefs
sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
@@ -682,31 +1068,42 @@
ddl2 = nullptr;
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache8View, reporter, ctxInfo) {
+ test_8(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache8Verts, reporter, ctxInfo) {
+ test_8(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
// Case 9: This checks that GrContext::releaseResourcesAndAbandonContext works as expected wrt
// the thread safe cache. This simulates the case where we have one DDL that has finished
// recording but one still recording when the releaseResourcesAndAbandonContext fires.
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache9, reporter, ctxInfo) {
- TestHelper helper(ctxInfo.directContext());
+static void test_9(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
- helper.accessCachedView(helper.liveCanvas(), kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+ TestHelper helper(dContext);
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
+ (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
- helper.accessCachedView(helper.ddlCanvas2(), kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
- /*hits*/ 2, /*misses*/ 1, /*refs*/ 3, kNoID));
+ (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
+ /*hits*/ 2, /*misses*/ 1, /*refs*/ 3, kNoID));
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 1);
REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);
- ctxInfo.directContext()->releaseResourcesAndAbandonContext(); // This should hit dropAllRefs
+ dContext->releaseResourcesAndAbandonContext(); // This should hit dropAllRefs
sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
@@ -716,11 +1113,20 @@
ddl2 = nullptr;
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache9View, reporter, ctxInfo) {
+ test_9(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache9Verts, reporter, ctxInfo) {
+ test_9(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
// Case 10: This checks that the GrContext::purgeUnlockedResources(size_t) variant works as
// expected wrt the thread safe cache. It, in particular, tests out the MRU behavior
// of the shared cache.
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache10, reporter, ctxInfo) {
- auto dContext = ctxInfo.directContext();
+static void test_10(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
if (GrBackendApi::kOpenGL != dContext->backend()) {
// The lower-level backends have too much going on for the following simple purging
@@ -730,23 +1136,23 @@
TestHelper helper(dContext);
- helper.accessCachedView(helper.liveCanvas(), kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+ (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
- helper.accessCachedView(helper.liveCanvas(), 2*kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
- /*hits*/ 1, /*misses*/ 2, /*refs*/ 1, kNoID));
+ (helper.*addAccess)(helper.liveCanvas(), 2*kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
+ /*hits*/ 1, /*misses*/ 2, /*refs*/ 1, kNoID));
- helper.accessCachedView(helper.ddlCanvas2(), 2*kImageWH);
+ (helper.*addAccess)(helper.ddlCanvas2(), 2*kImageWH, kNoID, false, false);
sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), 2*kImageWH,
- /*hits*/ 2, /*misses*/ 2, /*refs*/ 2, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), 2*kImageWH,
+ /*hits*/ 2, /*misses*/ 2, /*refs*/ 2, kNoID));
dContext->flush();
dContext->submit(true);
@@ -758,10 +1164,10 @@
ddl2 = nullptr;
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
- /*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
+ /*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));
// Regardless of which image is MRU, this should force the other out
size_t desiredBytes = helper.gpuSize(2*kImageWH) + helper.gpuSize(kImageWH)/2;
@@ -777,34 +1183,46 @@
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
- /*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
+ /*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache10View, reporter, ctxInfo) {
+ test_10(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+// To enable test_10 with verts would require a bit more work, namely:
+// have a different # of verts based on size
+// also pass in a gpuSize function to 'test_10'
+//DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache10Verts, reporter, ctxInfo) {
+// test_10(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+//}
+
// Case 11: This checks that scratch-only variant of GrContext::purgeUnlockedResources works as
// expected wrt the thread safe cache. In particular, that when 'scratchResourcesOnly'
// is true, the call has no effect on the cache.
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache11, reporter, ctxInfo) {
- auto dContext = ctxInfo.directContext();
+static void test_11(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
TestHelper helper(dContext);
- helper.accessCachedView(helper.liveCanvas(), kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+ (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
- helper.accessCachedView(helper.liveCanvas(), 2*kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
- /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
+ (helper.*addAccess)(helper.liveCanvas(), 2*kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
+ /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
dContext->flush();
dContext->submit(true);
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 2, /*refs*/ 0, kNoID));
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
- /*hits*/ 0, /*misses*/ 2, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 2, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
+ /*hits*/ 0, /*misses*/ 2, /*refs*/ 0, kNoID));
// This shouldn't remove anything from the cache
dContext->purgeUnlockedResources(/* scratchResourcesOnly */ true);
@@ -816,34 +1234,43 @@
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 0);
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache11View, reporter, ctxInfo) {
+ test_11(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache11Verts, reporter, ctxInfo) {
+ test_11(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
// Case 12: Test out purges caused by resetting the cache budget to 0. Note that, due to
// the how the cache operates (i.e., not directly driven by ref/unrefs) there
// needs to be an explicit kick to purge the cache.
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache12, reporter, ctxInfo) {
- auto dContext = ctxInfo.directContext();
+static void test_12(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
TestHelper helper(dContext);
- helper.accessCachedView(helper.liveCanvas(), kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
+ (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));
- helper.accessCachedView(helper.liveCanvas(), 2*kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
- /*hits*/ 1, /*misses*/ 2, /*refs*/ 1, kNoID));
+ (helper.*addAccess)(helper.liveCanvas(), 2*kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
+ /*hits*/ 1, /*misses*/ 2, /*refs*/ 1, kNoID));
dContext->flush();
dContext->submit(true);
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
- /*hits*/ 1, /*misses*/ 2, /*refs*/ 1, kNoID));
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
- /*hits*/ 1, /*misses*/ 2, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
+ /*hits*/ 1, /*misses*/ 2, /*refs*/ 1, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
+ /*hits*/ 1, /*misses*/ 2, /*refs*/ 0, kNoID));
dContext->setResourceCacheLimit(0);
@@ -857,25 +1284,34 @@
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 0);
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache12View, reporter, ctxInfo) {
+ test_12(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache12Verts, reporter, ctxInfo) {
+ test_12(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
+}
+
// Case 13: Test out the 'msNotUsed' parameter to GrContext::performDeferredCleanup.
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache13, reporter, ctxInfo) {
- auto dContext = ctxInfo.directContext();
+static void test_13(GrDirectContext* dContext, skiatest::Reporter* reporter,
+ TestHelper::addAccessFP addAccess,
+ TestHelper::checkFP check) {
TestHelper helper(dContext);
- helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
-
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
- /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
+ (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
+ /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
std::this_thread::sleep_for(std::chrono::milliseconds(5));
auto firstTime = GrStdSteadyClock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(5));
- helper.accessCachedView(helper.ddlCanvas2(), 2*kImageWH);
- REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), 2*kImageWH,
- /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
+ (helper.*addAccess)(helper.ddlCanvas2(), 2*kImageWH, kNoID, false, false);
+
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), 2*kImageWH,
+ /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
ddl1 = nullptr;
@@ -889,6 +1325,14 @@
dContext->performDeferredCleanup(msecs);
REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
- REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
- /*hits*/ 0, /*misses*/ 2, /*refs*/ 0, kNoID));
+ REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
+ /*hits*/ 0, /*misses*/ 2, /*refs*/ 0, kNoID));
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache13View, reporter, ctxInfo) {
+ test_13(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache13Verts, reporter, ctxInfo) {
+ test_13(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}