aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-06-06 12:27:16 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-07 18:26:11 +0000
commit46983b7dd88603bb2a9a3c3e1ce3e147f5615f2f (patch)
treecb2dccc7b6d44b1100dc34af92c60d7b243d01c7 /tests
parent912e6b883782cd6a53348056012ff7ed38658c79 (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.cpp14
-rw-r--r--tests/GrMeshTest.cpp4
-rw-r--r--tests/GrPipelineDynamicStateTest.cpp219
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