1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2017 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurfaceProps.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAlignedStorage.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkOnce.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSLTypeShared.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/KeyBuilder.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ResourceKey.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkBackingFit.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBuffer.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrColor.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDrawIndirectCommand.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGeometryProcessor.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrMeshDrawTarget.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrOpFlushState.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrOpsRenderPass.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPipeline.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPixmap.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProcessorAnalysis.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProcessorSet.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProgramInfo.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderCaps.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderVar.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrUserStencilSettings.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceDrawContext.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
49*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
50*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
51*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrDrawOp.h"
52*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrOp.h"
53*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelper.h"
54*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
55*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
58*c8dee2aaSAndroid Build Coastguard Worker #include <array>
59*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
60*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
61*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
62*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
63*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
64*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
65*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
66*c8dee2aaSAndroid Build Coastguard Worker
67*c8dee2aaSAndroid Build Coastguard Worker class GrAppliedClip;
68*c8dee2aaSAndroid Build Coastguard Worker class GrDstProxyView;
69*c8dee2aaSAndroid Build Coastguard Worker class GrGLSLProgramDataManager;
70*c8dee2aaSAndroid Build Coastguard Worker class GrRecordingContext;
71*c8dee2aaSAndroid Build Coastguard Worker class GrSurfaceProxyView;
72*c8dee2aaSAndroid Build Coastguard Worker enum class GrXferBarrierFlags;
73*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
76*c8dee2aaSAndroid Build Coastguard Worker
77*c8dee2aaSAndroid Build Coastguard Worker #if 0
78*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
79*c8dee2aaSAndroid Build Coastguard Worker #define WRITE_PNG_CONTEXT_TYPE kANGLE_D3D11_ES3
80*c8dee2aaSAndroid Build Coastguard Worker #endif
81*c8dee2aaSAndroid Build Coastguard Worker
82*c8dee2aaSAndroid Build Coastguard Worker SKGPU_DECLARE_STATIC_UNIQUE_KEY(gIndexBufferKey);
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kBoxSize = 2;
85*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kBoxCountY = 8;
86*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kBoxCountX = 8;
87*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kBoxCount = kBoxCountY * kBoxCountX;
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kImageWidth = kBoxCountY * kBoxSize;
90*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kImageHeight = kBoxCountX * kBoxSize;
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kIndexPatternRepeatCount = 3;
93*c8dee2aaSAndroid Build Coastguard Worker constexpr uint16_t kIndexPattern[6] = {0, 1, 2, 1, 2, 3};
94*c8dee2aaSAndroid Build Coastguard Worker
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker class DrawMeshHelper {
97*c8dee2aaSAndroid Build Coastguard Worker public:
DrawMeshHelper(GrOpFlushState * state)98*c8dee2aaSAndroid Build Coastguard Worker DrawMeshHelper(GrOpFlushState* state) : fState(state) {}
99*c8dee2aaSAndroid Build Coastguard Worker
100*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> getIndexBuffer();
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> makeIndexBuffer(const uint16_t[], int count);
103*c8dee2aaSAndroid Build Coastguard Worker
makeVertexBuffer(const TArray<T> & data)104*c8dee2aaSAndroid Build Coastguard Worker template<typename T> sk_sp<const GrBuffer> makeVertexBuffer(const TArray<T>& data) {
105*c8dee2aaSAndroid Build Coastguard Worker return this->makeVertexBuffer(data.begin(), data.size());
106*c8dee2aaSAndroid Build Coastguard Worker }
makeVertexBuffer(const std::vector<T> & data)107*c8dee2aaSAndroid Build Coastguard Worker template<typename T> sk_sp<const GrBuffer> makeVertexBuffer(const std::vector<T>& data) {
108*c8dee2aaSAndroid Build Coastguard Worker return this->makeVertexBuffer(data.data(), data.size());
109*c8dee2aaSAndroid Build Coastguard Worker }
110*c8dee2aaSAndroid Build Coastguard Worker template<typename T> sk_sp<const GrBuffer> makeVertexBuffer(const T* data, int count);
111*c8dee2aaSAndroid Build Coastguard Worker
target()112*c8dee2aaSAndroid Build Coastguard Worker GrMeshDrawTarget* target() { return fState; }
113*c8dee2aaSAndroid Build Coastguard Worker
114*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> fIndexBuffer;
115*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> fIndexBuffer2;
116*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> fInstBuffer;
117*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> fVertBuffer;
118*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> fVertBuffer2;
119*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> fDrawIndirectBuffer;
120*c8dee2aaSAndroid Build Coastguard Worker size_t fDrawIndirectBufferOffset;
121*c8dee2aaSAndroid Build Coastguard Worker
122*c8dee2aaSAndroid Build Coastguard Worker GrOpsRenderPass* bindPipeline(GrPrimitiveType, bool isInstanced, bool hasVertexBuffer);
123*c8dee2aaSAndroid Build Coastguard Worker
124*c8dee2aaSAndroid Build Coastguard Worker private:
125*c8dee2aaSAndroid Build Coastguard Worker GrOpFlushState* fState;
126*c8dee2aaSAndroid Build Coastguard Worker };
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Worker struct Box {
129*c8dee2aaSAndroid Build Coastguard Worker float fX, fY;
130*c8dee2aaSAndroid Build Coastguard Worker GrColor fColor;
131*c8dee2aaSAndroid Build Coastguard Worker };
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////////
134*c8dee2aaSAndroid Build Coastguard Worker
135*c8dee2aaSAndroid Build Coastguard Worker /**
136*c8dee2aaSAndroid Build Coastguard Worker * This is a GPU-backend specific test. It tries to test all possible usecases of
137*c8dee2aaSAndroid Build Coastguard Worker * GrOpsRenderPass::draw*. The test works by drawing checkerboards of colored boxes, reading back
138*c8dee2aaSAndroid Build Coastguard Worker * the pixels, and comparing with expected results. The boxes are drawn on integer boundaries and
139*c8dee2aaSAndroid Build Coastguard Worker * the (opaque) colors are chosen from the set (r,g,b) = (0,255)^3, so the GPU renderings ought to
140*c8dee2aaSAndroid Build Coastguard Worker * produce exact matches.
141*c8dee2aaSAndroid Build Coastguard Worker */
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker static void run_test(GrDirectContext*,
144*c8dee2aaSAndroid Build Coastguard Worker const char* testName,
145*c8dee2aaSAndroid Build Coastguard Worker skiatest::Reporter*,
146*c8dee2aaSAndroid Build Coastguard Worker const std::unique_ptr<skgpu::ganesh::SurfaceDrawContext>&,
147*c8dee2aaSAndroid Build Coastguard Worker const SkBitmap& gold,
148*c8dee2aaSAndroid Build Coastguard Worker std::function<void(DrawMeshHelper*)> prepareFn,
149*c8dee2aaSAndroid Build Coastguard Worker std::function<void(DrawMeshHelper*)> executeFn);
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker #ifdef WRITE_PNG_CONTEXT_TYPE
IsContextTypeForOutputPNGs(skgpu::ContextType type)152*c8dee2aaSAndroid Build Coastguard Worker static bool IsContextTypeForOutputPNGs(skgpu::ContextType type) {
153*c8dee2aaSAndroid Build Coastguard Worker return type == skgpu::ContextType::WRITE_PNG_CONTEXT_TYPE;
154*c8dee2aaSAndroid Build Coastguard Worker }
DEF_GANESH_TEST_FOR_CONTEXTS(GrMeshTest,IsContextTypeForOutputPNGs,reporter,ctxInfo,nullptr)155*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_CONTEXTS(GrMeshTest, IsContextTypeForOutputPNGs, reporter, ctxInfo, nullptr) {
156*c8dee2aaSAndroid Build Coastguard Worker #else
157*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrMeshTest, reporter, ctxInfo, CtsEnforcement::kApiLevel_T) {
158*c8dee2aaSAndroid Build Coastguard Worker #endif
159*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
160*c8dee2aaSAndroid Build Coastguard Worker
161*c8dee2aaSAndroid Build Coastguard Worker auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
162*c8dee2aaSAndroid Build Coastguard Worker GrColorType::kRGBA_8888,
163*c8dee2aaSAndroid Build Coastguard Worker nullptr,
164*c8dee2aaSAndroid Build Coastguard Worker SkBackingFit::kExact,
165*c8dee2aaSAndroid Build Coastguard Worker {kImageWidth, kImageHeight},
166*c8dee2aaSAndroid Build Coastguard Worker SkSurfaceProps(),
167*c8dee2aaSAndroid Build Coastguard Worker /*label=*/{});
168*c8dee2aaSAndroid Build Coastguard Worker if (!sdc) {
169*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "could not create render target context.");
170*c8dee2aaSAndroid Build Coastguard Worker return;
171*c8dee2aaSAndroid Build Coastguard Worker }
172*c8dee2aaSAndroid Build Coastguard Worker
173*c8dee2aaSAndroid Build Coastguard Worker TArray<Box> boxes;
174*c8dee2aaSAndroid Build Coastguard Worker TArray<std::array<Box, 4>> vertexData;
175*c8dee2aaSAndroid Build Coastguard Worker SkBitmap gold;
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker // ---- setup ----------
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
180*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrc);
181*c8dee2aaSAndroid Build Coastguard Worker gold.allocN32Pixels(kImageWidth, kImageHeight);
182*c8dee2aaSAndroid Build Coastguard Worker
183*c8dee2aaSAndroid Build Coastguard Worker SkCanvas goldCanvas(gold);
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < kBoxCountY; ++y) {
186*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < kBoxCountX; ++x) {
187*c8dee2aaSAndroid Build Coastguard Worker int c = y + x;
188*c8dee2aaSAndroid Build Coastguard Worker int rgb[3] = {-(c & 1) & 0xff, -((c >> 1) & 1) & 0xff, -((c >> 2) & 1) & 0xff};
189*c8dee2aaSAndroid Build Coastguard Worker
190*c8dee2aaSAndroid Build Coastguard Worker const Box box = boxes.push_back() = {
191*c8dee2aaSAndroid Build Coastguard Worker float(x * kBoxSize),
192*c8dee2aaSAndroid Build Coastguard Worker float(y * kBoxSize),
193*c8dee2aaSAndroid Build Coastguard Worker GrColorPackRGBA(rgb[0], rgb[1], rgb[2], 255)
194*c8dee2aaSAndroid Build Coastguard Worker };
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker std::array<Box, 4>& boxVertices = vertexData.push_back();
197*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) {
198*c8dee2aaSAndroid Build Coastguard Worker boxVertices[i] = {
199*c8dee2aaSAndroid Build Coastguard Worker box.fX + (i / 2) * kBoxSize,
200*c8dee2aaSAndroid Build Coastguard Worker box.fY + (i % 2) * kBoxSize,
201*c8dee2aaSAndroid Build Coastguard Worker box.fColor
202*c8dee2aaSAndroid Build Coastguard Worker };
203*c8dee2aaSAndroid Build Coastguard Worker }
204*c8dee2aaSAndroid Build Coastguard Worker
205*c8dee2aaSAndroid Build Coastguard Worker paint.setARGB(255, rgb[0], rgb[1], rgb[2]);
206*c8dee2aaSAndroid Build Coastguard Worker goldCanvas.drawRect(SkRect::MakeXYWH(box.fX, box.fY, kBoxSize, kBoxSize), paint);
207*c8dee2aaSAndroid Build Coastguard Worker }
208*c8dee2aaSAndroid Build Coastguard Worker }
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker // ---- tests ----------
211*c8dee2aaSAndroid Build Coastguard Worker
212*c8dee2aaSAndroid Build Coastguard Worker #define VALIDATE(buff) \
213*c8dee2aaSAndroid Build Coastguard Worker do { \
214*c8dee2aaSAndroid Build Coastguard Worker if (!buff) { \
215*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, #buff " is null."); \
216*c8dee2aaSAndroid Build Coastguard Worker return; \
217*c8dee2aaSAndroid Build Coastguard Worker } \
218*c8dee2aaSAndroid Build Coastguard Worker } while (0)
219*c8dee2aaSAndroid Build Coastguard Worker
220*c8dee2aaSAndroid Build Coastguard Worker run_test(dContext, "draw", reporter, sdc, gold,
221*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
222*c8dee2aaSAndroid Build Coastguard Worker TArray<Box> expandedVertexData;
223*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kBoxCount; ++i) {
224*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < 6; ++j) {
225*c8dee2aaSAndroid Build Coastguard Worker expandedVertexData.push_back(vertexData[i][kIndexPattern[j]]);
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker }
228*c8dee2aaSAndroid Build Coastguard Worker
229*c8dee2aaSAndroid Build Coastguard Worker // Draw boxes one line at a time to exercise base vertex.
230*c8dee2aaSAndroid Build Coastguard Worker helper->fVertBuffer = helper->makeVertexBuffer(expandedVertexData);
231*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fVertBuffer);
232*c8dee2aaSAndroid Build Coastguard Worker },
233*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
234*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < kBoxCountY; ++y) {
235*c8dee2aaSAndroid Build Coastguard Worker auto pass = helper->bindPipeline(GrPrimitiveType::kTriangles, false, true);
236*c8dee2aaSAndroid Build Coastguard Worker pass->bindBuffers(nullptr, nullptr, helper->fVertBuffer);
237*c8dee2aaSAndroid Build Coastguard Worker pass->draw(kBoxCountX * 6, y * kBoxCountX * 6);
238*c8dee2aaSAndroid Build Coastguard Worker }
239*c8dee2aaSAndroid Build Coastguard Worker });
240*c8dee2aaSAndroid Build Coastguard Worker
241*c8dee2aaSAndroid Build Coastguard Worker run_test(dContext, "drawIndexed", reporter, sdc, gold,
242*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
243*c8dee2aaSAndroid Build Coastguard Worker helper->fIndexBuffer = helper->getIndexBuffer();
244*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fIndexBuffer);
245*c8dee2aaSAndroid Build Coastguard Worker helper->fVertBuffer = helper->makeVertexBuffer(vertexData);
246*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fVertBuffer);
247*c8dee2aaSAndroid Build Coastguard Worker },
248*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
249*c8dee2aaSAndroid Build Coastguard Worker int baseRepetition = 0;
250*c8dee2aaSAndroid Build Coastguard Worker int i = 0;
251*c8dee2aaSAndroid Build Coastguard Worker // Start at various repetitions within the patterned index buffer to exercise base
252*c8dee2aaSAndroid Build Coastguard Worker // index.
253*c8dee2aaSAndroid Build Coastguard Worker while (i < kBoxCount) {
254*c8dee2aaSAndroid Build Coastguard Worker static_assert(kIndexPatternRepeatCount >= 3);
255*c8dee2aaSAndroid Build Coastguard Worker int repetitionCount = std::min(3 - baseRepetition, kBoxCount - i);
256*c8dee2aaSAndroid Build Coastguard Worker
257*c8dee2aaSAndroid Build Coastguard Worker auto pass = helper->bindPipeline(GrPrimitiveType::kTriangles, false, true);
258*c8dee2aaSAndroid Build Coastguard Worker pass->bindBuffers(helper->fIndexBuffer, nullptr, helper->fVertBuffer);
259*c8dee2aaSAndroid Build Coastguard Worker pass->drawIndexed(repetitionCount * 6, baseRepetition * 6, baseRepetition * 4,
260*c8dee2aaSAndroid Build Coastguard Worker (baseRepetition + repetitionCount) * 4 - 1,
261*c8dee2aaSAndroid Build Coastguard Worker (i - baseRepetition) * 4);
262*c8dee2aaSAndroid Build Coastguard Worker
263*c8dee2aaSAndroid Build Coastguard Worker baseRepetition = (baseRepetition + 1) % 3;
264*c8dee2aaSAndroid Build Coastguard Worker i += repetitionCount;
265*c8dee2aaSAndroid Build Coastguard Worker }
266*c8dee2aaSAndroid Build Coastguard Worker });
267*c8dee2aaSAndroid Build Coastguard Worker
268*c8dee2aaSAndroid Build Coastguard Worker run_test(dContext, "drawIndexPattern", reporter, sdc, gold,
269*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
270*c8dee2aaSAndroid Build Coastguard Worker helper->fIndexBuffer = helper->getIndexBuffer();
271*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fIndexBuffer);
272*c8dee2aaSAndroid Build Coastguard Worker helper->fVertBuffer = helper->makeVertexBuffer(vertexData);
273*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fVertBuffer);
274*c8dee2aaSAndroid Build Coastguard Worker },
275*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
276*c8dee2aaSAndroid Build Coastguard Worker // Draw boxes one line at a time to exercise base vertex. drawIndexPattern does
277*c8dee2aaSAndroid Build Coastguard Worker // not support a base index.
278*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < kBoxCountY; ++y) {
279*c8dee2aaSAndroid Build Coastguard Worker auto pass = helper->bindPipeline(GrPrimitiveType::kTriangles, false, true);
280*c8dee2aaSAndroid Build Coastguard Worker pass->bindBuffers(helper->fIndexBuffer, nullptr, helper->fVertBuffer);
281*c8dee2aaSAndroid Build Coastguard Worker pass->drawIndexPattern(6, kBoxCountX, kIndexPatternRepeatCount, 4,
282*c8dee2aaSAndroid Build Coastguard Worker y * kBoxCountX * 4);
283*c8dee2aaSAndroid Build Coastguard Worker
284*c8dee2aaSAndroid Build Coastguard Worker }
285*c8dee2aaSAndroid Build Coastguard Worker });
286*c8dee2aaSAndroid Build Coastguard Worker
287*c8dee2aaSAndroid Build Coastguard Worker for (bool indexed : {false, true}) {
288*c8dee2aaSAndroid Build Coastguard Worker if (!dContext->priv().caps()->drawInstancedSupport()) {
289*c8dee2aaSAndroid Build Coastguard Worker break;
290*c8dee2aaSAndroid Build Coastguard Worker }
291*c8dee2aaSAndroid Build Coastguard Worker
292*c8dee2aaSAndroid Build Coastguard Worker run_test(dContext, indexed ? "drawIndexedInstanced" : "drawInstanced",
293*c8dee2aaSAndroid Build Coastguard Worker reporter, sdc, gold,
294*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
295*c8dee2aaSAndroid Build Coastguard Worker helper->fIndexBuffer = indexed ? helper->getIndexBuffer() : nullptr;
296*c8dee2aaSAndroid Build Coastguard Worker TArray<uint16_t> baseIndexData;
297*c8dee2aaSAndroid Build Coastguard Worker baseIndexData.push_back(kBoxCountX/2 * 6); // for testing base index.
298*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 6; ++i) {
299*c8dee2aaSAndroid Build Coastguard Worker baseIndexData.push_back(kIndexPattern[i]);
300*c8dee2aaSAndroid Build Coastguard Worker }
301*c8dee2aaSAndroid Build Coastguard Worker helper->fIndexBuffer2 = helper->makeIndexBuffer(baseIndexData.begin(),
302*c8dee2aaSAndroid Build Coastguard Worker baseIndexData.size());
303*c8dee2aaSAndroid Build Coastguard Worker helper->fInstBuffer = helper->makeVertexBuffer(boxes);
304*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fInstBuffer);
305*c8dee2aaSAndroid Build Coastguard Worker helper->fVertBuffer =
306*c8dee2aaSAndroid Build Coastguard Worker helper->makeVertexBuffer(std::vector<float>{0,0, 0,1, 1,0, 1,1});
307*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fVertBuffer);
308*c8dee2aaSAndroid Build Coastguard Worker helper->fVertBuffer2 = helper->makeVertexBuffer( // for testing base vertex.
309*c8dee2aaSAndroid Build Coastguard Worker std::vector<float>{-1,-1, -1,-1, 0,0, 0,1, 1,0, 1,1});
310*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fVertBuffer2);
311*c8dee2aaSAndroid Build Coastguard Worker },
312*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
313*c8dee2aaSAndroid Build Coastguard Worker // Draw boxes one line at a time to exercise base instance, base vertex, and
314*c8dee2aaSAndroid Build Coastguard Worker // null vertex buffer.
315*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < kBoxCountY; ++y) {
316*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> vertexBuffer;
317*c8dee2aaSAndroid Build Coastguard Worker int baseVertex = 0;
318*c8dee2aaSAndroid Build Coastguard Worker switch (y % 3) {
319*c8dee2aaSAndroid Build Coastguard Worker case 0:
320*c8dee2aaSAndroid Build Coastguard Worker if (dContext->priv().caps()->shaderCaps()->fVertexIDSupport) {
321*c8dee2aaSAndroid Build Coastguard Worker break;
322*c8dee2aaSAndroid Build Coastguard Worker }
323*c8dee2aaSAndroid Build Coastguard Worker [[fallthrough]];
324*c8dee2aaSAndroid Build Coastguard Worker case 1:
325*c8dee2aaSAndroid Build Coastguard Worker vertexBuffer = helper->fVertBuffer;
326*c8dee2aaSAndroid Build Coastguard Worker break;
327*c8dee2aaSAndroid Build Coastguard Worker case 2:
328*c8dee2aaSAndroid Build Coastguard Worker vertexBuffer = helper->fVertBuffer2;
329*c8dee2aaSAndroid Build Coastguard Worker baseVertex = 2;
330*c8dee2aaSAndroid Build Coastguard Worker break;
331*c8dee2aaSAndroid Build Coastguard Worker }
332*c8dee2aaSAndroid Build Coastguard Worker
333*c8dee2aaSAndroid Build Coastguard Worker GrPrimitiveType primitiveType = indexed ? GrPrimitiveType::kTriangles
334*c8dee2aaSAndroid Build Coastguard Worker : GrPrimitiveType::kTriangleStrip;
335*c8dee2aaSAndroid Build Coastguard Worker auto pass = helper->bindPipeline(primitiveType, true,
336*c8dee2aaSAndroid Build Coastguard Worker SkToBool(vertexBuffer));
337*c8dee2aaSAndroid Build Coastguard Worker if (indexed) {
338*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> indexBuffer = (y % 2) ?
339*c8dee2aaSAndroid Build Coastguard Worker helper->fIndexBuffer2 : helper->fIndexBuffer;
340*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(indexBuffer);
341*c8dee2aaSAndroid Build Coastguard Worker int baseIndex = (y % 2);
342*c8dee2aaSAndroid Build Coastguard Worker pass->bindBuffers(std::move(indexBuffer), helper->fInstBuffer,
343*c8dee2aaSAndroid Build Coastguard Worker std::move(vertexBuffer));
344*c8dee2aaSAndroid Build Coastguard Worker pass->drawIndexedInstanced(6, baseIndex, kBoxCountX, y * kBoxCountX,
345*c8dee2aaSAndroid Build Coastguard Worker baseVertex);
346*c8dee2aaSAndroid Build Coastguard Worker } else {
347*c8dee2aaSAndroid Build Coastguard Worker pass->bindBuffers(nullptr, helper->fInstBuffer,
348*c8dee2aaSAndroid Build Coastguard Worker std::move(vertexBuffer));
349*c8dee2aaSAndroid Build Coastguard Worker pass->drawInstanced(kBoxCountX, y * kBoxCountY, 4, baseVertex);
350*c8dee2aaSAndroid Build Coastguard Worker }
351*c8dee2aaSAndroid Build Coastguard Worker }
352*c8dee2aaSAndroid Build Coastguard Worker });
353*c8dee2aaSAndroid Build Coastguard Worker }
354*c8dee2aaSAndroid Build Coastguard Worker
355*c8dee2aaSAndroid Build Coastguard Worker for (bool indexed : {false, true}) {
356*c8dee2aaSAndroid Build Coastguard Worker if (!dContext->priv().caps()->drawInstancedSupport()) {
357*c8dee2aaSAndroid Build Coastguard Worker break;
358*c8dee2aaSAndroid Build Coastguard Worker }
359*c8dee2aaSAndroid Build Coastguard Worker
360*c8dee2aaSAndroid Build Coastguard Worker run_test(dContext, (indexed) ? "drawIndexedIndirect" : "drawIndirect",
361*c8dee2aaSAndroid Build Coastguard Worker reporter, sdc, gold,
362*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
363*c8dee2aaSAndroid Build Coastguard Worker TArray<uint16_t> baseIndexData;
364*c8dee2aaSAndroid Build Coastguard Worker baseIndexData.push_back(kBoxCountX/2 * 6); // for testing base index.
365*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < kBoxCountY; ++j) {
366*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 6; ++i) {
367*c8dee2aaSAndroid Build Coastguard Worker baseIndexData.push_back(kIndexPattern[i]);
368*c8dee2aaSAndroid Build Coastguard Worker }
369*c8dee2aaSAndroid Build Coastguard Worker }
370*c8dee2aaSAndroid Build Coastguard Worker helper->fIndexBuffer2 = helper->makeIndexBuffer(baseIndexData.begin(),
371*c8dee2aaSAndroid Build Coastguard Worker baseIndexData.size());
372*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fIndexBuffer2);
373*c8dee2aaSAndroid Build Coastguard Worker helper->fInstBuffer = helper->makeVertexBuffer(boxes);
374*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fInstBuffer);
375*c8dee2aaSAndroid Build Coastguard Worker helper->fVertBuffer = helper->makeVertexBuffer(std::vector<float>{
376*c8dee2aaSAndroid Build Coastguard Worker -1,-1, 0,0, 0,1, 1,0, 1,1, -1,-1, 0,0, 1,0, 0,1, 1,1});
377*c8dee2aaSAndroid Build Coastguard Worker VALIDATE(helper->fVertBuffer);
378*c8dee2aaSAndroid Build Coastguard Worker
379*c8dee2aaSAndroid Build Coastguard Worker GrDrawIndirectWriter indirectWriter;
380*c8dee2aaSAndroid Build Coastguard Worker GrDrawIndexedIndirectWriter indexedIndirectWriter;
381*c8dee2aaSAndroid Build Coastguard Worker if (indexed) {
382*c8dee2aaSAndroid Build Coastguard Worker // Make helper->fDrawIndirectBufferOffset nonzero.
383*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> ignoredBuff;
384*c8dee2aaSAndroid Build Coastguard Worker size_t ignoredOffset;
385*c8dee2aaSAndroid Build Coastguard Worker // Make a superfluous call to makeDrawIndirectSpace in order to test
386*c8dee2aaSAndroid Build Coastguard Worker // "offsetInBytes!=0" for the actual call to makeDrawIndexedIndirectSpace.
387*c8dee2aaSAndroid Build Coastguard Worker helper->target()->makeDrawIndirectSpace(29, &ignoredBuff, &ignoredOffset);
388*c8dee2aaSAndroid Build Coastguard Worker indexedIndirectWriter = helper->target()->makeDrawIndexedIndirectSpace(
389*c8dee2aaSAndroid Build Coastguard Worker kBoxCountY, &helper->fDrawIndirectBuffer,
390*c8dee2aaSAndroid Build Coastguard Worker &helper->fDrawIndirectBufferOffset);
391*c8dee2aaSAndroid Build Coastguard Worker } else {
392*c8dee2aaSAndroid Build Coastguard Worker // Make helper->fDrawIndirectBufferOffset nonzero.
393*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> ignoredBuff;
394*c8dee2aaSAndroid Build Coastguard Worker size_t ignoredOffset;
395*c8dee2aaSAndroid Build Coastguard Worker // Make a superfluous call to makeDrawIndexedIndirectSpace in order to test
396*c8dee2aaSAndroid Build Coastguard Worker // "offsetInBytes!=0" for the actual call to makeDrawIndirectSpace.
397*c8dee2aaSAndroid Build Coastguard Worker helper->target()->makeDrawIndexedIndirectSpace(7, &ignoredBuff,
398*c8dee2aaSAndroid Build Coastguard Worker &ignoredOffset);
399*c8dee2aaSAndroid Build Coastguard Worker indirectWriter = helper->target()->makeDrawIndirectSpace(
400*c8dee2aaSAndroid Build Coastguard Worker kBoxCountY, &helper->fDrawIndirectBuffer,
401*c8dee2aaSAndroid Build Coastguard Worker &helper->fDrawIndirectBufferOffset);
402*c8dee2aaSAndroid Build Coastguard Worker }
403*c8dee2aaSAndroid Build Coastguard Worker
404*c8dee2aaSAndroid Build Coastguard Worker // Draw boxes one line at a time to exercise multiple draws.
405*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < kBoxCountY; ++y) {
406*c8dee2aaSAndroid Build Coastguard Worker int baseVertex = (y % 2) ? 1 : 6;
407*c8dee2aaSAndroid Build Coastguard Worker if (indexed) {
408*c8dee2aaSAndroid Build Coastguard Worker int baseIndex = 1 + y * 6;
409*c8dee2aaSAndroid Build Coastguard Worker indexedIndirectWriter.writeIndexed(6, baseIndex, kBoxCountX,
410*c8dee2aaSAndroid Build Coastguard Worker y * kBoxCountX, baseVertex);
411*c8dee2aaSAndroid Build Coastguard Worker } else {
412*c8dee2aaSAndroid Build Coastguard Worker indirectWriter.write(kBoxCountX, y * kBoxCountX, 4, baseVertex);
413*c8dee2aaSAndroid Build Coastguard Worker }
414*c8dee2aaSAndroid Build Coastguard Worker }
415*c8dee2aaSAndroid Build Coastguard Worker },
416*c8dee2aaSAndroid Build Coastguard Worker [&](DrawMeshHelper* helper) {
417*c8dee2aaSAndroid Build Coastguard Worker GrOpsRenderPass* pass;
418*c8dee2aaSAndroid Build Coastguard Worker if (indexed) {
419*c8dee2aaSAndroid Build Coastguard Worker pass = helper->bindPipeline(GrPrimitiveType::kTriangles, true, true);
420*c8dee2aaSAndroid Build Coastguard Worker pass->bindBuffers(helper->fIndexBuffer2, helper->fInstBuffer,
421*c8dee2aaSAndroid Build Coastguard Worker helper->fVertBuffer);
422*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
423*c8dee2aaSAndroid Build Coastguard Worker int start = kBoxCountY * i / 3;
424*c8dee2aaSAndroid Build Coastguard Worker int end = kBoxCountY * (i + 1) / 3;
425*c8dee2aaSAndroid Build Coastguard Worker size_t offset = helper->fDrawIndirectBufferOffset + start *
426*c8dee2aaSAndroid Build Coastguard Worker sizeof(GrDrawIndexedIndirectCommand);
427*c8dee2aaSAndroid Build Coastguard Worker pass->drawIndexedIndirect(helper->fDrawIndirectBuffer.get(), offset,
428*c8dee2aaSAndroid Build Coastguard Worker end - start);
429*c8dee2aaSAndroid Build Coastguard Worker }
430*c8dee2aaSAndroid Build Coastguard Worker } else {
431*c8dee2aaSAndroid Build Coastguard Worker pass = helper->bindPipeline(GrPrimitiveType::kTriangleStrip, true, true);
432*c8dee2aaSAndroid Build Coastguard Worker pass->bindBuffers(nullptr, helper->fInstBuffer, helper->fVertBuffer);
433*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 2; ++i) {
434*c8dee2aaSAndroid Build Coastguard Worker int start = kBoxCountY * i / 2;
435*c8dee2aaSAndroid Build Coastguard Worker int end = kBoxCountY * (i + 1) / 2;
436*c8dee2aaSAndroid Build Coastguard Worker size_t offset = helper->fDrawIndirectBufferOffset + start *
437*c8dee2aaSAndroid Build Coastguard Worker sizeof(GrDrawIndirectCommand);
438*c8dee2aaSAndroid Build Coastguard Worker pass->drawIndirect(helper->fDrawIndirectBuffer.get(), offset,
439*c8dee2aaSAndroid Build Coastguard Worker end - start);
440*c8dee2aaSAndroid Build Coastguard Worker }
441*c8dee2aaSAndroid Build Coastguard Worker }
442*c8dee2aaSAndroid Build Coastguard Worker });
443*c8dee2aaSAndroid Build Coastguard Worker }
444*c8dee2aaSAndroid Build Coastguard Worker }
445*c8dee2aaSAndroid Build Coastguard Worker
446*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////////
447*c8dee2aaSAndroid Build Coastguard Worker
448*c8dee2aaSAndroid Build Coastguard Worker namespace {
449*c8dee2aaSAndroid Build Coastguard Worker class MeshTestOp : public GrDrawOp {
450*c8dee2aaSAndroid Build Coastguard Worker public:
451*c8dee2aaSAndroid Build Coastguard Worker DEFINE_OP_CLASS_ID
452*c8dee2aaSAndroid Build Coastguard Worker
453*c8dee2aaSAndroid Build Coastguard Worker static GrOp::Owner Make(GrRecordingContext* rContext,
454*c8dee2aaSAndroid Build Coastguard Worker std::function<void(DrawMeshHelper*)> prepareFn,
455*c8dee2aaSAndroid Build Coastguard Worker std::function<void(DrawMeshHelper*)> executeFn) {
456*c8dee2aaSAndroid Build Coastguard Worker return GrOp::Make<MeshTestOp>(rContext, prepareFn, executeFn);
457*c8dee2aaSAndroid Build Coastguard Worker }
458*c8dee2aaSAndroid Build Coastguard Worker
459*c8dee2aaSAndroid Build Coastguard Worker private:
460*c8dee2aaSAndroid Build Coastguard Worker friend class GrOp; // for ctor
461*c8dee2aaSAndroid Build Coastguard Worker
462*c8dee2aaSAndroid Build Coastguard Worker MeshTestOp(std::function<void(DrawMeshHelper*)> prepareFn,
463*c8dee2aaSAndroid Build Coastguard Worker std::function<void(DrawMeshHelper*)> executeFn)
464*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(ClassID()), fPrepareFn(prepareFn), fExecuteFn(executeFn) {
465*c8dee2aaSAndroid Build Coastguard Worker this->setBounds(
466*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeIWH(kImageWidth, kImageHeight), HasAABloat::kNo, IsHairline::kNo);
467*c8dee2aaSAndroid Build Coastguard Worker }
468*c8dee2aaSAndroid Build Coastguard Worker
469*c8dee2aaSAndroid Build Coastguard Worker const char* name() const override { return "GrMeshTestOp"; }
470*c8dee2aaSAndroid Build Coastguard Worker FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
471*c8dee2aaSAndroid Build Coastguard Worker GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override {
472*c8dee2aaSAndroid Build Coastguard Worker return GrProcessorSet::EmptySetAnalysis();
473*c8dee2aaSAndroid Build Coastguard Worker }
474*c8dee2aaSAndroid Build Coastguard Worker
475*c8dee2aaSAndroid Build Coastguard Worker void onPrePrepare(GrRecordingContext*,
476*c8dee2aaSAndroid Build Coastguard Worker const GrSurfaceProxyView& writeView,
477*c8dee2aaSAndroid Build Coastguard Worker GrAppliedClip*,
478*c8dee2aaSAndroid Build Coastguard Worker const GrDstProxyView&,
479*c8dee2aaSAndroid Build Coastguard Worker GrXferBarrierFlags renderPassXferBarriers,
480*c8dee2aaSAndroid Build Coastguard Worker GrLoadOp colorLoadOp) override {}
481*c8dee2aaSAndroid Build Coastguard Worker void onPrepare(GrOpFlushState* state) override {
482*c8dee2aaSAndroid Build Coastguard Worker fHelper = std::make_unique<DrawMeshHelper>(state);
483*c8dee2aaSAndroid Build Coastguard Worker fPrepareFn(fHelper.get());
484*c8dee2aaSAndroid Build Coastguard Worker }
485*c8dee2aaSAndroid Build Coastguard Worker void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {
486*c8dee2aaSAndroid Build Coastguard Worker fExecuteFn(fHelper.get());
487*c8dee2aaSAndroid Build Coastguard Worker }
488*c8dee2aaSAndroid Build Coastguard Worker
489*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<DrawMeshHelper> fHelper;
490*c8dee2aaSAndroid Build Coastguard Worker std::function<void(DrawMeshHelper*)> fPrepareFn;
491*c8dee2aaSAndroid Build Coastguard Worker std::function<void(DrawMeshHelper*)> fExecuteFn;
492*c8dee2aaSAndroid Build Coastguard Worker
493*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrDrawOp;
494*c8dee2aaSAndroid Build Coastguard Worker };
495*c8dee2aaSAndroid Build Coastguard Worker
496*c8dee2aaSAndroid Build Coastguard Worker class MeshTestProcessor : public GrGeometryProcessor {
497*c8dee2aaSAndroid Build Coastguard Worker public:
498*c8dee2aaSAndroid Build Coastguard Worker static GrGeometryProcessor* Make(SkArenaAlloc* arena, bool instanced, bool hasVertexBuffer) {
499*c8dee2aaSAndroid Build Coastguard Worker return arena->make([&](void* ptr) {
500*c8dee2aaSAndroid Build Coastguard Worker return new (ptr) MeshTestProcessor(instanced, hasVertexBuffer);
501*c8dee2aaSAndroid Build Coastguard Worker });
502*c8dee2aaSAndroid Build Coastguard Worker }
503*c8dee2aaSAndroid Build Coastguard Worker
504*c8dee2aaSAndroid Build Coastguard Worker const char* name() const override { return "GrMeshTestProcessor"; }
505*c8dee2aaSAndroid Build Coastguard Worker
506*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const GrShaderCaps&, skgpu::KeyBuilder* b) const final {
507*c8dee2aaSAndroid Build Coastguard Worker b->add32(fInstanceLocation.isInitialized());
508*c8dee2aaSAndroid Build Coastguard Worker b->add32(fVertexPosition.isInitialized());
509*c8dee2aaSAndroid Build Coastguard Worker }
510*c8dee2aaSAndroid Build Coastguard Worker
511*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final;
512*c8dee2aaSAndroid Build Coastguard Worker
513*c8dee2aaSAndroid Build Coastguard Worker private:
514*c8dee2aaSAndroid Build Coastguard Worker class Impl;
515*c8dee2aaSAndroid Build Coastguard Worker
516*c8dee2aaSAndroid Build Coastguard Worker const Attribute& inColor() const {
517*c8dee2aaSAndroid Build Coastguard Worker return fVertexColor.isInitialized() ? fVertexColor : fInstanceColor;
518*c8dee2aaSAndroid Build Coastguard Worker }
519*c8dee2aaSAndroid Build Coastguard Worker
520*c8dee2aaSAndroid Build Coastguard Worker MeshTestProcessor(bool instanced, bool hasVertexBuffer)
521*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(kGrMeshTestProcessor_ClassID) {
522*c8dee2aaSAndroid Build Coastguard Worker if (instanced) {
523*c8dee2aaSAndroid Build Coastguard Worker fInstanceLocation = {"location", kFloat2_GrVertexAttribType, SkSLType::kHalf2};
524*c8dee2aaSAndroid Build Coastguard Worker fInstanceColor = {"color", kUByte4_norm_GrVertexAttribType, SkSLType::kHalf4};
525*c8dee2aaSAndroid Build Coastguard Worker this->setInstanceAttributesWithImplicitOffsets(&fInstanceLocation, 2);
526*c8dee2aaSAndroid Build Coastguard Worker if (hasVertexBuffer) {
527*c8dee2aaSAndroid Build Coastguard Worker fVertexPosition = {"vertex", kFloat2_GrVertexAttribType, SkSLType::kHalf2};
528*c8dee2aaSAndroid Build Coastguard Worker this->setVertexAttributesWithImplicitOffsets(&fVertexPosition, 1);
529*c8dee2aaSAndroid Build Coastguard Worker }
530*c8dee2aaSAndroid Build Coastguard Worker } else {
531*c8dee2aaSAndroid Build Coastguard Worker fVertexPosition = {"vertex", kFloat2_GrVertexAttribType, SkSLType::kHalf2};
532*c8dee2aaSAndroid Build Coastguard Worker fVertexColor = {"color", kUByte4_norm_GrVertexAttribType, SkSLType::kHalf4};
533*c8dee2aaSAndroid Build Coastguard Worker this->setVertexAttributesWithImplicitOffsets(&fVertexPosition, 2);
534*c8dee2aaSAndroid Build Coastguard Worker }
535*c8dee2aaSAndroid Build Coastguard Worker }
536*c8dee2aaSAndroid Build Coastguard Worker
537*c8dee2aaSAndroid Build Coastguard Worker Attribute fVertexPosition;
538*c8dee2aaSAndroid Build Coastguard Worker Attribute fVertexColor;
539*c8dee2aaSAndroid Build Coastguard Worker
540*c8dee2aaSAndroid Build Coastguard Worker Attribute fInstanceLocation;
541*c8dee2aaSAndroid Build Coastguard Worker Attribute fInstanceColor;
542*c8dee2aaSAndroid Build Coastguard Worker
543*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrGeometryProcessor;
544*c8dee2aaSAndroid Build Coastguard Worker };
545*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
546*c8dee2aaSAndroid Build Coastguard Worker
547*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrGeometryProcessor::ProgramImpl> MeshTestProcessor::makeProgramImpl(
548*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps&) const {
549*c8dee2aaSAndroid Build Coastguard Worker class Impl : public ProgramImpl {
550*c8dee2aaSAndroid Build Coastguard Worker public:
551*c8dee2aaSAndroid Build Coastguard Worker void setData(const GrGLSLProgramDataManager&,
552*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps&,
553*c8dee2aaSAndroid Build Coastguard Worker const GrGeometryProcessor&) final {}
554*c8dee2aaSAndroid Build Coastguard Worker
555*c8dee2aaSAndroid Build Coastguard Worker private:
556*c8dee2aaSAndroid Build Coastguard Worker void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
557*c8dee2aaSAndroid Build Coastguard Worker const MeshTestProcessor& mp = args.fGeomProc.cast<MeshTestProcessor>();
558*c8dee2aaSAndroid Build Coastguard Worker GrGLSLVertexBuilder* v = args.fVertBuilder;
559*c8dee2aaSAndroid Build Coastguard Worker GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
560*c8dee2aaSAndroid Build Coastguard Worker
561*c8dee2aaSAndroid Build Coastguard Worker GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
562*c8dee2aaSAndroid Build Coastguard Worker varyingHandler->emitAttributes(mp);
563*c8dee2aaSAndroid Build Coastguard Worker f->codeAppendf("half4 %s;", args.fOutputColor);
564*c8dee2aaSAndroid Build Coastguard Worker varyingHandler->addPassThroughAttribute(mp.inColor().asShaderVar(), args.fOutputColor);
565*c8dee2aaSAndroid Build Coastguard Worker
566*c8dee2aaSAndroid Build Coastguard Worker if (!mp.fInstanceLocation.isInitialized()) {
567*c8dee2aaSAndroid Build Coastguard Worker v->codeAppendf("float2 vertex = %s;", mp.fVertexPosition.name());
568*c8dee2aaSAndroid Build Coastguard Worker } else {
569*c8dee2aaSAndroid Build Coastguard Worker if (mp.fVertexPosition.isInitialized()) {
570*c8dee2aaSAndroid Build Coastguard Worker v->codeAppendf("float2 offset = %s;", mp.fVertexPosition.name());
571*c8dee2aaSAndroid Build Coastguard Worker } else {
572*c8dee2aaSAndroid Build Coastguard Worker v->codeAppend("float2 offset = float2(sk_VertexID / 2, sk_VertexID % 2);");
573*c8dee2aaSAndroid Build Coastguard Worker }
574*c8dee2aaSAndroid Build Coastguard Worker v->codeAppendf("float2 vertex = %s + offset * %i;", mp.fInstanceLocation.name(),
575*c8dee2aaSAndroid Build Coastguard Worker kBoxSize);
576*c8dee2aaSAndroid Build Coastguard Worker }
577*c8dee2aaSAndroid Build Coastguard Worker gpArgs->fPositionVar.set(SkSLType::kFloat2, "vertex");
578*c8dee2aaSAndroid Build Coastguard Worker
579*c8dee2aaSAndroid Build Coastguard Worker f->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
580*c8dee2aaSAndroid Build Coastguard Worker }
581*c8dee2aaSAndroid Build Coastguard Worker };
582*c8dee2aaSAndroid Build Coastguard Worker
583*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<Impl>();
584*c8dee2aaSAndroid Build Coastguard Worker }
585*c8dee2aaSAndroid Build Coastguard Worker
586*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////////
587*c8dee2aaSAndroid Build Coastguard Worker
588*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> DrawMeshHelper::makeIndexBuffer(const uint16_t indices[], int count) {
589*c8dee2aaSAndroid Build Coastguard Worker return fState->resourceProvider()->createBuffer(indices,
590*c8dee2aaSAndroid Build Coastguard Worker count*sizeof(uint16_t),
591*c8dee2aaSAndroid Build Coastguard Worker GrGpuBufferType::kIndex,
592*c8dee2aaSAndroid Build Coastguard Worker kDynamic_GrAccessPattern);
593*c8dee2aaSAndroid Build Coastguard Worker }
594*c8dee2aaSAndroid Build Coastguard Worker
595*c8dee2aaSAndroid Build Coastguard Worker template<typename T>
596*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> DrawMeshHelper::makeVertexBuffer(const T* data, int count) {
597*c8dee2aaSAndroid Build Coastguard Worker return fState->resourceProvider()->createBuffer(data,
598*c8dee2aaSAndroid Build Coastguard Worker count*sizeof(T),
599*c8dee2aaSAndroid Build Coastguard Worker GrGpuBufferType::kVertex,
600*c8dee2aaSAndroid Build Coastguard Worker kDynamic_GrAccessPattern);
601*c8dee2aaSAndroid Build Coastguard Worker }
602*c8dee2aaSAndroid Build Coastguard Worker
603*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> DrawMeshHelper::getIndexBuffer() {
604*c8dee2aaSAndroid Build Coastguard Worker SKGPU_DEFINE_STATIC_UNIQUE_KEY(gIndexBufferKey);
605*c8dee2aaSAndroid Build Coastguard Worker return fState->resourceProvider()->findOrCreatePatternedIndexBuffer(
606*c8dee2aaSAndroid Build Coastguard Worker kIndexPattern, 6, kIndexPatternRepeatCount, 4, gIndexBufferKey);
607*c8dee2aaSAndroid Build Coastguard Worker }
608*c8dee2aaSAndroid Build Coastguard Worker
609*c8dee2aaSAndroid Build Coastguard Worker GrOpsRenderPass* DrawMeshHelper::bindPipeline(GrPrimitiveType primitiveType, bool isInstanced,
610*c8dee2aaSAndroid Build Coastguard Worker bool hasVertexBuffer) {
611*c8dee2aaSAndroid Build Coastguard Worker GrProcessorSet processorSet(SkBlendMode::kSrc);
612*c8dee2aaSAndroid Build Coastguard Worker
613*c8dee2aaSAndroid Build Coastguard Worker // TODO: add a GrProcessorSet testing helper to make this easier
614*c8dee2aaSAndroid Build Coastguard Worker SkPMColor4f overrideColor;
615*c8dee2aaSAndroid Build Coastguard Worker processorSet.finalize(GrProcessorAnalysisColor(),
616*c8dee2aaSAndroid Build Coastguard Worker GrProcessorAnalysisCoverage::kNone,
617*c8dee2aaSAndroid Build Coastguard Worker fState->appliedClip(),
618*c8dee2aaSAndroid Build Coastguard Worker nullptr,
619*c8dee2aaSAndroid Build Coastguard Worker fState->caps(),
620*c8dee2aaSAndroid Build Coastguard Worker GrClampType::kAuto,
621*c8dee2aaSAndroid Build Coastguard Worker &overrideColor);
622*c8dee2aaSAndroid Build Coastguard Worker
623*c8dee2aaSAndroid Build Coastguard Worker auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(fState,
624*c8dee2aaSAndroid Build Coastguard Worker std::move(processorSet),
625*c8dee2aaSAndroid Build Coastguard Worker GrPipeline::InputFlags::kNone);
626*c8dee2aaSAndroid Build Coastguard Worker
627*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor* mtp = MeshTestProcessor::Make(fState->allocator(), isInstanced,
628*c8dee2aaSAndroid Build Coastguard Worker hasVertexBuffer);
629*c8dee2aaSAndroid Build Coastguard Worker
630*c8dee2aaSAndroid Build Coastguard Worker GrProgramInfo programInfo(fState->caps(), fState->writeView(), fState->usesMSAASurface(),
631*c8dee2aaSAndroid Build Coastguard Worker pipeline, &GrUserStencilSettings::kUnused, mtp, primitiveType,
632*c8dee2aaSAndroid Build Coastguard Worker fState->renderPassBarriers(), fState->colorLoadOp());
633*c8dee2aaSAndroid Build Coastguard Worker
634*c8dee2aaSAndroid Build Coastguard Worker fState->opsRenderPass()->bindPipeline(programInfo, SkRect::MakeIWH(kImageWidth, kImageHeight));
635*c8dee2aaSAndroid Build Coastguard Worker return fState->opsRenderPass();
636*c8dee2aaSAndroid Build Coastguard Worker }
637*c8dee2aaSAndroid Build Coastguard Worker
638*c8dee2aaSAndroid Build Coastguard Worker static void run_test(GrDirectContext* dContext,
639*c8dee2aaSAndroid Build Coastguard Worker const char* testName,
640*c8dee2aaSAndroid Build Coastguard Worker skiatest::Reporter* reporter,
641*c8dee2aaSAndroid Build Coastguard Worker const std::unique_ptr<skgpu::ganesh::SurfaceDrawContext>& sdc,
642*c8dee2aaSAndroid Build Coastguard Worker const SkBitmap& gold,
643*c8dee2aaSAndroid Build Coastguard Worker std::function<void(DrawMeshHelper*)> prepareFn,
644*c8dee2aaSAndroid Build Coastguard Worker std::function<void(DrawMeshHelper*)> executeFn) {
645*c8dee2aaSAndroid Build Coastguard Worker const int w = gold.width(), h = gold.height();
646*c8dee2aaSAndroid Build Coastguard Worker const uint32_t* goldPx = reinterpret_cast<const uint32_t*>(gold.getPixels());
647*c8dee2aaSAndroid Build Coastguard Worker if (h != sdc->height() || w != sdc->width()) {
648*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "[%s] expectation and rtc not compatible (?).", testName);
649*c8dee2aaSAndroid Build Coastguard Worker return;
650*c8dee2aaSAndroid Build Coastguard Worker }
651*c8dee2aaSAndroid Build Coastguard Worker if (sizeof(uint32_t) * kImageWidth != gold.rowBytes()) {
652*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "[%s] unexpected row bytes in gold image", testName);
653*c8dee2aaSAndroid Build Coastguard Worker return;
654*c8dee2aaSAndroid Build Coastguard Worker }
655*c8dee2aaSAndroid Build Coastguard Worker
656*c8dee2aaSAndroid Build Coastguard Worker GrPixmap resultPM = GrPixmap::Allocate(gold.info());
657*c8dee2aaSAndroid Build Coastguard Worker sdc->clear(SkPMColor4f::FromBytes_RGBA(0xbaaaaaad));
658*c8dee2aaSAndroid Build Coastguard Worker sdc->addDrawOp(MeshTestOp::Make(dContext, prepareFn, executeFn));
659*c8dee2aaSAndroid Build Coastguard Worker
660*c8dee2aaSAndroid Build Coastguard Worker sdc->readPixels(dContext, resultPM, {0, 0});
661*c8dee2aaSAndroid Build Coastguard Worker
662*c8dee2aaSAndroid Build Coastguard Worker #ifdef WRITE_PNG_CONTEXT_TYPE
663*c8dee2aaSAndroid Build Coastguard Worker #define STRINGIFY(X) #X
664*c8dee2aaSAndroid Build Coastguard Worker #define TOSTRING(X) STRINGIFY(X)
665*c8dee2aaSAndroid Build Coastguard Worker SkString filename;
666*c8dee2aaSAndroid Build Coastguard Worker filename.printf("GrMeshTest_%s_%s.png", TOSTRING(WRITE_PNG_CONTEXT_TYPE), testName);
667*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("writing %s...\n", filename.c_str());
668*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::EncodeImageToPngFile(filename.c_str(), resultPM);
669*c8dee2aaSAndroid Build Coastguard Worker #endif
670*c8dee2aaSAndroid Build Coastguard Worker
671*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < h; ++y) {
672*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < w; ++x) {
673*c8dee2aaSAndroid Build Coastguard Worker uint32_t expected = goldPx[y * kImageWidth + x];
674*c8dee2aaSAndroid Build Coastguard Worker uint32_t actual = static_cast<uint32_t*>(resultPM.addr())[y * kImageWidth + x];
675*c8dee2aaSAndroid Build Coastguard Worker if (expected != actual) {
676*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "[%s] pixel (%i,%i): got 0x%x expected 0x%x",
677*c8dee2aaSAndroid Build Coastguard Worker testName, x, y, actual, expected);
678*c8dee2aaSAndroid Build Coastguard Worker return;
679*c8dee2aaSAndroid Build Coastguard Worker }
680*c8dee2aaSAndroid Build Coastguard Worker }
681*c8dee2aaSAndroid Build Coastguard Worker }
682*c8dee2aaSAndroid Build Coastguard Worker }
683