From 7278d68cac9e39970144909df449113d43fff480 Mon Sep 17 00:00:00 2001 From: Greg Daniel Date: Fri, 16 Mar 2018 14:57:21 -0400 Subject: Add DoneProc to Promise Images This proc will notify the client when we will no longer call fulfill on their promise image so that can delete any meta data they needed to store to be able to complete the fulfill requests. Bug: skia: Change-Id: Ife1e6845f221c31ce1ae2c0d2ba5e4c8f0203b74 Reviewed-on: https://skia-review.googlesource.com/114092 Commit-Queue: Greg Daniel Reviewed-by: Robert Phillips Reviewed-by: Brian Salomon --- tests/PromiseImageTest.cpp | 257 ++++++++++++++++++++++++++------------------- 1 file changed, 149 insertions(+), 108 deletions(-) (limited to 'tests/PromiseImageTest.cpp') diff --git a/tests/PromiseImageTest.cpp b/tests/PromiseImageTest.cpp index c5bd9cd268..ef4a299850 100644 --- a/tests/PromiseImageTest.cpp +++ b/tests/PromiseImageTest.cpp @@ -22,10 +22,12 @@ struct PromiseTextureChecker { explicit PromiseTextureChecker(const GrBackendTexture& tex) : fTexture(tex) , fFulfillCount(0) - , fReleaseCount(0) {} + , fReleaseCount(0) + , fDoneCount(0) {} GrBackendTexture fTexture; int fFulfillCount; int fReleaseCount; + int fDoneCount; static void Fulfill(void* self, GrBackendTexture* outTexture) { static_cast(self)->fFulfillCount++; *outTexture = static_cast(self)->fTexture; @@ -33,6 +35,9 @@ struct PromiseTextureChecker { static void Release(void* self) { static_cast(self)->fReleaseCount++; } + static void Done(void* self) { + static_cast(self)->fDoneCount++; + } }; // Because Vulkan may delay when it actually calls the ReleaseProcs depending on when command @@ -43,6 +48,7 @@ static bool check_fulfill_and_release_cnts(const PromiseTextureChecker& promiseC int expectedFulfillCnt, int expectedReleaseCnt, bool expectedRequired, + int expectedDoneCnt, skiatest::Reporter* reporter) { bool result = true; int countDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount; @@ -81,123 +87,158 @@ static bool check_fulfill_and_release_cnts(const PromiseTextureChecker& promiseC } } + if (expectedDoneCnt != promiseChecker.fDoneCount) { + result = false; + REPORTER_ASSERT(reporter, expectedDoneCnt == promiseChecker.fDoneCount); + } + return result; } DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) { const int kWidth = 10; const int kHeight = 10; - std::unique_ptr pixels(new uint32_t[kWidth * kHeight]); GrContext* ctx = ctxInfo.grContext(); GrGpu* gpu = ctx->contextPriv().getGpu(); - GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture( - pixels.get(), kWidth, kHeight, kRGBA_8888_GrPixelConfig, true, GrMipMapped::kNo); - REPORTER_ASSERT(reporter, backendTex.isValid()); - - GrBackendFormat backendFormat = backendTex.format(); - REPORTER_ASSERT(reporter, backendFormat.isValid()); - - PromiseTextureChecker promiseChecker(backendTex); - GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin; - sk_sp refImg( - SkImage_Gpu::MakePromiseTexture(ctx, backendFormat, kWidth, kHeight, GrMipMapped::kNo, - texOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType, - nullptr, - PromiseTextureChecker::Fulfill, - PromiseTextureChecker::Release, - &promiseChecker)); - - SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight); - sk_sp surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info); - SkCanvas* canvas = surface->getCanvas(); - - int expectedFulfillCnt = 0; - int expectedReleaseCnt = 0; - - canvas->drawImage(refImg, 0, 0); - REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, - true, - expectedFulfillCnt, - expectedReleaseCnt, - true, - reporter)); - - bool isVulkan = kVulkan_GrBackend == ctx->contextPriv().getBackend(); - canvas->flush(); - expectedFulfillCnt++; - expectedReleaseCnt++; - REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, - !isVulkan, - expectedFulfillCnt, - expectedReleaseCnt, - !isVulkan, - reporter)); - - gpu->testingOnly_flushGpuAndSync(); - REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, - true, - expectedFulfillCnt, - expectedReleaseCnt, - true, - reporter)); - - canvas->drawImage(refImg, 0, 0); - canvas->drawImage(refImg, 0, 0); - - canvas->flush(); - expectedFulfillCnt++; - expectedReleaseCnt++; - - gpu->testingOnly_flushGpuAndSync(); - REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, - true, - expectedFulfillCnt, - expectedReleaseCnt, - true, - reporter)); - - // Now test code path on Vulkan where we released the texture, but the GPU isn't done with - // resource yet and we do another draw. We should only call fulfill on the first draw and - // use the cached GrBackendTexture on the second. Release should only be called after the second - // draw is finished. - canvas->drawImage(refImg, 0, 0); - canvas->flush(); - expectedFulfillCnt++; - expectedReleaseCnt++; - REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, - !isVulkan, - expectedFulfillCnt, - expectedReleaseCnt, - !isVulkan, - reporter)); - - canvas->drawImage(refImg, 0, 0); - canvas->flush(); - expectedFulfillCnt++; - - gpu->testingOnly_flushGpuAndSync(); - expectedReleaseCnt++; - REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, - true, - expectedFulfillCnt, - expectedReleaseCnt, - !isVulkan, - reporter)); - expectedFulfillCnt = promiseChecker.fFulfillCount; - expectedReleaseCnt = promiseChecker.fReleaseCount; - - refImg.reset(); - - REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, - true, - expectedFulfillCnt, - expectedReleaseCnt, - true, - reporter)); - - gpu->deleteTestingOnlyBackendTexture(backendTex); + for (bool releaseImageEarly : {true, false}) { + GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture( + nullptr, kWidth, kHeight, kRGBA_8888_GrPixelConfig, true, GrMipMapped::kNo); + REPORTER_ASSERT(reporter, backendTex.isValid()); + + GrBackendFormat backendFormat = backendTex.format(); + REPORTER_ASSERT(reporter, backendFormat.isValid()); + + PromiseTextureChecker promiseChecker(backendTex); + GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin; + sk_sp refImg( + SkImage_Gpu::MakePromiseTexture(ctx, backendFormat, kWidth, kHeight, + GrMipMapped::kNo, texOrigin, + kRGBA_8888_SkColorType, kPremul_SkAlphaType, + nullptr, + PromiseTextureChecker::Fulfill, + PromiseTextureChecker::Release, + PromiseTextureChecker::Done, + &promiseChecker)); + + SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight); + sk_sp surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info); + SkCanvas* canvas = surface->getCanvas(); + + int expectedFulfillCnt = 0; + int expectedReleaseCnt = 0; + int expectedDoneCnt = 0; + + canvas->drawImage(refImg, 0, 0); + REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, + true, + expectedFulfillCnt, + expectedReleaseCnt, + true, + expectedDoneCnt, + reporter)); + + bool isVulkan = kVulkan_GrBackend == ctx->contextPriv().getBackend(); + canvas->flush(); + expectedFulfillCnt++; + expectedReleaseCnt++; + REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, + !isVulkan, + expectedFulfillCnt, + expectedReleaseCnt, + !isVulkan, + expectedDoneCnt, + reporter)); + + gpu->testingOnly_flushGpuAndSync(); + REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, + true, + expectedFulfillCnt, + expectedReleaseCnt, + true, + expectedDoneCnt, + reporter)); + + canvas->drawImage(refImg, 0, 0); + canvas->drawImage(refImg, 0, 0); + + canvas->flush(); + expectedFulfillCnt++; + expectedReleaseCnt++; + + gpu->testingOnly_flushGpuAndSync(); + REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, + true, + expectedFulfillCnt, + expectedReleaseCnt, + true, + expectedDoneCnt, + reporter)); + + // Now test code path on Vulkan where we released the texture, but the GPU isn't done with + // resource yet and we do another draw. We should only call fulfill on the first draw and + // use the cached GrBackendTexture on the second. Release should only be called after the + // second draw is finished. + canvas->drawImage(refImg, 0, 0); + canvas->flush(); + expectedFulfillCnt++; + expectedReleaseCnt++; + REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, + !isVulkan, + expectedFulfillCnt, + expectedReleaseCnt, + !isVulkan, + expectedDoneCnt, + reporter)); + + canvas->drawImage(refImg, 0, 0); + + if (releaseImageEarly) { + refImg.reset(); + } + + REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, + !isVulkan, + expectedFulfillCnt, + expectedReleaseCnt, + !isVulkan, + expectedDoneCnt, + reporter)); + + canvas->flush(); + expectedFulfillCnt++; + + gpu->testingOnly_flushGpuAndSync(); + expectedReleaseCnt++; + if (releaseImageEarly) { + expectedDoneCnt++; + } + REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, + true, + expectedFulfillCnt, + expectedReleaseCnt, + !isVulkan, + expectedDoneCnt, + reporter)); + expectedFulfillCnt = promiseChecker.fFulfillCount; + expectedReleaseCnt = promiseChecker.fReleaseCount; + + if (!releaseImageEarly) { + refImg.reset(); + expectedDoneCnt++; + } + + REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker, + true, + expectedFulfillCnt, + expectedReleaseCnt, + true, + expectedDoneCnt, + reporter)); + + gpu->deleteTestingOnlyBackendTexture(backendTex); + } } #endif -- cgit v1.2.3