Add a writer class for indirect draw commands
This enforces write-only access to the mapped buffers, will enable
chaining of indirect strokes, and gives us the ability to reorder the
fields for Metal.
Bug: chromium:1172543
Bug: skia:11291
Bug: skia:10419
Change-Id: I4449ff85dd0019f6d6d6781ede52bcf26dee8b02
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/367416
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrBufferAllocPool.h b/src/gpu/GrBufferAllocPool.h
index ce4b02c..ad57668 100644
--- a/src/gpu/GrBufferAllocPool.h
+++ b/src/gpu/GrBufferAllocPool.h
@@ -14,6 +14,7 @@
#include "include/private/SkTArray.h"
#include "include/private/SkTDArray.h"
#include "src/gpu/GrCpuBuffer.h"
+#include "src/gpu/GrDrawIndirectCommand.h"
#include "src/gpu/GrNonAtomicRef.h"
class GrGpu;
@@ -319,23 +320,23 @@
GrDrawIndirectBufferAllocPool(GrGpu* gpu, sk_sp<CpuBufferCache> cpuBufferCache)
: GrBufferAllocPool(gpu, GrGpuBufferType::kDrawIndirect, std::move(cpuBufferCache)) {}
- GrDrawIndirectCommand* makeSpace(int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offset) {
- return static_cast<GrDrawIndirectCommand*>(this->GrBufferAllocPool::makeSpace(
- (size_t)drawCount * sizeof(GrDrawIndirectCommand), 4, buffer, offset));
+ GrDrawIndirectWriter makeSpace(int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offset) {
+ return this->GrBufferAllocPool::makeSpace(drawCount * sizeof(GrDrawIndirectCommand), 4,
+ buffer, offset);
}
void putBack(int drawCount) {
- this->GrBufferAllocPool::putBack((size_t)drawCount * sizeof(GrDrawIndirectCommand));
+ this->GrBufferAllocPool::putBack(drawCount * sizeof(GrDrawIndirectCommand));
}
- GrDrawIndexedIndirectCommand* makeIndexedSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
- size_t* offset) {
- return static_cast<GrDrawIndexedIndirectCommand*>(this->GrBufferAllocPool::makeSpace(
- (size_t)drawCount * sizeof(GrDrawIndexedIndirectCommand), 4, buffer, offset));
+ GrDrawIndexedIndirectWriter makeIndexedSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
+ size_t* offset) {
+ return this->GrBufferAllocPool::makeSpace(
+ drawCount * sizeof(GrDrawIndexedIndirectCommand), 4, buffer, offset);
}
void putBackIndexed(int drawCount) {
- this->GrBufferAllocPool::putBack((size_t)drawCount * sizeof(GrDrawIndexedIndirectCommand));
+ this->GrBufferAllocPool::putBack(drawCount * sizeof(GrDrawIndexedIndirectCommand));
}
using GrBufferAllocPool::unmap;
diff --git a/src/gpu/GrDrawIndirectCommand.h b/src/gpu/GrDrawIndirectCommand.h
new file mode 100644
index 0000000..ba7cb05
--- /dev/null
+++ b/src/gpu/GrDrawIndirectCommand.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDrawIndirectCommand_DEFINED
+#define GrDrawIndirectCommand_DEFINED
+
+#include "src/gpu/GrCaps.h"
+#include <array>
+
+// Draw commands on the GPU are simple tuples of uint32_t. The ordering is backend-specific.
+using GrDrawIndirectCommand = std::array<uint32_t, 4>;
+using GrDrawIndexedIndirectCommand = std::array<uint32_t, 5>;
+
+// Helper for writing commands to an indirect draw buffer. Usage:
+//
+// GrDrawIndirectWriter indirectWriter = target->makeDrawIndirectSpace(...);
+// indirectWriter.write(...);
+// indirectWriter.write(...);
+struct GrDrawIndirectWriter {
+public:
+ GrDrawIndirectWriter() = default;
+ GrDrawIndirectWriter(void* data) : fData(static_cast<GrDrawIndirectCommand*>(data)) {}
+ GrDrawIndirectWriter(const GrDrawIndirectWriter&) = delete;
+ GrDrawIndirectWriter(GrDrawIndirectWriter&& that) { *this = std::move(that); }
+
+ GrDrawIndirectWriter& operator=(const GrDrawIndirectWriter&) = delete;
+ GrDrawIndirectWriter& operator=(GrDrawIndirectWriter&& that) {
+ fData = that.fData;
+ that.fData = nullptr;
+ return *this;
+ }
+
+ bool isValid() const { return fData != nullptr; }
+
+ inline void write(uint32_t instanceCount, uint32_t baseInstance, uint32_t vertexCount,
+ uint32_t baseVertex, const GrCaps&) {
+ *fData++ = {vertexCount, instanceCount, baseVertex, baseInstance};
+ }
+
+private:
+ GrDrawIndirectCommand* fData;
+};
+
+// Helper for writing commands to an indexed indirect draw buffer. Usage:
+//
+// GrDrawIndexedIndirectWriter indirectWriter = target->makeDrawIndexedIndirectSpace(...);
+// indirectWriter.writeIndexed(...);
+// indirectWriter.writeIndexed(...);
+struct GrDrawIndexedIndirectWriter {
+public:
+ GrDrawIndexedIndirectWriter() = default;
+ GrDrawIndexedIndirectWriter(void* data)
+ : fData(static_cast<GrDrawIndexedIndirectCommand*>(data)) {}
+ GrDrawIndexedIndirectWriter(const GrDrawIndexedIndirectWriter&) = delete;
+ GrDrawIndexedIndirectWriter(GrDrawIndexedIndirectWriter&& that) { *this = std::move(that); }
+
+ GrDrawIndexedIndirectWriter& operator=(const GrDrawIndexedIndirectWriter&) = delete;
+ GrDrawIndexedIndirectWriter& operator=(GrDrawIndexedIndirectWriter&& that) {
+ fData = that.fData;
+ that.fData = nullptr;
+ return *this;
+ }
+
+ bool isValid() const { return fData != nullptr; }
+
+ inline void writeIndexed(uint32_t indexCount, uint32_t baseIndex, uint32_t instanceCount,
+ uint32_t baseInstance, uint32_t baseVertex, const GrCaps&) {
+ *fData++ = {indexCount, instanceCount, baseIndex, baseVertex, baseInstance};
+ }
+
+private:
+ GrDrawIndexedIndirectCommand* fData;
+};
+
+#endif
diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h
index 5065fec..77e85d0 100644
--- a/src/gpu/GrOpFlushState.h
+++ b/src/gpu/GrOpFlushState.h
@@ -134,12 +134,13 @@
uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
sk_sp<const GrBuffer>*, int* startIndex,
int* actualIndexCount) final;
- GrDrawIndirectCommand* makeDrawIndirectSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
- size_t* offset) override {
+ GrDrawIndirectWriter makeDrawIndirectSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
+ size_t* offset) override {
return fDrawIndirectPool.makeSpace(drawCount, buffer, offset);
}
- GrDrawIndexedIndirectCommand* makeDrawIndexedIndirectSpace(
- int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offset) override {
+ GrDrawIndexedIndirectWriter makeDrawIndexedIndirectSpace(int drawCount,
+ sk_sp<const GrBuffer>* buffer,
+ size_t* offset) override {
return fDrawIndirectPool.makeIndexedSpace(drawCount, buffer, offset);
}
void putBackIndices(int indexCount) final;
diff --git a/src/gpu/GrOpsRenderPass.cpp b/src/gpu/GrOpsRenderPass.cpp
index e48c14c..88468af 100644
--- a/src/gpu/GrOpsRenderPass.cpp
+++ b/src/gpu/GrOpsRenderPass.cpp
@@ -10,6 +10,7 @@
#include "include/core/SkRect.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrCpuBuffer.h"
+#include "src/gpu/GrDrawIndirectCommand.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrPrimitiveProcessor.h"
#include "src/gpu/GrProgramInfo.h"
@@ -284,13 +285,13 @@
if (!this->gpu()->caps()->nativeDrawIndirectSupport()) {
// Polyfill indirect draws with looping instanced calls.
SkASSERT(drawIndirectBuffer->isCpuBuffer());
- auto cpuIndirectBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
- auto cmd = reinterpret_cast<const GrDrawIndirectCommand*>(
+ auto* cpuIndirectBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
+ auto* cmds = reinterpret_cast<const GrDrawIndirectCommand*>(
cpuIndirectBuffer->data() + bufferOffset);
- auto end = cmd + drawCount;
- for (; cmd != end; ++cmd) {
- this->onDrawInstanced(cmd->fInstanceCount, cmd->fBaseInstance, cmd->fVertexCount,
- cmd->fBaseVertex);
+ for (int i = 0; i < drawCount; ++i) {
+ // TODO: SkASSERT(caps.drawIndirectSignature() == standard);
+ auto [vertexCount, instanceCount, baseVertex, baseInstance] = cmds[i];
+ this->onDrawInstanced(instanceCount, baseInstance, vertexCount, baseVertex);
}
return;
}
@@ -312,13 +313,14 @@
this->gpu()->caps()->nativeDrawIndexedIndirectIsBroken()) {
// Polyfill indexedIndirect draws with looping indexedInstanced calls.
SkASSERT(drawIndirectBuffer->isCpuBuffer());
- auto cpuIndirectBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
- auto cmd = reinterpret_cast<const GrDrawIndexedIndirectCommand*>(
+ auto* cpuIndirectBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
+ auto* cmds = reinterpret_cast<const GrDrawIndexedIndirectCommand*>(
cpuIndirectBuffer->data() + bufferOffset);
- auto end = cmd + drawCount;
- for (; cmd != end; ++cmd) {
- this->onDrawIndexedInstanced(cmd->fIndexCount, cmd->fBaseIndex, cmd->fInstanceCount,
- cmd->fBaseInstance, cmd->fBaseVertex);
+ for (int i = 0; i < drawCount; ++i) {
+ // TODO: SkASSERT(caps.drawIndirectSignature() == standard);
+ auto [indexCount, instanceCount, baseIndex, baseVertex, baseInstance] = cmds[i];
+ this->onDrawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance,
+ baseVertex);
}
return;
}
diff --git a/src/gpu/gl/GrGLOpsRenderPass.cpp b/src/gpu/gl/GrGLOpsRenderPass.cpp
index be69a2b..812ad42 100644
--- a/src/gpu/gl/GrGLOpsRenderPass.cpp
+++ b/src/gpu/gl/GrGLOpsRenderPass.cpp
@@ -286,11 +286,12 @@
while (drawCount) {
int countInBatch = std::min(drawCount, kMaxDrawCountPerBatch);
for (int i = 0; i < countInBatch; ++i) {
- const auto& cmd = cmds[i];
- fFirsts[i] = cmd.fBaseVertex;
- fCounts[i] = cmd.fVertexCount;
- fInstanceCounts[i] = cmd.fInstanceCount;
- fBaseInstances[i] = cmd.fBaseInstance;
+ // TODO: SkASSERT(caps.drawIndirectSignature() == standard);
+ auto [vertexCount, instanceCount, baseVertex, baseInstance] = cmds[i];
+ fFirsts[i] = baseVertex;
+ fCounts[i] = vertexCount;
+ fInstanceCounts[i] = instanceCount;
+ fBaseInstances[i] = baseInstance;
}
if (countInBatch == 1) {
GL_CALL(DrawArraysInstancedBaseInstance(glPrimType, fFirsts[0], fCounts[0],
@@ -359,12 +360,13 @@
while (drawCount) {
int countInBatch = std::min(drawCount, kMaxDrawCountPerBatch);
for (int i = 0; i < countInBatch; ++i) {
- const auto& cmd = cmds[i];
- fCounts[i] = cmd.fIndexCount;
- fIndices[i] = this->offsetForBaseIndex(cmd.fBaseIndex);
- fInstanceCounts[i] = cmd.fInstanceCount;
- fBaseVertices[i] = cmd.fBaseVertex;
- fBaseInstances[i] = cmd.fBaseInstance;
+ // TODO: SkASSERT(caps.drawIndirectSignature() == standard);
+ auto [indexCount, instanceCount, baseIndex, baseVertex, baseInstance] = cmds[i];
+ fCounts[i] = indexCount;
+ fIndices[i] = this->offsetForBaseIndex(baseIndex);
+ fInstanceCounts[i] = instanceCount;
+ fBaseVertices[i] = baseVertex;
+ fBaseInstances[i] = baseInstance;
}
if (countInBatch == 1) {
GL_CALL(DrawElementsInstancedBaseVertexBaseInstance(glPrimType, fCounts[0],
diff --git a/src/gpu/mock/GrMockOpTarget.h b/src/gpu/mock/GrMockOpTarget.h
index a8cc8c5..9564cf3 100644
--- a/src/gpu/mock/GrMockOpTarget.h
+++ b/src/gpu/mock/GrMockOpTarget.h
@@ -56,32 +56,35 @@
return fStaticVertexData;
}
- GrDrawIndirectCommand* makeDrawIndirectSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
- size_t* offsetInBytes) override {
- int staticBufferCount = (int)SK_ARRAY_COUNT(fStaticDrawIndirectData);
- if (drawCount > staticBufferCount) {
- SK_ABORT("FATAL: wanted %i static drawIndirect elements; only have %i.\n",
- drawCount, staticBufferCount);
+ GrDrawIndirectWriter makeDrawIndirectSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
+ size_t* offsetInBytes) override {
+ if (sizeof(GrDrawIndirectCommand) * drawCount > sizeof(fStaticIndirectData)) {
+ SK_ABORT("FATAL: wanted %zu bytes of static indirect data; only have %zu.\n",
+ sizeof(GrDrawIndirectCommand) * drawCount, sizeof(fStaticIndirectData));
}
*offsetInBytes = 0;
- return fStaticDrawIndirectData;
+ return fStaticIndirectData;
}
void putBackIndirectDraws(int count) override { /* no-op */ }
- GrDrawIndexedIndirectCommand* makeDrawIndexedIndirectSpace(
- int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offsetInBytes) override {
- int staticBufferCount = (int)SK_ARRAY_COUNT(fStaticDrawIndexedIndirectData);
- if (drawCount > staticBufferCount) {
- SK_ABORT("FATAL: wanted %i static drawIndexedIndirect elements; only have %i.\n",
- drawCount, staticBufferCount);
+ GrDrawIndexedIndirectWriter makeDrawIndexedIndirectSpace(int drawCount,
+ sk_sp<const GrBuffer>* buffer,
+ size_t* offsetInBytes) override {
+ if (sizeof(GrDrawIndexedIndirectCommand) * drawCount > sizeof(fStaticIndirectData)) {
+ SK_ABORT("FATAL: wanted %zu bytes of static indirect data; only have %zu.\n",
+ sizeof(GrDrawIndexedIndirectCommand) * drawCount, sizeof(fStaticIndirectData));
}
*offsetInBytes = 0;
- return fStaticDrawIndexedIndirectData;
+ return fStaticIndirectData;
}
void putBackIndexedIndirectDraws(int count) override { /* no-op */ }
+ // Call these methods to see what got written after the previous call to make*Space.
+ const void* peekStaticVertexData() const { return fStaticVertexData; }
+ const void* peekStaticIndirectData() const { return fStaticIndirectData; }
+
#define UNIMPL(...) __VA_ARGS__ override { SK_ABORT("unimplemented."); }
UNIMPL(void recordDraw(const GrGeometryProcessor*, const GrSimpleMesh[], int,
const GrSurfaceProxy* const[], GrPrimitiveType))
@@ -100,8 +103,7 @@
private:
sk_sp<GrDirectContext> fMockContext;
char fStaticVertexData[6 * 1024 * 1024];
- GrDrawIndirectCommand fStaticDrawIndirectData[32];
- GrDrawIndexedIndirectCommand fStaticDrawIndexedIndirectData[32];
+ char fStaticIndirectData[sizeof(GrDrawIndexedIndirectCommand) * 32];
SkSTArenaAllocWithReset<1024 * 1024> fAllocator;
GrXferProcessor::DstProxyView fDstProxyView;
};
diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h
index b8e6c06..4704b46 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -10,6 +10,7 @@
#include "src/core/SkArenaAlloc.h"
#include "src/gpu/GrAppliedClip.h"
+#include "src/gpu/GrDrawIndirectCommand.h"
#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrSimpleMesh.h"
#include "src/gpu/ops/GrDrawOp.h"
@@ -199,16 +200,16 @@
* Makes space for elements in a draw-indirect buffer. Upon success, the returned pointer is a
* CPU mapping where the data should be written.
*/
- virtual GrDrawIndirectCommand* makeDrawIndirectSpace(int drawCount,
- sk_sp<const GrBuffer>* buffer,
- size_t* offsetInBytes) = 0;
+ virtual GrDrawIndirectWriter makeDrawIndirectSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
+ size_t* offsetInBytes) = 0;
/**
* Makes space for elements in a draw-indexed-indirect buffer. Upon success, the returned
* pointer is a CPU mapping where the data should be written.
*/
- virtual GrDrawIndexedIndirectCommand* makeDrawIndexedIndirectSpace(
- int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offsetInBytes) = 0;
+ virtual GrDrawIndexedIndirectWriter makeDrawIndexedIndirectSpace(int drawCount,
+ sk_sp<const GrBuffer>*,
+ size_t* offsetInBytes) = 0;
/** Helpers for ops which over-allocate and then return excess data to the pool. */
virtual void putBackIndices(int indices) = 0;
diff --git a/src/gpu/tessellate/GrPathTessellator.cpp b/src/gpu/tessellate/GrPathTessellator.cpp
index adeceb9..f3dc4fb 100644
--- a/src/gpu/tessellate/GrPathTessellator.cpp
+++ b/src/gpu/tessellate/GrPathTessellator.cpp
@@ -49,9 +49,10 @@
void GrPathIndirectTessellator::prepare(GrMeshDrawOp::Target* target, const SkMatrix& viewMatrix,
const SkPath& path,
const BreadcrumbTriangleList* breadcrumbTriangleList) {
+ const GrCaps& caps = target->caps();
SkASSERT(fTotalInstanceCount == 0);
SkASSERT(fIndirectDrawCount == 0);
- SkASSERT(target->caps().drawInstancedSupport());
+ SkASSERT(caps.drawInstancedSupport());
int instanceLockCount = fOuterCurveInstanceCount;
if (fDrawInnerFan) {
@@ -110,9 +111,9 @@
// possible resolve level (kMaxResolveLevel; resolveLevel=0 never has any instances), plus one
// more for the optional inner fan triangles.
int indirectLockCnt = kMaxResolveLevel + 1;
- GrDrawIndexedIndirectCommand* indirectData = target->makeDrawIndexedIndirectSpace(
+ GrDrawIndexedIndirectWriter indirectWriter = target->makeDrawIndexedIndirectSpace(
indirectLockCnt, &fIndirectDrawBuffer, &fIndirectDrawOffset);
- if (!indirectData) {
+ if (!indirectWriter.isValid()) {
SkASSERT(!fIndirectDrawBuffer);
return;
}
@@ -126,8 +127,10 @@
// at the beginning of the instance buffer. Add a special-case indirect draw here that will
// emit the triangles [P0, P1, P2] from these 4-point instances.
SkASSERT(fIndirectDrawCount < indirectLockCnt);
- indirectData[fIndirectDrawCount++] = GrMiddleOutCubicShader::MakeDrawTrianglesIndirectCmd(
- numTrianglesAtBeginningOfData, fBaseInstance);
+ GrMiddleOutCubicShader::WriteDrawTrianglesIndirectCmd(&indirectWriter,
+ numTrianglesAtBeginningOfData,
+ fBaseInstance, caps);
+ ++fIndirectDrawCount;
runningInstanceCount = numTrianglesAtBeginningOfData;
}
SkASSERT(fResolveLevelCounts[0] == 0);
@@ -139,8 +142,11 @@
}
instanceLocations[resolveLevel] = instanceData + runningInstanceCount * 4;
SkASSERT(fIndirectDrawCount < indirectLockCnt);
- indirectData[fIndirectDrawCount++] = GrMiddleOutCubicShader::MakeDrawCubicsIndirectCmd(
- resolveLevel, instanceCountAtCurrLevel, fBaseInstance + runningInstanceCount);
+ GrMiddleOutCubicShader::WriteDrawCubicsIndirectCmd(&indirectWriter, resolveLevel,
+ instanceCountAtCurrLevel,
+ fBaseInstance + runningInstanceCount,
+ caps);
+ ++fIndirectDrawCount;
runningInstanceCount += instanceCountAtCurrLevel;
}
diff --git a/src/gpu/tessellate/GrStencilPathShader.h b/src/gpu/tessellate/GrStencilPathShader.h
index 9e44b82..87a01c9 100644
--- a/src/gpu/tessellate/GrStencilPathShader.h
+++ b/src/gpu/tessellate/GrStencilPathShader.h
@@ -8,6 +8,7 @@
#ifndef GrStencilPathShader_DEFINED
#define GrStencilPathShader_DEFINED
+#include "src/gpu/GrDrawIndirectCommand.h"
#include "src/gpu/tessellate/GrPathShader.h"
#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
@@ -165,25 +166,26 @@
// Configures an indirect draw to render cubic instances with 2^resolveLevel evenly-spaced (in
// the parametric sense) line segments.
- static GrDrawIndexedIndirectCommand MakeDrawCubicsIndirectCmd(int resolveLevel,
- uint32_t instanceCount,
- uint32_t baseInstance) {
+ static void WriteDrawCubicsIndirectCmd(GrDrawIndexedIndirectWriter* indirectWriter,
+ int resolveLevel, uint32_t instanceCount,
+ uint32_t baseInstance, const GrCaps& caps) {
SkASSERT(resolveLevel > 0 && resolveLevel <= GrTessellationPathRenderer::kMaxResolveLevel);
// Starting at baseIndex=3, the index buffer triangulates a cubic with 2^kMaxResolveLevel
// line segments. Each index value corresponds to a parametric T value on the curve. Since
// the triangles are arranged in "middle-out" order, we can conveniently control the
// resolveLevel by changing only the indexCount.
uint32_t indexCount = NumVerticesAtResolveLevel(resolveLevel);
- return {indexCount, instanceCount, 3, 0, baseInstance};
+ indirectWriter->writeIndexed(indexCount, 3, instanceCount, baseInstance, 0, caps);
}
// For performance reasons we can often express triangles as an indirect cubic draw and sneak
// them in alongside the other indirect draws. This method configures an indirect draw to emit
// the triangle [P0, P1, P2] from a 4-point instance.
- static GrDrawIndexedIndirectCommand MakeDrawTrianglesIndirectCmd(uint32_t instanceCount,
- uint32_t baseInstance) {
+ static void WriteDrawTrianglesIndirectCmd(GrDrawIndexedIndirectWriter* indirectWriter,
+ uint32_t instanceCount, uint32_t baseInstance,
+ const GrCaps& caps) {
// Indices 0,1,2 have special index values that emit points P0, P1, and P2 respectively.
- return {3, instanceCount, 0, 0, baseInstance};
+ indirectWriter->writeIndexed(3, 0, instanceCount, baseInstance, 0, caps);
}
// Returns the index buffer that should be bound when drawing with this shader.
diff --git a/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp b/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp
index 1e8080c..7ca6467 100644
--- a/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp
+++ b/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp
@@ -599,11 +599,14 @@
return;
}
+ const GrCaps& caps = target->caps();
+
// Allocate enough indirect commands for every resolve level. We will putBack the unused ones
// at the end.
- GrDrawIndirectCommand* drawIndirectData = target->makeDrawIndirectSpace(
- kMaxResolveLevel + 1, &fDrawIndirectBuffer, &fDrawIndirectOffset);
- if (!drawIndirectData) {
+ GrDrawIndirectWriter indirectWriter = target->makeDrawIndirectSpace(kMaxResolveLevel + 1,
+ &fDrawIndirectBuffer,
+ &fDrawIndirectOffset);
+ if (!indirectWriter.isValid()) {
SkASSERT(!fDrawIndirectBuffer);
return;
}
@@ -627,11 +630,9 @@
for (int i = 0; i <= kMaxResolveLevel; ++i) {
if (fResolveLevelCounts[i]) {
int numEdges = numExtraEdgesInJoin + num_edges_in_resolve_level(i);
- auto& cmd = drawIndirectData[fDrawIndirectCount++];
- cmd.fVertexCount = numEdges * 2;
- cmd.fInstanceCount = fResolveLevelCounts[i];
- cmd.fBaseVertex = 0;
- cmd.fBaseInstance = baseInstance + currentInstanceIdx;
+ indirectWriter.write(fResolveLevelCounts[i], baseInstance + currentInstanceIdx,
+ numEdges * 2, 0, caps);
+ ++fDrawIndirectCount;
numEdgesPerResolveLevel[i] = numEdges;
nextInstanceLocations[i] = instanceData + currentInstanceIdx;
#ifdef SK_DEBUG
diff --git a/src/gpu/tessellate/GrStrokeIndirectTessellator.h b/src/gpu/tessellate/GrStrokeIndirectTessellator.h
index 54bb7ed..c91bfc2 100644
--- a/src/gpu/tessellate/GrStrokeIndirectTessellator.h
+++ b/src/gpu/tessellate/GrStrokeIndirectTessellator.h
@@ -61,9 +61,9 @@
#if GR_TEST_UTILS
public:
- void verifyResolveLevels(skiatest::Reporter*, GrMeshDrawOp::Target*, const SkMatrix&,
+ void verifyResolveLevels(skiatest::Reporter*, class GrMockOpTarget*, const SkMatrix&,
const SkPath&, const SkStrokeRec&);
- void verifyBuffers(skiatest::Reporter*, GrMeshDrawOp::Target*, const SkMatrix&,
+ void verifyBuffers(skiatest::Reporter*, class GrMockOpTarget*, const SkMatrix&,
const SkStrokeRec&);
class Benchmark;
#endif