diff options
author | Chris Dalton <csmartdalton@google.com> | 2017-06-06 12:27:16 -0600 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-06-07 18:26:11 +0000 |
commit | 46983b7dd88603bb2a9a3c3e1ce3e147f5615f2f (patch) | |
tree | cb2dccc7b6d44b1100dc34af92c60d7b243d01c7 /tests | |
parent | 912e6b883782cd6a53348056012ff7ed38658c79 (diff) |
Introduce dynamic pipeline state
Adds a DynamicState struct to GrPipeline that has a field for the
scissor rect. Eventually this should become the only way to specify a
scissor rectangle and may grow to contain more fields. Adds an array of
DynamicStates to GrGpuCommandBuffer::draw and implements support in GL
and Vulkan.
Bug: skia:
Change-Id: If5aebbf9da5d192acf7e68e7def4674ffc7ec310
Reviewed-on: https://skia-review.googlesource.com/18510
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/GpuSampleLocationsTest.cpp | 14 | ||||
-rw-r--r-- | tests/GrMeshTest.cpp | 4 | ||||
-rw-r--r-- | tests/GrPipelineDynamicStateTest.cpp | 219 |
3 files changed, 227 insertions, 10 deletions
diff --git a/tests/GpuSampleLocationsTest.cpp b/tests/GpuSampleLocationsTest.cpp index 75d2846dd6..aaab98adda 100644 --- a/tests/GpuSampleLocationsTest.cpp +++ b/tests/GpuSampleLocationsTest.cpp @@ -91,10 +91,6 @@ public: virtual ~TestSampleLocationsInterface() {} }; -static sk_sp<GrPipeline> construct_dummy_pipeline(GrRenderTargetContext* dc) { - return sk_sp<GrPipeline>(new GrPipeline(dc->accessRenderTarget(), SkBlendMode::kSrcOver)); -} - void assert_equal(skiatest::Reporter* reporter, const SamplePattern& pattern, const GrGpu::MultisampleSpecs& specs, bool flipY) { GrAlwaysAssert(specs.fSampleLocations); @@ -136,11 +132,13 @@ void test_sampleLocations(skiatest::Reporter* reporter, TestSampleLocationsInter for (int repeat = 0; repeat < 2; ++repeat) { for (int i = 0; i < numTestPatterns; ++i) { testInterface->overrideSamplePattern(kTestPatterns[i]); - for (GrRenderTargetContext* dc : {bottomUps[i].get(), topDowns[i].get()}) { - sk_sp<GrPipeline> dummyPipeline = construct_dummy_pipeline(dc); - GrRenderTarget* rt = dc->accessRenderTarget(); + for (GrRenderTargetContext* rtc : {bottomUps[i].get(), topDowns[i].get()}) { + GrPipeline dummyPipeline(rtc->accessRenderTarget(), + GrPipeline::ScissorState::kDisabled, + SkBlendMode::kSrcOver); + GrRenderTarget* rt = rtc->accessRenderTarget(); assert_equal(reporter, kTestPatterns[i], - rt->renderTargetPriv().getMultisampleSpecs(*dummyPipeline), + rt->renderTargetPriv().getMultisampleSpecs(dummyPipeline), kBottomLeft_GrSurfaceOrigin == rt->origin()); } } diff --git a/tests/GrMeshTest.cpp b/tests/GrMeshTest.cpp index 3a2be784a5..dd2a2d9e33 100644 --- a/tests/GrMeshTest.cpp +++ b/tests/GrMeshTest.cpp @@ -364,9 +364,9 @@ sk_sp<const GrBuffer> DrawMeshHelper::getIndexBuffer() { void DrawMeshHelper::drawMesh(const GrMesh& mesh) { GrRenderTarget* rt = fState->drawOpArgs().fRenderTarget; - GrPipeline pipeline(rt, SkBlendMode::kSrc); + GrPipeline pipeline(rt, GrPipeline::ScissorState::kDisabled, SkBlendMode::kSrc); GrMeshTestProcessor mtp(mesh.isInstanced(), mesh.hasVertexData()); - fState->commandBuffer()->draw(pipeline, mtp, &mesh, 1, + fState->commandBuffer()->draw(pipeline, mtp, &mesh, nullptr, 1, SkRect::MakeIWH(kImageWidth, kImageHeight)); } diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp new file mode 100644 index 0000000000..4c5843aeb1 --- /dev/null +++ b/tests/GrPipelineDynamicStateTest.cpp @@ -0,0 +1,219 @@ +/* + * Copyright 2017 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 "GrColor.h" +#include "GrGeometryProcessor.h" +#include "GrOpFlushState.h" +#include "GrRenderTargetContext.h" +#include "GrRenderTargetContextPriv.h" +#include "GrResourceProvider.h" +#include "SkMakeUnique.h" +#include "glsl/GrGLSLVertexShaderBuilder.h" +#include "glsl/GrGLSLFragmentShaderBuilder.h" +#include "glsl/GrGLSLGeometryProcessor.h" +#include "glsl/GrGLSLVarying.h" + +/** + * This is a GPU-backend specific test for dynamic pipeline state. It draws boxes using dynamic + * scissor rectangles then reads back the result to verify a successful test. + */ + +using ScissorState = GrPipeline::ScissorState; + +static constexpr int kScreenSize = 6; +static constexpr int kNumMeshes = 4; +static constexpr int kScreenSplitX = kScreenSize/2; +static constexpr int kScreenSplitY = kScreenSize/2; + +static const GrPipeline::DynamicState kDynamicStates[kNumMeshes] = { + {SkIRect::MakeLTRB(0, 0, kScreenSplitX, kScreenSplitY)}, + {SkIRect::MakeLTRB(0, kScreenSplitY, kScreenSplitX, kScreenSize)}, + {SkIRect::MakeLTRB(kScreenSplitX, 0, kScreenSize, kScreenSplitY)}, + {SkIRect::MakeLTRB(kScreenSplitX, kScreenSplitY, kScreenSize, kScreenSize)}, +}; + +static const GrColor kMeshColors[kNumMeshes] { + GrColorPackRGBA(255, 0, 0, 255), + GrColorPackRGBA(0, 255, 0, 255), + GrColorPackRGBA(0, 0, 255, 255), + GrColorPackRGBA(0, 0, 0, 255) +}; + +struct Vertex { + float fX; + float fY; + GrColor fColor; +}; + +class GrPipelineDynamicStateTestProcessor : public GrGeometryProcessor { +public: + GrPipelineDynamicStateTestProcessor() + : fVertex(this->addVertexAttrib("vertex", kVec2f_GrVertexAttribType)) + , fColor(this->addVertexAttrib("color", kVec4ub_GrVertexAttribType)) { + this->initClassID<GrPipelineDynamicStateTestProcessor>(); + } + + const char* name() const override { return "GrPipelineDynamicStateTest Processor"; } + + void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const final {} + + GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final; + +protected: + const Attribute& fVertex; + const Attribute& fColor; + + friend class GLSLPipelineDynamicStateTestProcessor; + typedef GrGeometryProcessor INHERITED; +}; + +class GLSLPipelineDynamicStateTestProcessor : public GrGLSLGeometryProcessor { + void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&, + FPCoordTransformIter&& transformIter) final {} + + void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final { + const GrPipelineDynamicStateTestProcessor& mp = + args.fGP.cast<GrPipelineDynamicStateTestProcessor>(); + + GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; + varyingHandler->emitAttributes(mp); + varyingHandler->addPassThroughAttribute(&mp.fColor, args.fOutputColor); + + GrGLSLVertexBuilder* v = args.fVertBuilder; + v->codeAppendf("vec2 vertex = %s;", mp.fVertex.fName); + gpArgs->fPositionVar.set(kVec2f_GrSLType, "vertex"); + + GrGLSLPPFragmentBuilder* f = args.fFragBuilder; + f->codeAppendf("%s = vec4(1);", args.fOutputCoverage); + } +}; + +GrGLSLPrimitiveProcessor* +GrPipelineDynamicStateTestProcessor::createGLSLInstance(const GrShaderCaps&) const { + return new GLSLPipelineDynamicStateTestProcessor; +} + +class GrPipelineDynamicStateTestOp : public GrDrawOp { +public: + DEFINE_OP_CLASS_ID + + GrPipelineDynamicStateTestOp(ScissorState scissorState, sk_sp<const GrBuffer> vbuff) + : INHERITED(ClassID()) + , fScissorState(scissorState) + , fVertexBuffer(std::move(vbuff)) { + this->setBounds(SkRect::MakeIWH(kScreenSize, kScreenSize), + HasAABloat::kNo, IsZeroArea::kNo); + } + +private: + const char* name() const override { return "GrPipelineDynamicStateTestOp"; } + FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } + bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override { return false; } + bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override { return false; } + void onPrepare(GrOpFlushState*) override {} + void onExecute(GrOpFlushState* state) override { + GrRenderTarget* rt = state->drawOpArgs().fRenderTarget; + GrPipeline pipeline(rt, fScissorState, SkBlendMode::kSrc); + SkSTArray<kNumMeshes, GrMesh> meshes; + for (int i = 0; i < kNumMeshes; ++i) { + GrMesh& mesh = meshes.emplace_back(kTriangleStrip_GrPrimitiveType); + mesh.setNonIndexedNonInstanced(4); + mesh.setVertexData(fVertexBuffer.get(), 4 * i); + } + state->commandBuffer()->draw(pipeline, GrPipelineDynamicStateTestProcessor(), + meshes.begin(), kDynamicStates, 4, + SkRect::MakeIWH(kScreenSize, kScreenSize)); + } + + ScissorState fScissorState; + const sk_sp<const GrBuffer> fVertexBuffer; + + typedef GrDrawOp INHERITED; +}; + +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrPipelineDynamicStateTest, reporter, ctxInfo) { + GrContext* const context = ctxInfo.grContext(); + GrResourceProvider* rp = context->resourceProvider(); + + sk_sp<GrRenderTargetContext> rtc( + context->makeDeferredRenderTargetContext(SkBackingFit::kExact, kScreenSize, kScreenSize, + kRGBA_8888_GrPixelConfig, nullptr)); + if (!rtc) { + ERRORF(reporter, "could not create render target context."); + return; + } + + constexpr float d = (float) kScreenSize; + Vertex vdata[kNumMeshes * 4] = { + {0, 0, kMeshColors[0]}, + {0, d, kMeshColors[0]}, + {d, 0, kMeshColors[0]}, + {d, d, kMeshColors[0]}, + + {0, 0, kMeshColors[1]}, + {0, d, kMeshColors[1]}, + {d, 0, kMeshColors[1]}, + {d, d, kMeshColors[1]}, + + {0, 0, kMeshColors[2]}, + {0, d, kMeshColors[2]}, + {d, 0, kMeshColors[2]}, + {d, d, kMeshColors[2]}, + + {0, 0, kMeshColors[3]}, + {0, d, kMeshColors[3]}, + {d, 0, kMeshColors[3]}, + {d, d, kMeshColors[3]} + }; + + sk_sp<const GrBuffer> vbuff(rp->createBuffer(sizeof(vdata), kVertex_GrBufferType, + kDynamic_GrAccessPattern, + GrResourceProvider::kNoPendingIO_Flag | + GrResourceProvider::kRequireGpuMemory_Flag, + vdata)); + if (!vbuff) { + ERRORF(reporter, "vbuff is null."); + return; + } + + uint32_t resultPx[kScreenSize * kScreenSize]; + + for (ScissorState scissorState : {ScissorState::kEnabled, ScissorState::kDisabled}) { + rtc->clear(nullptr, 0xbaaaaaad, true); + rtc->priv().testingOnly_addDrawOp( + skstd::make_unique<GrPipelineDynamicStateTestOp>(scissorState, vbuff)); + rtc->readPixels(SkImageInfo::Make(kScreenSize, kScreenSize, + kRGBA_8888_SkColorType, kPremul_SkAlphaType), + resultPx, 4 * kScreenSize, 0, 0, 0); + for (int y = 0; y < kScreenSize; ++y) { + for (int x = 0; x < kScreenSize; ++x) { + int expectedColorIdx; + if (ScissorState::kEnabled == scissorState) { + expectedColorIdx = (x < kScreenSplitX ? 0 : 2) + (y < kScreenSplitY ? 0 : 1); + } else { + expectedColorIdx = kNumMeshes - 1; + } + uint32_t expected = kMeshColors[expectedColorIdx]; + uint32_t actual = resultPx[y * kScreenSize + x]; + if (expected != actual) { + ERRORF(reporter, "[scissor=%s] pixel (%i,%i): got 0x%x expected 0x%x", + ScissorState::kEnabled == scissorState ? "enabled" : "disabled", x, y, + actual, expected); + return; + } + } + } + } +} + +#endif |