diff options
-rw-r--r-- | gn/tests.gni | 1 | ||||
-rw-r--r-- | include/gpu/GrGpuResource.h | 2 | ||||
-rw-r--r-- | include/gpu/GrProcessor.h | 5 | ||||
-rw-r--r-- | src/gpu/GrAllocator.h | 7 | ||||
-rw-r--r-- | src/gpu/GrResourceProvider.h | 1 | ||||
-rw-r--r-- | tests/ProcessorTest.cpp | 233 |
6 files changed, 249 insertions, 0 deletions
diff --git a/gn/tests.gni b/gn/tests.gni index 95e1a7980c..65b79ab8f6 100644 --- a/gn/tests.gni +++ b/gn/tests.gni @@ -160,6 +160,7 @@ tests_sources = [ "$_tests/PointTest.cpp", "$_tests/PremulAlphaRoundTripTest.cpp", "$_tests/PrimitiveProcessorTest.cpp", + "$_tests/ProcessorTest.cpp", "$_tests/ProxyConversionTest.cpp", "$_tests/ProxyRefTest.cpp", "$_tests/ProxyTest.cpp", diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h index 29d33df4bd..32376e524b 100644 --- a/include/gpu/GrGpuResource.h +++ b/include/gpu/GrGpuResource.h @@ -75,6 +75,8 @@ public: #endif } + void testingOnly_getCounts(int* refCnt, int* readCnt, int* writeCnt) const; + protected: GrIORef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0) { } diff --git a/include/gpu/GrProcessor.h b/include/gpu/GrProcessor.h index f0f895f3c2..32995c308b 100644 --- a/include/gpu/GrProcessor.h +++ b/include/gpu/GrProcessor.h @@ -252,6 +252,11 @@ private: */ class GrProcessor::BufferAccess : public SkNoncopyable { public: + BufferAccess() = default; + BufferAccess(GrPixelConfig texelConfig, GrBuffer* buffer, + GrShaderFlags visibility = kFragment_GrShaderFlag) { + this->reset(texelConfig, buffer, visibility); + } /** * Must be initialized before adding to a GrProcessor's buffer access list. */ diff --git a/src/gpu/GrAllocator.h b/src/gpu/GrAllocator.h index 5b9bd5bab9..e5d2f4ea61 100644 --- a/src/gpu/GrAllocator.h +++ b/src/gpu/GrAllocator.h @@ -258,6 +258,13 @@ public: return *(T*)item; } + template <typename... Args> T& emplace_back(Args&&... args) { + void* item = fAllocator.push_back(); + SkASSERT(item); + new (item) T(std::forward<Args>(args)...); + return *(T*)item; + } + /** * Remove the last item, only call if count() != 0 */ diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h index 58bd1f8c3c..47490e14de 100644 --- a/src/gpu/GrResourceProvider.h +++ b/src/gpu/GrResourceProvider.h @@ -89,6 +89,7 @@ public: GrPathRange* createGlyphs(const SkTypeface*, const SkScalerContextEffects&, const SkDescriptor*, const GrStyle&); + using GrTextureProvider::createTexture; using GrTextureProvider::assignUniqueKeyToResource; using GrTextureProvider::findAndRefResourceByUniqueKey; using GrTextureProvider::findAndRefTextureByUniqueKey; diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp new file mode 100644 index 0000000000..b6cacccb95 --- /dev/null +++ b/tests/ProcessorTest.cpp @@ -0,0 +1,233 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkTypes.h" +#include "Test.h" + +#if SK_SUPPORT_GPU +#include "GrContext.h" +#include "GrGpuResource.h" +#include "GrRenderTargetContext.h" +#include "GrRenderTargetContextPriv.h" +#include "GrResourceProvider.h" +#include "glsl/GrGLSLFragmentProcessor.h" +#include "glsl/GrGLSLFragmentShaderBuilder.h" +#include "ops/GrTestMeshDrawOp.h" + +namespace { +class TestOp : public GrTestMeshDrawOp { +public: + DEFINE_OP_CLASS_ID + const char* name() const override { return "TestOp"; } + + static std::unique_ptr<GrDrawOp> Make() { return std::unique_ptr<GrDrawOp>(new TestOp); } + +private: + TestOp() : INHERITED(ClassID(), SkRect::MakeWH(100, 100), 0xFFFFFFFF) {} + + void onPrepareDraws(Target* target) const override { return; } + + typedef GrTestMeshDrawOp INHERITED; +}; + +/** + * FP used to test ref/IO counts on owned GrGpuResources. Can also be a parent FP to test counts + * of resources owned by child FPs. + */ +class TestFP : public GrFragmentProcessor { +public: + struct Image { + Image(sk_sp<GrTexture> texture, GrIOType ioType) : fTexture(texture), fIOType(ioType) {} + sk_sp<GrTexture> fTexture; + GrIOType fIOType; + }; + static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor> child) { + return sk_sp<GrFragmentProcessor>(new TestFP(std::move(child))); + } + static sk_sp<GrFragmentProcessor> Make(const SkTArray<sk_sp<GrTexture>>& textures, + const SkTArray<sk_sp<GrBuffer>>& buffers, + const SkTArray<Image>& images) { + return sk_sp<GrFragmentProcessor>(new TestFP(textures, buffers, images)); + } + + const char* name() const override { return "test"; } + + void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { + // We don't really care about reusing these. + static int32_t gKey = 0; + b->add32(sk_atomic_inc(&gKey)); + } + + void onComputeInvariantOutput(GrInvariantOutput* inout) const override { + // We don't care about optimizing these processors. + inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); + } + +private: + TestFP(const SkTArray<sk_sp<GrTexture>>& textures, const SkTArray<sk_sp<GrBuffer>>& buffers, + const SkTArray<Image>& images) + : fSamplers(4), fBuffers(4), fImages(4) { + for (const auto& texture : textures) { + this->addTextureSampler(&fSamplers.emplace_back(texture.get())); + } + for (const auto& buffer : buffers) { + this->addBufferAccess(&fBuffers.emplace_back(kRGBA_8888_GrPixelConfig, buffer.get())); + } + for (const Image& image : images) { + this->addImageStorageAccess(&fImages.emplace_back( + image.fTexture, image.fIOType, GrSLMemoryModel::kNone, GrSLRestrict::kNo)); + } + } + + TestFP(sk_sp<GrFragmentProcessor> child) : fSamplers(4), fBuffers(4), fImages(4) { + this->registerChildProcessor(std::move(child)); + } + + virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { + class TestGLSLFP : public GrGLSLFragmentProcessor { + public: + TestGLSLFP() {} + void emitCode(EmitArgs& args) override { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor); + } + + private: + }; + return new TestGLSLFP(); + } + + bool onIsEqual(const GrFragmentProcessor&) const override { return false; } + + GrTAllocator<TextureSampler> fSamplers; + GrTAllocator<BufferAccess> fBuffers; + GrTAllocator<ImageStorageAccess> fImages; +}; +} + +template <typename D> +inline void GrIORef<D>::testingOnly_getCounts(int* refCnt, int* readCnt, int* writeCnt) const { + *refCnt = fRefCnt; + *readCnt = fPendingReads; + *writeCnt = fPendingWrites; +} + +DEF_GPUTEST_FOR_ALL_CONTEXTS(ProcessorRefTest, reporter, ctxInfo) { + GrContext* context = ctxInfo.grContext(); + + GrTextureDesc desc; + desc.fConfig = kRGBA_8888_GrPixelConfig; + desc.fWidth = 10; + desc.fHeight = 10; + + for (int parentCnt = 0; parentCnt < 2; parentCnt++) { + sk_sp<GrRenderTargetContext> renderTargetContext(context->makeRenderTargetContext( + SkBackingFit::kApprox, 1, 1, kRGBA_8888_GrPixelConfig, nullptr)); + { + bool texelBufferSupport = context->caps()->shaderCaps()->texelBufferSupport(); + bool imageLoadStoreSupport = context->caps()->shaderCaps()->imageLoadStoreSupport(); + sk_sp<GrTexture> texture1( + context->resourceProvider()->createTexture(desc, SkBudgeted::kYes)); + sk_sp<GrTexture> texture2( + context->resourceProvider()->createTexture(desc, SkBudgeted::kYes)); + sk_sp<GrTexture> texture3( + context->resourceProvider()->createTexture(desc, SkBudgeted::kYes)); + sk_sp<GrTexture> texture4( + context->resourceProvider()->createTexture(desc, SkBudgeted::kYes)); + sk_sp<GrBuffer> buffer(texelBufferSupport + ? context->resourceProvider()->createBuffer( + 1024, GrBufferType::kTexel_GrBufferType, + GrAccessPattern::kStatic_GrAccessPattern, 0) + : nullptr); + { + SkTArray<sk_sp<GrTexture>> textures; + SkTArray<sk_sp<GrBuffer>> buffers; + SkTArray<TestFP::Image> images; + textures.push_back(texture1); + if (texelBufferSupport) { + buffers.push_back(buffer); + } + if (imageLoadStoreSupport) { + images.emplace_back(texture2, GrIOType::kRead_GrIOType); + images.emplace_back(texture3, GrIOType::kWrite_GrIOType); + images.emplace_back(texture4, GrIOType::kRW_GrIOType); + } + std::unique_ptr<GrDrawOp> op(TestOp::Make()); + GrPaint paint; + auto fp = TestFP::Make(std::move(textures), std::move(buffers), std::move(images)); + for (int i = 0; i < parentCnt; ++i) { + fp = TestFP::Make(std::move(fp)); + } + paint.addColorFragmentProcessor(std::move(fp)); + renderTargetContext->priv().testingOnly_addDrawOp(paint, GrAAType::kNone, + std::move(op)); + } + int refCnt, readCnt, writeCnt; + + texture1->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 1 == readCnt); + REPORTER_ASSERT(reporter, 0 == writeCnt); + + if (texelBufferSupport) { + buffer->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 1 == readCnt); + REPORTER_ASSERT(reporter, 0 == writeCnt); + } + + if (imageLoadStoreSupport) { + texture2->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 1 == readCnt); + REPORTER_ASSERT(reporter, 0 == writeCnt); + + texture3->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 0 == readCnt); + REPORTER_ASSERT(reporter, 1 == writeCnt); + + texture4->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 1 == readCnt); + REPORTER_ASSERT(reporter, 1 == writeCnt); + } + + context->flush(); + + texture1->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 0 == readCnt); + REPORTER_ASSERT(reporter, 0 == writeCnt); + + if (texelBufferSupport) { + buffer->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 0 == readCnt); + REPORTER_ASSERT(reporter, 0 == writeCnt); + } + + if (texelBufferSupport) { + texture2->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 0 == readCnt); + REPORTER_ASSERT(reporter, 0 == writeCnt); + + texture3->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 0 == readCnt); + REPORTER_ASSERT(reporter, 0 == writeCnt); + + texture4->testingOnly_getCounts(&refCnt, &readCnt, &writeCnt); + REPORTER_ASSERT(reporter, 1 == refCnt); + REPORTER_ASSERT(reporter, 0 == readCnt); + REPORTER_ASSERT(reporter, 0 == writeCnt); + } + } + } +} +#endif |