Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Macros | Functions | Variables
GrMeshTest.cpp File Reference
#include "include/core/SkBitmap.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GrDirectContext.h"
#include "include/private/SkColorData.h"
#include "include/private/base/SkAlignedStorage.h"
#include "include/private/base/SkOnce.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTo.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/base/SkArenaAlloc.h"
#include "src/core/SkSLTypeShared.h"
#include "src/gpu/KeyBuilder.h"
#include "src/gpu/ResourceKey.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/ganesh/GrBuffer.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrColor.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrDrawIndirectCommand.h"
#include "src/gpu/ganesh/GrGeometryProcessor.h"
#include "src/gpu/ganesh/GrMeshDrawTarget.h"
#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/GrOpsRenderPass.h"
#include "src/gpu/ganesh/GrPipeline.h"
#include "src/gpu/ganesh/GrPixmap.h"
#include "src/gpu/ganesh/GrProcessorAnalysis.h"
#include "src/gpu/ganesh/GrProcessorSet.h"
#include "src/gpu/ganesh/GrProgramInfo.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrShaderCaps.h"
#include "src/gpu/ganesh/GrShaderVar.h"
#include "src/gpu/ganesh/GrUserStencilSettings.h"
#include "src/gpu/ganesh/SurfaceDrawContext.h"
#include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
#include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
#include "src/gpu/ganesh/ops/GrDrawOp.h"
#include "src/gpu/ganesh/ops/GrOp.h"
#include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelper.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <initializer_list>
#include <memory>
#include <utility>
#include <vector>

Go to the source code of this file.

Classes

class  DrawMeshHelper
 
struct  Box
 

Macros

#define VALIDATE(buff)
 

Functions

 SKGPU_DECLARE_STATIC_UNIQUE_KEY (gIndexBufferKey)
 
static void run_test (GrDirectContext *, const char *testName, skiatest::Reporter *, const std::unique_ptr< skgpu::ganesh::SurfaceDrawContext > &, const SkBitmap &gold, std::function< void(DrawMeshHelper *)> prepareFn, std::function< void(DrawMeshHelper *)> executeFn)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (GrMeshTest, reporter, ctxInfo, CtsEnforcement::kApiLevel_T)
 

Variables

static constexpr int kBoxSize = 2
 
static constexpr int kBoxCountY = 8
 
static constexpr int kBoxCountX = 8
 
static constexpr int kBoxCount = kBoxCountY * kBoxCountX
 
static constexpr int kImageWidth = kBoxCountY * kBoxSize
 
static constexpr int kImageHeight = kBoxCountX * kBoxSize
 
static constexpr int kIndexPatternRepeatCount = 3
 
constexpr uint16_t kIndexPattern [6] = {0, 1, 2, 1, 2, 3}
 

Macro Definition Documentation

◆ VALIDATE

