diff options
-rw-r--r-- | src/gpu/GrProcessor.h | 32 | ||||
-rw-r--r-- | tests/GLProgramsTest.cpp | 7 | ||||
-rw-r--r-- | tests/ImageStorageTest.cpp | 49 | ||||
-rw-r--r-- | tests/ProcessorTest.cpp | 236 |
4 files changed, 214 insertions, 110 deletions
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h index 2afebb72b1..e4bf5919ff 100644 --- a/src/gpu/GrProcessor.h +++ b/src/gpu/GrProcessor.h @@ -229,10 +229,14 @@ public: , fVisibility(that.fVisibility) {} TextureSampler(sk_sp<GrTextureProxy>, const GrSamplerParams&); + explicit TextureSampler(sk_sp<GrTextureProxy>, GrSamplerParams::FilterMode = GrSamplerParams::kNone_FilterMode, SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode, GrShaderFlags visibility = kFragment_GrShaderFlag); + + TextureSampler& operator=(const TextureSampler&) = delete; + void reset(sk_sp<GrTextureProxy>, const GrSamplerParams&, GrShaderFlags visibility = kFragment_GrShaderFlag); void reset(sk_sp<GrTextureProxy>, @@ -279,7 +283,7 @@ private: * Used to represent a texel buffer that will be read in a GrResourceIOProcessor. It holds a * GrBuffer along with an associated offset and texel config. */ -class GrResourceIOProcessor::BufferAccess : public SkNoncopyable { +class GrResourceIOProcessor::BufferAccess { public: BufferAccess() = default; BufferAccess(GrPixelConfig texelConfig, GrBuffer* buffer, @@ -287,6 +291,17 @@ public: this->reset(texelConfig, buffer, visibility); } /** + * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy + * always takes a new ref on the buffer proxy as the new fragment processor will not yet be + * in pending execution state. + */ + explicit BufferAccess(const BufferAccess& that) { + this->reset(that.fTexelConfig, that.fBuffer.get(), that.fVisibility); + } + + BufferAccess& operator=(const BufferAccess&) = delete; + + /** * Must be initialized before adding to a GrProcessor's buffer access list. */ void reset(GrPixelConfig texelConfig, GrBuffer* buffer, @@ -327,10 +342,23 @@ private: * Currently the format of the load/store data in the shader is inferred from the texture config, * though it could be made explicit. */ -class GrResourceIOProcessor::ImageStorageAccess : public SkNoncopyable { +class GrResourceIOProcessor::ImageStorageAccess { public: ImageStorageAccess(sk_sp<GrTextureProxy>, GrIOType, GrSLMemoryModel, GrSLRestrict, GrShaderFlags visibility = kFragment_GrShaderFlag); + /** + * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy + * always takes a new ref on the surface proxy as the new fragment processor will not yet be + * in pending execution state. + */ + explicit ImageStorageAccess(const ImageStorageAccess& that) + : fProxyRef(sk_ref_sp(that.fProxyRef.get()), that.fProxyRef.ioType()) + , fVisibility(that.fVisibility) + , fFormat(that.fFormat) + , fMemoryModel(that.fMemoryModel) + , fRestrict(that.fRestrict) {} + + ImageStorageAccess& operator=(const ImageStorageAccess&) = delete; bool operator==(const ImageStorageAccess& that) const { return this->proxy() == that.proxy() && fVisibility == that.fVisibility; diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 8b07568fdc..aca548cdf8 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -75,6 +75,8 @@ public: return new GLBigKeyProcessor; } + sk_sp<GrFragmentProcessor> clone() const override { return Make(); } + private: BigKeyProcessor() : INHERITED(kNone_OptimizationFlags) { this->initClassID<BigKeyProcessor>(); } virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps, @@ -108,6 +110,11 @@ public: GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLFP; } + sk_sp<GrFragmentProcessor> clone() const override { + auto child = this->childProcessor(0).clone(); + return child ? Make(std::move(child)) : nullptr; + } + private: class GLFP : public GrGLSLFragmentProcessor { public: diff --git a/tests/ImageStorageTest.cpp b/tests/ImageStorageTest.cpp index f55553c518..9a5f8962fb 100644 --- a/tests/ImageStorageTest.cpp +++ b/tests/ImageStorageTest.cpp @@ -27,6 +27,10 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) { const char* name() const override { return "Image Load Test FP"; } + sk_sp<GrFragmentProcessor> clone() const override { + return sk_sp<GrFragmentProcessor>(new TestFP(*this)); + } + private: TestFP(sk_sp<GrTextureProxy> proxy, GrSLMemoryModel mm, GrSLRestrict restrict) : INHERITED(kNone_OptimizationFlags) @@ -35,6 +39,13 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) { this->addImageStorageAccess(&fImageStorageAccess); } + explicit TestFP(const TestFP& that) + : INHERITED(that.optimizationFlags()) + , fImageStorageAccess(that.fImageStorageAccess) { + this->initClassID<TestFP>(); + this->addImageStorageAccess(&fImageStorageAccess); + } + void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {} bool onIsEqual(const GrFragmentProcessor& that) const override { return true; } @@ -134,22 +145,28 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) { sk_sp<GrRenderTargetContext> rtContext = context->makeDeferredRenderTargetContext(SkBackingFit::kExact, kS, kS, kRGBA_8888_GrPixelConfig, nullptr); - GrPaint paint; - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); - paint.addColorFragmentProcessor(TestFP::Make(imageStorageTexture, mm, restrict)); - rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I()); - std::unique_ptr<uint32_t[]> readData(new uint32_t[kS * kS]); - SkImageInfo info = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType, - kPremul_SkAlphaType); - rtContext->readPixels(info, readData.get(), 0, 0, 0); - int failed = false; - for (int j = 0; j < kS && !failed; ++j) { - for (int i = 0; i < kS && !failed; ++i) { - uint32_t d = test.fData[j * kS + i]; - uint32_t rd = readData[j * kS + i]; - if (d != rd) { - failed = true; - ERRORF(reporter, "Expected 0x%08x, got 0x%08x at %d, %d.", d, rd, i, j); + // We make a clone to test that copying GrFragmentProcessor::ImageStorageAccess + // copying works. + auto testFP = TestFP::Make(imageStorageTexture, mm, restrict); + for (auto fp : {testFP, testFP->clone()}) { + GrPaint paint; + paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.addColorFragmentProcessor(fp); + rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I()); + std::unique_ptr<uint32_t[]> readData(new uint32_t[kS * kS]); + SkImageInfo info = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType, + kPremul_SkAlphaType); + rtContext->readPixels(info, readData.get(), 0, 0, 0); + int failed = false; + for (int j = 0; j < kS && !failed; ++j) { + for (int i = 0; i < kS && !failed; ++i) { + uint32_t d = test.fData[j * kS + i]; + uint32_t rd = readData[j * kS + i]; + if (d != rd) { + failed = true; + ERRORF(reporter, "Expected 0x%08x, got 0x%08x at %d, %d.", + d, rd, i, j); + } } } } diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp index ec157f9003..3bfd62e3a4 100644 --- a/tests/ProcessorTest.cpp +++ b/tests/ProcessorTest.cpp @@ -83,11 +83,24 @@ public: b->add32(sk_atomic_inc(&gKey)); } + sk_sp<GrFragmentProcessor> clone() const override { + sk_sp<GrFragmentProcessor> child; + if (this->numChildProcessors()) { + SkASSERT(1 == this->numChildProcessors()); + child = this->childProcessor(0).clone(); + if (!child) { + return nullptr; + } + } + return sk_sp<GrFragmentProcessor> (new TestFP(*this, std::move(child))); + } + private: TestFP(const SkTArray<sk_sp<GrTextureProxy>>& proxies, const SkTArray<sk_sp<GrBuffer>>& buffers, const SkTArray<Image>& images) : INHERITED(kNone_OptimizationFlags), fSamplers(4), fBuffers(4), fImages(4) { + this->initClassID<TestFP>(); for (const auto& proxy : proxies) { this->addTextureSampler(&fSamplers.emplace_back(proxy)); } @@ -103,9 +116,30 @@ private: TestFP(sk_sp<GrFragmentProcessor> child) : INHERITED(kNone_OptimizationFlags), fSamplers(4), fBuffers(4), fImages(4) { + this->initClassID<TestFP>(); this->registerChildProcessor(std::move(child)); } + explicit TestFP(const TestFP& that, sk_sp<GrFragmentProcessor> child) + : INHERITED(that.optimizationFlags()), fSamplers(4), fBuffers(4), fImages(4) { + this->initClassID<TestFP>(); + for (int i = 0; i < that.fSamplers.count(); ++i) { + fSamplers.emplace_back(that.fSamplers[i]); + this->addTextureSampler(&fSamplers.back()); + } + for (int i = 0; i < that.fBuffers.count(); ++i) { + fBuffers.emplace_back(that.fBuffers[i]); + this->addBufferAccess(&fBuffers.back()); + } + for (int i = 0; i < that.fImages.count(); ++i) { + fImages.emplace_back(that.fImages[i]); + this->addImageStorageAccess(&fImages.back()); + } + if (child) { + this->registerChildProcessor(std::move(child)); + } + } + virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { class TestGLSLFP : public GrGLSLFragmentProcessor { public: @@ -151,109 +185,127 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(ProcessorRefTest, reporter, ctxInfo) { desc.fHeight = 10; desc.fConfig = kRGBA_8888_GrPixelConfig; - for (int parentCnt = 0; parentCnt < 2; parentCnt++) { - sk_sp<GrRenderTargetContext> renderTargetContext(context->makeDeferredRenderTargetContext( - SkBackingFit::kApprox, 1, 1, kRGBA_8888_GrPixelConfig, nullptr)); - { - bool texelBufferSupport = context->caps()->shaderCaps()->texelBufferSupport(); - bool imageLoadStoreSupport = context->caps()->shaderCaps()->imageLoadStoreSupport(); - sk_sp<GrTextureProxy> proxy1(GrSurfaceProxy::MakeDeferred(context->resourceProvider(), - desc, SkBackingFit::kExact, - SkBudgeted::kYes)); - sk_sp<GrTextureProxy> proxy2(GrSurfaceProxy::MakeDeferred(context->resourceProvider(), - desc, SkBackingFit::kExact, - SkBudgeted::kYes)); - sk_sp<GrTextureProxy> proxy3(GrSurfaceProxy::MakeDeferred(context->resourceProvider(), - desc, SkBackingFit::kExact, - SkBudgeted::kYes)); - sk_sp<GrTextureProxy> proxy4(GrSurfaceProxy::MakeDeferred(context->resourceProvider(), - desc, SkBackingFit::kExact, - SkBudgeted::kYes)); - sk_sp<GrBuffer> buffer(texelBufferSupport - ? context->resourceProvider()->createBuffer( - 1024, GrBufferType::kTexel_GrBufferType, - GrAccessPattern::kStatic_GrAccessPattern, 0) - : nullptr); + for (bool makeClone : {false, true}) { + for (int parentCnt = 0; parentCnt < 2; parentCnt++) { + sk_sp<GrRenderTargetContext> renderTargetContext( + context->makeDeferredRenderTargetContext( SkBackingFit::kApprox, 1, 1, + kRGBA_8888_GrPixelConfig, nullptr)); { - SkTArray<sk_sp<GrTextureProxy>> proxies; - SkTArray<sk_sp<GrBuffer>> buffers; - SkTArray<TestFP::Image> images; - proxies.push_back(proxy1); - if (texelBufferSupport) { - buffers.push_back(buffer); - } - if (imageLoadStoreSupport) { - images.emplace_back(proxy2, GrIOType::kRead_GrIOType); - images.emplace_back(proxy3, GrIOType::kWrite_GrIOType); - images.emplace_back(proxy4, GrIOType::kRW_GrIOType); - } - auto fp = TestFP::Make(std::move(proxies), std::move(buffers), std::move(images)); - for (int i = 0; i < parentCnt; ++i) { - fp = TestFP::Make(std::move(fp)); + bool texelBufferSupport = context->caps()->shaderCaps()->texelBufferSupport(); + bool imageLoadStoreSupport = context->caps()->shaderCaps()->imageLoadStoreSupport(); + sk_sp<GrTextureProxy> proxy1( + GrSurfaceProxy::MakeDeferred(context->resourceProvider(), + desc, SkBackingFit::kExact, + SkBudgeted::kYes)); + sk_sp<GrTextureProxy> proxy2 + (GrSurfaceProxy::MakeDeferred(context->resourceProvider(), + desc, SkBackingFit::kExact, + SkBudgeted::kYes)); + sk_sp<GrTextureProxy> proxy3( + GrSurfaceProxy::MakeDeferred(context->resourceProvider(), + desc, SkBackingFit::kExact, + SkBudgeted::kYes)); + sk_sp<GrTextureProxy> proxy4( + GrSurfaceProxy::MakeDeferred(context->resourceProvider(), + desc, SkBackingFit::kExact, + SkBudgeted::kYes)); + sk_sp<GrBuffer> buffer(texelBufferSupport + ? context->resourceProvider()->createBuffer( + 1024, GrBufferType::kTexel_GrBufferType, + GrAccessPattern::kStatic_GrAccessPattern, 0) + : nullptr); + { + SkTArray<sk_sp<GrTextureProxy>> proxies; + SkTArray<sk_sp<GrBuffer>> buffers; + SkTArray<TestFP::Image> images; + proxies.push_back(proxy1); + if (texelBufferSupport) { + buffers.push_back(buffer); + } + if (imageLoadStoreSupport) { + images.emplace_back(proxy2, GrIOType::kRead_GrIOType); + images.emplace_back(proxy3, GrIOType::kWrite_GrIOType); + images.emplace_back(proxy4, GrIOType::kRW_GrIOType); + } + auto fp = TestFP::Make(std::move(proxies), std::move(buffers), + std::move(images)); + for (int i = 0; i < parentCnt; ++i) { + fp = TestFP::Make(std::move(fp)); + } + sk_sp<GrFragmentProcessor> clone; + if (makeClone) { + clone = fp->clone(); + } + std::unique_ptr<GrDrawOp> op(TestOp::Make(std::move(fp))); + renderTargetContext->priv().testingOnly_addDrawOp(std::move(op)); + if (clone) { + op = TestOp::Make(std::move(clone)); + renderTargetContext->priv().testingOnly_addDrawOp(std::move(op)); + } } - std::unique_ptr<GrDrawOp> op(TestOp::Make(std::move(fp))); - renderTargetContext->priv().testingOnly_addDrawOp(std::move(op)); - } - int refCnt, readCnt, writeCnt; + int refCnt, readCnt, writeCnt; - testingOnly_getIORefCnts(proxy1.get(), &refCnt, &readCnt, &writeCnt); - REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 1 == readCnt); - REPORTER_ASSERT(reporter, 0 == writeCnt); - - if (texelBufferSupport) { - testingOnly_getIORefCnts(buffer.get(), &refCnt, &readCnt, &writeCnt); - REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 1 == readCnt); - REPORTER_ASSERT(reporter, 0 == writeCnt); - } - - if (imageLoadStoreSupport) { - testingOnly_getIORefCnts(proxy2.get(), &refCnt, &readCnt, &writeCnt); - REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 1 == readCnt); - REPORTER_ASSERT(reporter, 0 == writeCnt); - - testingOnly_getIORefCnts(proxy3.get(), &refCnt, &readCnt, &writeCnt); + testingOnly_getIORefCnts(proxy1.get(), &refCnt, &readCnt, &writeCnt); + // IO counts should be double if there is a clone of the FP. + int ioRefMul = makeClone ? 2 : 1; REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 0 == readCnt); - REPORTER_ASSERT(reporter, 1 == writeCnt); + REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt); - testingOnly_getIORefCnts(proxy4.get(), &refCnt, &readCnt, &writeCnt); - REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 1 == readCnt); - REPORTER_ASSERT(reporter, 1 == writeCnt); - } - - context->flush(); + if (texelBufferSupport) { + testingOnly_getIORefCnts(buffer.get(), &refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt); + } - testingOnly_getIORefCnts(proxy1.get(), &refCnt, &readCnt, &writeCnt); - REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 0 == readCnt); - REPORTER_ASSERT(reporter, 0 == writeCnt); + if (imageLoadStoreSupport) { + testingOnly_getIORefCnts(proxy2.get(), &refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt); + + testingOnly_getIORefCnts(proxy3.get(), &refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 1 == writeCnt); + + testingOnly_getIORefCnts(proxy4.get(), &refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 1 == writeCnt); + } - if (texelBufferSupport) { - testingOnly_getIORefCnts(buffer.get(), &refCnt, &readCnt, &writeCnt); - REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 0 == readCnt); - REPORTER_ASSERT(reporter, 0 == writeCnt); - } + context->flush(); - if (texelBufferSupport) { - testingOnly_getIORefCnts(proxy2.get(), &refCnt, &readCnt, &writeCnt); + testingOnly_getIORefCnts(proxy1.get(), &refCnt, &readCnt, &writeCnt); REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 0 == readCnt); - REPORTER_ASSERT(reporter, 0 == writeCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt); - testingOnly_getIORefCnts(proxy3.get(), &refCnt, &readCnt, &writeCnt); - REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 0 == readCnt); - REPORTER_ASSERT(reporter, 0 == writeCnt); + if (texelBufferSupport) { + testingOnly_getIORefCnts(buffer.get(), &refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt); + } - testingOnly_getIORefCnts(proxy4.get(), &refCnt, &readCnt, &writeCnt); - REPORTER_ASSERT(reporter, 1 == refCnt); - REPORTER_ASSERT(reporter, 0 == readCnt); - REPORTER_ASSERT(reporter, 0 == writeCnt); + if (texelBufferSupport) { + testingOnly_getIORefCnts(proxy2.get(), &refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt); + + testingOnly_getIORefCnts(proxy3.get(), &refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt); + + testingOnly_getIORefCnts(proxy4.get(), &refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt); + REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt); + } } } } |