Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrPipelineDynamicStateTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
13#include "include/core/SkRect.h"
46#include "tests/Test.h"
47
48#include <array>
49#include <cstdint>
50#include <initializer_list>
51#include <memory>
52#include <utility>
53
54using namespace skia_private;
55
56class GrAppliedClip;
57class GrDstProxyView;
60class GrCaps;
61enum class GrXferBarrierFlags;
62namespace skgpu { class KeyBuilder; }
63struct GrContextOptions;
64struct GrShaderCaps;
65
66/**
67 * This is a GPU-backend specific test for dynamic pipeline state. It draws boxes using dynamic
68 * scissor rectangles then reads back the result to verify a successful test.
69 */
70
71static constexpr int kScreenSize = 6;
72static constexpr int kNumMeshes = 4;
73static constexpr int kScreenSplitX = kScreenSize/2;
74static constexpr int kScreenSplitY = kScreenSize/2;
75
82
84 GrColorPackRGBA(255, 0, 0, 255),
85 GrColorPackRGBA(0, 255, 0, 255),
86 GrColorPackRGBA(0, 0, 255, 255),
87 GrColorPackRGBA(0, 0, 0, 255)
88};
89
90struct Vertex {
91 float fX;
92 float fY;
94};
95
96namespace {
97class PipelineDynamicStateTestProcessor : public GrGeometryProcessor {
98public:
99 static GrGeometryProcessor* Make(SkArenaAlloc* arena) {
100 return arena->make(
101 [&](void* ptr) { return new (ptr) PipelineDynamicStateTestProcessor(); });
102 }
103
104 const char* name() const override { return "GrPipelineDynamicStateTest Processor"; }
105
106 void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const final {}
107
108 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final;
109
110private:
111 PipelineDynamicStateTestProcessor() : INHERITED(kGrPipelineDynamicStateTestProcessor_ClassID) {
112 this->setVertexAttributesWithImplicitOffsets(kAttributes, std::size(kAttributes));
113 }
114
115 const Attribute& inVertex() const { return kAttributes[0]; }
116 const Attribute& inColor() const { return kAttributes[1]; }
117
118 inline static constexpr Attribute kAttributes[] = {
121 };
122
123 friend class GLSLPipelineDynamicStateTestProcessor;
125};
126} // anonymous namespace
127
128std::unique_ptr<GrGeometryProcessor::ProgramImpl>
129PipelineDynamicStateTestProcessor::makeProgramImpl(const GrShaderCaps&) const {
130 class Impl : public GrGeometryProcessor::ProgramImpl {
131 public:
133 const GrShaderCaps&,
134 const GrGeometryProcessor&) final {}
135
136 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
137 const PipelineDynamicStateTestProcessor& mp =
138 args.fGeomProc.cast<PipelineDynamicStateTestProcessor>();
139 GrGLSLVertexBuilder* v = args.fVertBuilder;
140 GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
141
142 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
143 varyingHandler->emitAttributes(mp);
144 f->codeAppendf("half4 %s;", args.fOutputColor);
145 varyingHandler->addPassThroughAttribute(mp.inColor().asShaderVar(), args.fOutputColor);
146
147 v->codeAppendf("float2 vertex = %s;", mp.inVertex().name());
148 gpArgs->fPositionVar.set(SkSLType::kFloat2, "vertex");
149 f->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
150 }
151 };
152 return std::make_unique<Impl>();
153}
154
155namespace {
156class GrPipelineDynamicStateTestOp : public GrDrawOp {
157public:
159
160 static GrOp::Owner Make(GrRecordingContext* context,
161 GrScissorTest scissorTest,
162 sk_sp<const GrBuffer> vbuff) {
163 return GrOp::Make<GrPipelineDynamicStateTestOp>(context, scissorTest, std::move(vbuff));
164 }
165
166private:
167 friend class GrOp;
168
169 GrPipelineDynamicStateTestOp(GrScissorTest scissorTest, sk_sp<const GrBuffer> vbuff)
170 : INHERITED(ClassID())
171 , fScissorTest(scissorTest)
172 , fVertexBuffer(std::move(vbuff)) {
174 HasAABloat::kNo, IsHairline::kNo);
175 }
176
177 const char* name() const override { return "GrPipelineDynamicStateTestOp"; }
178 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
181 }
183 const GrSurfaceProxyView& writeView,
185 const GrDstProxyView&,
186 GrXferBarrierFlags renderPassXferBarriers,
187 GrLoadOp colorLoadOp) override {}
188 void onPrepare(GrOpFlushState*) override {}
189 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
190 GrPipeline pipeline(fScissorTest, SkBlendMode::kSrc,
191 flushState->drawOpArgs().writeView().swizzle());
193 for (int i = 0; i < kNumMeshes; ++i) {
194 GrSimpleMesh& mesh = meshes.push_back();
195 mesh.set(fVertexBuffer, 4, 4 * i);
196 }
197
198 auto geomProc = PipelineDynamicStateTestProcessor::Make(flushState->allocator());
199
200 GrProgramInfo programInfo(flushState->caps(),
201 flushState->writeView(),
202 flushState->usesMSAASurface(),
203 &pipeline,
205 geomProc,
207 flushState->renderPassBarriers(),
208 flushState->colorLoadOp());
209
210 flushState->bindPipeline(programInfo, SkRect::MakeIWH(kScreenSize, kScreenSize));
211 for (int i = 0; i < 4; ++i) {
212 if (fScissorTest == GrScissorTest::kEnabled) {
213 flushState->setScissorRect(kDynamicScissors[i]);
214 }
215 flushState->drawMesh(meshes[i]);
216 }
217 }
218
219 GrScissorTest fScissorTest;
220 const sk_sp<const GrBuffer> fVertexBuffer;
221
222 using INHERITED = GrDrawOp;
223};
224} // anonymous namespace
225
226DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrPipelineDynamicStateTest,
227 reporter,
228 ctxInfo,
230 auto dContext = ctxInfo.directContext();
231 GrResourceProvider* rp = dContext->priv().resourceProvider();
232
233 auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
235 nullptr,
239 /*label=*/{});
240 if (!sdc) {
241 ERRORF(reporter, "could not create render target context.");
242 return;
243 }
244
245 constexpr float d = (float) kScreenSize;
246 Vertex vdata[kNumMeshes * 4] = {
247 {0, 0, kMeshColors[0]},
248 {0, d, kMeshColors[0]},
249 {d, 0, kMeshColors[0]},
250 {d, d, kMeshColors[0]},
251
252 {0, 0, kMeshColors[1]},
253 {0, d, kMeshColors[1]},
254 {d, 0, kMeshColors[1]},
255 {d, d, kMeshColors[1]},
256
257 {0, 0, kMeshColors[2]},
258 {0, d, kMeshColors[2]},
259 {d, 0, kMeshColors[2]},
260 {d, d, kMeshColors[2]},
261
262 {0, 0, kMeshColors[3]},
263 {0, d, kMeshColors[3]},
264 {d, 0, kMeshColors[3]},
265 {d, d, kMeshColors[3]}
266 };
267
268 sk_sp<const GrBuffer> vbuff(rp->createBuffer(vdata,
269 sizeof(vdata),
272 if (!vbuff) {
273 ERRORF(reporter, "vbuff is null.");
274 return;
275 }
276
277 uint32_t resultPx[kScreenSize * kScreenSize];
278
280 sdc->clear(SkPMColor4f::FromBytes_RGBA(0xbaaaaaad));
281 sdc->addDrawOp(GrPipelineDynamicStateTestOp::Make(dContext, scissorTest, vbuff));
284 GrPixmap resultPM(ii, resultPx, kScreenSize*sizeof(uint32_t));
285 sdc->readPixels(dContext, resultPM, {0, 0});
286 for (int y = 0; y < kScreenSize; ++y) {
287 for (int x = 0; x < kScreenSize; ++x) {
288 int expectedColorIdx;
289 if (GrScissorTest::kEnabled == scissorTest) {
290 expectedColorIdx = (x < kScreenSplitX ? 0 : 2) + (y < kScreenSplitY ? 0 : 1);
291 } else {
292 expectedColorIdx = kNumMeshes - 1;
293 }
294 uint32_t expected = kMeshColors[expectedColorIdx];
295 uint32_t actual = resultPx[y * kScreenSize + x];
296 if (expected != actual) {
297 ERRORF(reporter, "[scissor=%s] pixel (%i,%i): got 0x%x expected 0x%x",
298 GrScissorTest::kEnabled == scissorTest ? "enabled" : "disabled", x, y,
299 actual, expected);
300 return;
301 }
302 }
303 }
304 }
305}
reporter
static GrColor GrColorPackRGBA(unsigned r, unsigned g, unsigned b, unsigned a)
Definition GrColor.h:46
uint32_t GrColor
Definition GrColor.h:25
#define DEFINE_OP_CLASS_ID
Definition GrOp.h:64
static constexpr int kScreenSplitY
static constexpr int kScreenSplitX
static constexpr int kNumMeshes
static const SkIRect kDynamicScissors[kNumMeshes]
static const GrColor kMeshColors[kNumMeshes]
static constexpr int kScreenSize
GrClampType
GrScissorTest
@ kDynamic_GrAccessPattern
GrLoadOp
@ kFloat2_GrVertexAttribType
@ kUByte4_norm_GrVertexAttribType
GrXferBarrierFlags
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
#define INHERITED(method,...)
#define ERRORF(r,...)
Definition Test.h:293
#define DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info, ctsEnforcement)
Definition Test.h:434
virtual FixedFunctionFlags fixedFunctionFlags() const
Definition GrDrawOp.h:112
virtual GrProcessorSet::Analysis finalize(const GrCaps &, const GrAppliedClip *, GrClampType)=0
void emitAttributes(const GrGeometryProcessor &)
void addPassThroughAttribute(const GrShaderVar &vsVar, const char *output, Interpolation=Interpolation::kInterpolated)
virtual void onEmitCode(EmitArgs &, GrGPArgs *)=0
virtual void setData(const GrGLSLProgramDataManager &, const GrShaderCaps &, const GrGeometryProcessor &)=0
virtual std::unique_ptr< ProgramImpl > makeProgramImpl(const GrShaderCaps &) const =0
virtual void addToKey(const GrShaderCaps &, skgpu::KeyBuilder *) const =0
void setVertexAttributesWithImplicitOffsets(const Attribute *attrs, int attrCount)
void setScissorRect(const SkIRect &scissorRect)
GrLoadOp colorLoadOp() const final
GrXferBarrierFlags renderPassBarriers() const final
SkArenaAlloc * allocator() override
void drawMesh(const GrSimpleMesh &mesh)
const GrSurfaceProxyView & writeView() const final
const GrCaps & caps() const final
void bindPipeline(const GrProgramInfo &programInfo, const SkRect &drawBounds)
const OpArgs & drawOpArgs() const
bool usesMSAASurface() const final
Definition GrOp.h:70
virtual void onExecute(GrOpFlushState *, const SkRect &chainBounds)=0
static Owner Make(GrRecordingContext *context, Args &&... args)
Definition GrOp.h:75
std::unique_ptr< GrOp > Owner
Definition GrOp.h:72
virtual void onPrepare(GrOpFlushState *)=0
virtual const char * name() const =0
virtual void onPrePrepare(GrRecordingContext *, const GrSurfaceProxyView &writeView, GrAppliedClip *, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)=0
void setBounds(const SkRect &newBounds, HasAABloat aabloat, IsHairline zeroArea)
Definition GrOp.h:279
static constexpr Analysis EmptySetAnalysis()
virtual const char * name() const =0
sk_sp< GrGpuBuffer > createBuffer(size_t size, GrGpuBufferType, GrAccessPattern, ZeroInit)
GrResourceProviderPriv priv()
skgpu::Swizzle swizzle() const
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
static std::unique_ptr< SurfaceDrawContext > Make(GrRecordingContext *, GrColorType, sk_sp< GrSurfaceProxy >, sk_sp< SkColorSpace >, GrSurfaceOrigin, const SkSurfaceProps &)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
double y
double x
SkMesh mesh
Definition SkRecords.h:345
Definition ref_ptr.h:256
const GrSurfaceProxyView & writeView() const
static const GrUserStencilSettings & kUnused
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition SkRect.h:91
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static SkRGBA4f FromBytes_RGBA(uint32_t color)
static SkRect MakeIWH(int w, int h)
Definition SkRect.h:623