#define VALIDATE (   buff)
Value:
do { \
if (!buff) { \
ERRORF(reporter, #buff " is null."); \
return; \
} \
} while (0)
reporter

Function Documentation

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS()

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( GrMeshTest  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kApiLevel_T   
)

Definition at line 157 of file GrMeshTest.cpp.

157 {
158#endif
159 auto dContext = ctxInfo.directContext();
160
161 auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
163 nullptr,
167 /*label=*/{});
168 if (!sdc) {
169 ERRORF(reporter, "could not create render target context.");
170 return;
171 }
172
173 TArray<Box> boxes;
174 TArray<std::array<Box, 4>> vertexData;
175 SkBitmap gold;
176
177 // ---- setup ----------
178
180 paint.setBlendMode(SkBlendMode::kSrc);
182
183 SkCanvas goldCanvas(gold);
184
185 for (int y = 0; y < kBoxCountY; ++y) {
186 for (int x = 0; x < kBoxCountX; ++x) {
187 int c = y + x;
188 int rgb[3] = {-(c & 1) & 0xff, -((c >> 1) & 1) & 0xff, -((c >> 2) & 1) & 0xff};
189
190 const Box box = boxes.push_back() = {
191 float(x * kBoxSize),
192 float(y * kBoxSize),
193 GrColorPackRGBA(rgb[0], rgb[1], rgb[2], 255)
194 };
195
196 std::array<Box, 4>& boxVertices = vertexData.push_back();
197 for (int i = 0; i < 4; ++i) {
198 boxVertices[i] = {
199 box.fX + (i / 2) * kBoxSize,
200 box.fY + (i % 2) * kBoxSize,
201 box.fColor
202 };
203 }
204
205 paint.setARGB(255, rgb[0], rgb[1], rgb[2]);
206 goldCanvas.drawRect(SkRect::MakeXYWH(box.fX, box.fY, kBoxSize, kBoxSize), paint);
207 }
208 }
209
210 // ---- tests ----------
211
212#define VALIDATE(buff) \
213 do { \
214 if (!buff) { \
215 ERRORF(reporter, #buff " is null."); \
216 return; \
217 } \
218 } while (0)
219
220 run_test(dContext, "draw", reporter, sdc, gold,
221 [&](DrawMeshHelper* helper) {
222 TArray<Box> expandedVertexData;
223 for (int i = 0; i < kBoxCount; ++i) {
224 for (int j = 0; j < 6; ++j) {
225 expandedVertexData.push_back(vertexData[i][kIndexPattern[j]]);
226 }
227 }
228
229 // Draw boxes one line at a time to exercise base vertex.
230 helper->fVertBuffer = helper->makeVertexBuffer(expandedVertexData);
231 VALIDATE(helper->fVertBuffer);
232 },
233 [&](DrawMeshHelper* helper) {
234 for (int y = 0; y < kBoxCountY; ++y) {
235 auto pass = helper->bindPipeline(GrPrimitiveType::kTriangles, false, true);
236 pass->bindBuffers(nullptr, nullptr, helper->fVertBuffer);
237 pass->draw(kBoxCountX * 6, y * kBoxCountX * 6);
238 }
239 });
240
241 run_test(dContext, "drawIndexed", reporter, sdc, gold,
242 [&](DrawMeshHelper* helper) {
243 helper->fIndexBuffer = helper->getIndexBuffer();
244 VALIDATE(helper->fIndexBuffer);
245 helper->fVertBuffer = helper->makeVertexBuffer(vertexData);
246 VALIDATE(helper->fVertBuffer);
247 },
248 [&](DrawMeshHelper* helper) {
249 int baseRepetition = 0;
250 int i = 0;
251 // Start at various repetitions within the patterned index buffer to exercise base
252 // index.
253 while (i < kBoxCount) {
254 static_assert(kIndexPatternRepeatCount >= 3);
255 int repetitionCount = std::min(3 - baseRepetition, kBoxCount - i);
256
257 auto pass = helper->bindPipeline(GrPrimitiveType::kTriangles, false, true);
258 pass->bindBuffers(helper->fIndexBuffer, nullptr, helper->fVertBuffer);
259 pass->drawIndexed(repetitionCount * 6, baseRepetition * 6, baseRepetition * 4,
260 (baseRepetition + repetitionCount) * 4 - 1,
261 (i - baseRepetition) * 4);
262
263 baseRepetition = (baseRepetition + 1) % 3;
264 i += repetitionCount;
265 }
266 });
267
268 run_test(dContext, "drawIndexPattern", reporter, sdc, gold,
269 [&](DrawMeshHelper* helper) {
270 helper->fIndexBuffer = helper->getIndexBuffer();
271 VALIDATE(helper->fIndexBuffer);
272 helper->fVertBuffer = helper->makeVertexBuffer(vertexData);
273 VALIDATE(helper->fVertBuffer);
274 },
275 [&](DrawMeshHelper* helper) {
276 // Draw boxes one line at a time to exercise base vertex. drawIndexPattern does
277 // not support a base index.
278 for (int y = 0; y < kBoxCountY; ++y) {
279 auto pass = helper->bindPipeline(GrPrimitiveType::kTriangles, false, true);
280 pass->bindBuffers(helper->fIndexBuffer, nullptr, helper->fVertBuffer);
281 pass->drawIndexPattern(6, kBoxCountX, kIndexPatternRepeatCount, 4,
282 y * kBoxCountX * 4);
283
284 }
285 });
286
287 for (bool indexed : {false, true}) {
288 if (!dContext->priv().caps()->drawInstancedSupport()) {
289 break;
290 }
291
292 run_test(dContext, indexed ? "drawIndexedInstanced" : "drawInstanced",
293 reporter, sdc, gold,
294 [&](DrawMeshHelper* helper) {
295 helper->fIndexBuffer = indexed ? helper->getIndexBuffer() : nullptr;
296 TArray<uint16_t> baseIndexData;
297 baseIndexData.push_back(kBoxCountX/2 * 6); // for testing base index.
298 for (int i = 0; i < 6; ++i) {
299 baseIndexData.push_back(kIndexPattern[i]);
300 }
301 helper->fIndexBuffer2 = helper->makeIndexBuffer(baseIndexData.begin(),
302 baseIndexData.size());
303 helper->fInstBuffer = helper->makeVertexBuffer(boxes);
304 VALIDATE(helper->fInstBuffer);
305 helper->fVertBuffer =
306 helper->makeVertexBuffer(std::vector<float>{0,0, 0,1, 1,0, 1,1});
307 VALIDATE(helper->fVertBuffer);
308 helper->fVertBuffer2 = helper->makeVertexBuffer( // for testing base vertex.
309 std::vector<float>{-1,-1, -1,-1, 0,0, 0,1, 1,0, 1,1});
310 VALIDATE(helper->fVertBuffer2);
311 },
312 [&](DrawMeshHelper* helper) {
313 // Draw boxes one line at a time to exercise base instance, base vertex, and
314 // null vertex buffer.
315 for (int y = 0; y < kBoxCountY; ++y) {
316 sk_sp<const GrBuffer> vertexBuffer;
317 int baseVertex = 0;
318 switch (y % 3) {
319 case 0:
320 if (dContext->priv().caps()->shaderCaps()->fVertexIDSupport) {
321 break;
322 }
323 [[fallthrough]];
324 case 1:
325 vertexBuffer = helper->fVertBuffer;
326 break;
327 case 2:
328 vertexBuffer = helper->fVertBuffer2;
329 baseVertex = 2;
330 break;
331 }
332
333 GrPrimitiveType primitiveType = indexed ? GrPrimitiveType::kTriangles
335 auto pass = helper->bindPipeline(primitiveType, true,
336 SkToBool(vertexBuffer));
337 if (indexed) {
338 sk_sp<const GrBuffer> indexBuffer = (y % 2) ?
339 helper->fIndexBuffer2 : helper->fIndexBuffer;
340 VALIDATE(indexBuffer);
341 int baseIndex = (y % 2);
342 pass->bindBuffers(std::move(indexBuffer), helper->fInstBuffer,
343 std::move(vertexBuffer));
344 pass->drawIndexedInstanced(6, baseIndex, kBoxCountX, y * kBoxCountX,
345 baseVertex);
346 } else {
347 pass->bindBuffers(nullptr, helper->fInstBuffer,
348 std::move(vertexBuffer));
349 pass->drawInstanced(kBoxCountX, y * kBoxCountY, 4, baseVertex);
350 }
351 }
352 });
353 }
354
355 for (bool indexed : {false, true}) {
356 if (!dContext->priv().caps()->drawInstancedSupport()) {
357 break;
358 }
359
360 run_test(dContext, (indexed) ? "drawIndexedIndirect" : "drawIndirect",
361 reporter, sdc, gold,
362 [&](DrawMeshHelper* helper) {
363 TArray<uint16_t> baseIndexData;
364 baseIndexData.push_back(kBoxCountX/2 * 6); // for testing base index.
365 for (int j = 0; j < kBoxCountY; ++j) {
366 for (int i = 0; i < 6; ++i) {
367 baseIndexData.push_back(kIndexPattern[i]);
368 }
369 }
370 helper->fIndexBuffer2 = helper->makeIndexBuffer(baseIndexData.begin(),
371 baseIndexData.size());
372 VALIDATE(helper->fIndexBuffer2);
373 helper->fInstBuffer = helper->makeVertexBuffer(boxes);
374 VALIDATE(helper->fInstBuffer);
375 helper->fVertBuffer = helper->makeVertexBuffer(std::vector<float>{
376 -1,-1, 0,0, 0,1, 1,0, 1,1, -1,-1, 0,0, 1,0, 0,1, 1,1});
377 VALIDATE(helper->fVertBuffer);
378
379 GrDrawIndirectWriter indirectWriter;
380 GrDrawIndexedIndirectWriter indexedIndirectWriter;
381 if (indexed) {
382 // Make helper->fDrawIndirectBufferOffset nonzero.
383 sk_sp<const GrBuffer> ignoredBuff;
384 size_t ignoredOffset;
385 // Make a superfluous call to makeDrawIndirectSpace in order to test
386 // "offsetInBytes!=0" for the actual call to makeDrawIndexedIndirectSpace.
387 helper->target()->makeDrawIndirectSpace(29, &ignoredBuff, &ignoredOffset);
388 indexedIndirectWriter = helper->target()->makeDrawIndexedIndirectSpace(
391 } else {
392 // Make helper->fDrawIndirectBufferOffset nonzero.
393 sk_sp<const GrBuffer> ignoredBuff;
394 size_t ignoredOffset;
395 // Make a superfluous call to makeDrawIndexedIndirectSpace in order to test
396 // "offsetInBytes!=0" for the actual call to makeDrawIndirectSpace.
397 helper->target()->makeDrawIndexedIndirectSpace(7, &ignoredBuff,
398 &ignoredOffset);
399 indirectWriter = helper->target()->makeDrawIndirectSpace(
402 }
403
404 // Draw boxes one line at a time to exercise multiple draws.
405 for (int y = 0; y < kBoxCountY; ++y) {
406 int baseVertex = (y % 2) ? 1 : 6;
407 if (indexed) {
408 int baseIndex = 1 + y * 6;
409 indexedIndirectWriter.writeIndexed(6, baseIndex, kBoxCountX,
410 y * kBoxCountX, baseVertex);
411 } else {
412 indirectWriter.write(kBoxCountX, y * kBoxCountX, 4, baseVertex);
413 }
414 }
415 },
416 [&](DrawMeshHelper* helper) {
417 GrOpsRenderPass* pass;
418 if (indexed) {
419 pass = helper->bindPipeline(GrPrimitiveType::kTriangles, true, true);
420 pass->bindBuffers(helper->fIndexBuffer2, helper->fInstBuffer,
421 helper->fVertBuffer);
422 for (int i = 0; i < 3; ++i) {
423 int start = kBoxCountY * i / 3;
424 int end = kBoxCountY * (i + 1) / 3;
425 size_t offset = helper->fDrawIndirectBufferOffset + start *
428 end - start);
429 }
430 } else {
431 pass = helper->bindPipeline(GrPrimitiveType::kTriangleStrip, true, true);
432 pass->bindBuffers(nullptr, helper->fInstBuffer, helper->fVertBuffer);
433 for (int i = 0; i < 2; ++i) {
434 int start = kBoxCountY * i / 2;
435 int end = kBoxCountY * (i + 1) / 2;
436 size_t offset = helper->fDrawIndirectBufferOffset + start *
437 sizeof(GrDrawIndirectCommand);
439 end - start);
440 }
441 }
442 });
443 }
444}
static GrColor GrColorPackRGBA(unsigned r, unsigned g, unsigned b, unsigned a)
Definition GrColor.h:46
constexpr uint16_t kIndexPattern[6]
static constexpr int kBoxCount
#define VALIDATE(buff)
static constexpr int kBoxCountX
static constexpr int kIndexPatternRepeatCount
static constexpr int kImageWidth
static constexpr int kBoxCountY
static constexpr int kBoxSize
static constexpr int kImageHeight
GrPrimitiveType
Definition GrTypesPriv.h:42
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
#define ERRORF(r,...)
Definition Test.h:293
sk_sp< const GrBuffer > fInstBuffer
sk_sp< const GrBuffer > fIndexBuffer2
sk_sp< const GrBuffer > fVertBuffer
sk_sp< const GrBuffer > getIndexBuffer()
size_t fDrawIndirectBufferOffset
sk_sp< const GrBuffer > fDrawIndirectBuffer
GrMeshDrawTarget * target()
sk_sp< const GrBuffer > fVertBuffer2
sk_sp< const GrBuffer > fIndexBuffer
sk_sp< const GrBuffer > makeVertexBuffer(const TArray< T > &data)
sk_sp< const GrBuffer > makeIndexBuffer(const uint16_t[], int count)
GrOpsRenderPass * bindPipeline(GrPrimitiveType, bool isInstanced, bool hasVertexBuffer)
virtual GrDrawIndexedIndirectWriter makeDrawIndexedIndirectSpace(int drawCount, sk_sp< const GrBuffer > *, size_t *offsetInBytes)=0
virtual GrDrawIndirectWriter makeDrawIndirectSpace(int drawCount, sk_sp< const GrBuffer > *buffer, size_t *offsetInBytes)=0
void bindBuffers(sk_sp< const GrBuffer > indexBuffer, sk_sp< const GrBuffer > instanceBuffer, sk_sp< const GrBuffer > vertexBuffer, GrPrimitiveRestart=GrPrimitiveRestart::kNo)
void drawIndexedIndirect(const GrBuffer *drawIndirectBuffer, size_t bufferOffset, int drawCount)
void drawIndirect(const GrBuffer *drawIndirectBuffer, size_t bufferOffset, int drawCount)
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition SkBitmap.cpp:232
T * get() const
Definition SkRefCnt.h:303
static std::unique_ptr< SurfaceDrawContext > Make(GrRecordingContext *, GrColorType, sk_sp< GrSurfaceProxy >, sk_sp< SkColorSpace >, GrSurfaceOrigin, const SkSurfaceProps &)
int size() const
Definition SkTArray.h:416
const Paint & paint
glong glong end
double y
double x
void run_test(skiatest::Reporter *reporter, Context *context, SkISize surfaceSize, SkISize recordingSize, SkISize replayOffset, DrawCallback draw, const std::vector< Expectation > &expectations)
Point offset
float fX
float fY
GrColor fColor
void writeIndexed(uint32_t indexCount, uint32_t baseIndex, uint32_t instanceCount, uint32_t baseInstance, int32_t baseVertex)
void write(uint32_t instanceCount, uint32_t baseInstance, uint32_t vertexCount, int32_t baseVertex)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659

◆ run_test()

static void run_test ( GrDirectContext dContext,
const char *  testName,
skiatest::Reporter reporter,
const std::unique_ptr< skgpu::ganesh::SurfaceDrawContext > &  sdc,
const SkBitmap gold,
std::function< void(DrawMeshHelper *)>  prepareFn,
std::function< void(DrawMeshHelper *)>  executeFn 
)
static

This is a GPU-backend specific test. It tries to test all possible usecases of GrOpsRenderPass::draw*. The test works by drawing checkerboards of colored boxes, reading back the pixels, and comparing with expected results. The boxes are drawn on integer boundaries and the (opaque) colors are chosen from the set (r,g,b) = (0,255)^3, so the GPU renderings ought to produce exact matches.

Definition at line 638 of file GrMeshTest.cpp.

644 {
645 const int w = gold.width(), h = gold.height();
646 const uint32_t* goldPx = reinterpret_cast<const uint32_t*>(gold.getPixels());
647 if (h != sdc->height() || w != sdc->width()) {
648 ERRORF(reporter, "[%s] expectation and rtc not compatible (?).", testName);
649 return;
650 }
651 if (sizeof(uint32_t) * kImageWidth != gold.rowBytes()) {
652 ERRORF(reporter, "[%s] unexpected row bytes in gold image", testName);
653 return;
654 }
655
656 GrPixmap resultPM = GrPixmap::Allocate(gold.info());
657 sdc->clear(SkPMColor4f::FromBytes_RGBA(0xbaaaaaad));
658 sdc->addDrawOp(MeshTestOp::Make(dContext, prepareFn, executeFn));
659
660 sdc->readPixels(dContext, resultPM, {0, 0});
661
662#ifdef WRITE_PNG_CONTEXT_TYPE
663#define STRINGIFY(X) #X
664#define TOSTRING(X) STRINGIFY(X)
665 SkString filename;
666 filename.printf("GrMeshTest_%s_%s.png", TOSTRING(WRITE_PNG_CONTEXT_TYPE), testName);
667 SkDebugf("writing %s...\n", filename.c_str());
668 ToolUtils::EncodeImageToPngFile(filename.c_str(), resultPM);
669#endif
670
671 for (int y = 0; y < h; ++y) {
672 for (int x = 0; x < w; ++x) {
673 uint32_t expected = goldPx[y * kImageWidth + x];
674 uint32_t actual = static_cast<uint32_t*>(resultPM.addr())[y * kImageWidth + x];
675 if (expected != actual) {
676 ERRORF(reporter, "[%s] pixel (%i,%i): got 0x%x expected 0x%x",
677 testName, x, y, actual, expected);
678 return;
679 }
680 }
681 }
682}
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
T * addr() const
Definition GrPixmap.h:20
static GrPixmap Allocate(const GrImageInfo &info)
Definition GrPixmap.h:101
int width() const
Definition SkBitmap.h:149
size_t rowBytes() const
Definition SkBitmap.h:238
void * getPixels() const
Definition SkBitmap.h:283
const SkImageInfo & info() const
Definition SkBitmap.h:139
int height() const
Definition SkBitmap.h:158
void printf(const char format[],...) SK_PRINTF_LIKE(2
Definition SkString.cpp:534
const char * c_str() const
Definition SkString.h:133
bool EncodeImageToPngFile(const char *path, const SkBitmap &src)
SkScalar w
SkScalar h
static SkRGBA4f FromBytes_RGBA(uint32_t color)

◆ SKGPU_DECLARE_STATIC_UNIQUE_KEY()

SKGPU_DECLARE_STATIC_UNIQUE_KEY ( gIndexBufferKey  )

Variable Documentation

◆ kBoxCount

constexpr int kBoxCount = kBoxCountY * kBoxCountX
staticconstexpr

Definition at line 87 of file GrMeshTest.cpp.

◆ kBoxCountX

constexpr int kBoxCountX = 8
staticconstexpr

Definition at line 86 of file GrMeshTest.cpp.

◆ kBoxCountY

constexpr int kBoxCountY = 8
staticconstexpr

Definition at line 85 of file GrMeshTest.cpp.

◆ kBoxSize

constexpr int kBoxSize = 2
staticconstexpr

Definition at line 84 of file GrMeshTest.cpp.

◆ kImageHeight

constexpr int kImageHeight = kBoxCountX * kBoxSize
staticconstexpr

Definition at line 90 of file GrMeshTest.cpp.

◆ kImageWidth

constexpr int kImageWidth = kBoxCountY * kBoxSize
staticconstexpr

Definition at line 89 of file GrMeshTest.cpp.

◆ kIndexPattern

constexpr uint16_t kIndexPattern[6] = {0, 1, 2, 1, 2, 3}
constexpr

Definition at line 93 of file GrMeshTest.cpp.

93{0, 1, 2, 1, 2, 3};

◆ kIndexPatternRepeatCount

constexpr int kIndexPatternRepeatCount = 3
staticconstexpr

Definition at line 92 of file GrMeshTest.cpp.