Remove shims for reordering indirect draw command signatures

Change-Id: I0eb48cc8a7721cc0fbdfa579b36db5e6ed0aa695
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/368917
Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Chris Dalton 2021-02-10 12:55:48 -07:00
parent 9374617a4c
commit b849f7a791
8 changed files with 37 additions and 33 deletions

View File

@ -8,12 +8,28 @@
#ifndef GrDrawIndirectCommand_DEFINED
#define GrDrawIndirectCommand_DEFINED
#include "src/gpu/GrCaps.h"
#include <array>
#include <stdint.h>
#include <utility>
// 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>;
struct GrDrawIndirectCommand {
uint32_t fVertexCount;
uint32_t fInstanceCount;
int32_t fBaseVertex;
uint32_t fBaseInstance;
};
static_assert(sizeof(GrDrawIndirectCommand) == 16, "GrDrawIndirectCommand must be tightly packed");
struct GrDrawIndexedIndirectCommand {
uint32_t fIndexCount;
uint32_t fInstanceCount;
uint32_t fBaseIndex;
int32_t fBaseVertex;
uint32_t fBaseInstance;
};
static_assert(sizeof(GrDrawIndexedIndirectCommand) == 20,
"GrDrawIndexedIndirectCommand must be tightly packed");
// Helper for writing commands to an indirect draw buffer. Usage:
//
@ -37,7 +53,7 @@ public:
bool isValid() const { return fData != nullptr; }
inline void write(uint32_t instanceCount, uint32_t baseInstance, uint32_t vertexCount,
uint32_t baseVertex, const GrCaps&) {
int32_t baseVertex) {
*fData++ = {vertexCount, instanceCount, baseVertex, baseInstance};
}
@ -68,7 +84,7 @@ public:
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&) {
uint32_t baseInstance, int32_t baseVertex) {
*fData++ = {indexCount, instanceCount, baseIndex, baseVertex, baseInstance};
}

View File

@ -289,7 +289,6 @@ void GrOpsRenderPass::drawIndirect(const GrBuffer* drawIndirectBuffer, size_t bu
auto* cmds = reinterpret_cast<const GrDrawIndirectCommand*>(
cpuIndirectBuffer->data() + bufferOffset);
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);
}
@ -317,7 +316,6 @@ void GrOpsRenderPass::drawIndexedIndirect(const GrBuffer* drawIndirectBuffer, si
auto* cmds = reinterpret_cast<const GrDrawIndexedIndirectCommand*>(
cpuIndirectBuffer->data() + bufferOffset);
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);

View File

@ -286,7 +286,6 @@ void GrGLOpsRenderPass::multiDrawArraysANGLEOrWebGL(const GrBuffer* drawIndirect
while (drawCount) {
int countInBatch = std::min(drawCount, kMaxDrawCountPerBatch);
for (int i = 0; i < countInBatch; ++i) {
// TODO: SkASSERT(caps.drawIndirectSignature() == standard);
auto [vertexCount, instanceCount, baseVertex, baseInstance] = cmds[i];
fFirsts[i] = baseVertex;
fCounts[i] = vertexCount;
@ -360,7 +359,6 @@ void GrGLOpsRenderPass::multiDrawElementsANGLEOrWebGL(const GrBuffer* drawIndire
while (drawCount) {
int countInBatch = std::min(drawCount, kMaxDrawCountPerBatch);
for (int i = 0; i < countInBatch; ++i) {
// TODO: SkASSERT(caps.drawIndirectSignature() == standard);
auto [indexCount, instanceCount, baseIndex, baseVertex, baseInstance] = cmds[i];
fCounts[i] = indexCount;
fIndices[i] = this->offsetForBaseIndex(baseIndex);

View File

@ -49,10 +49,9 @@ GrPathIndirectTessellator::GrPathIndirectTessellator(const SkMatrix& viewMatrix,
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(caps.drawInstancedSupport());
SkASSERT(target->caps().drawInstancedSupport());
int instanceLockCount = fOuterCurveInstanceCount;
if (fDrawInnerFan) {
@ -129,7 +128,7 @@ void GrPathIndirectTessellator::prepare(GrMeshDrawOp::Target* target, const SkMa
SkASSERT(fIndirectDrawCount < indirectLockCnt);
GrMiddleOutCubicShader::WriteDrawTrianglesIndirectCmd(&indirectWriter,
numTrianglesAtBeginningOfData,
fBaseInstance, caps);
fBaseInstance);
++fIndirectDrawCount;
runningInstanceCount = numTrianglesAtBeginningOfData;
}
@ -144,8 +143,7 @@ void GrPathIndirectTessellator::prepare(GrMeshDrawOp::Target* target, const SkMa
SkASSERT(fIndirectDrawCount < indirectLockCnt);
GrMiddleOutCubicShader::WriteDrawCubicsIndirectCmd(&indirectWriter, resolveLevel,
instanceCountAtCurrLevel,
fBaseInstance + runningInstanceCount,
caps);
fBaseInstance + runningInstanceCount);
++fIndirectDrawCount;
runningInstanceCount += instanceCountAtCurrLevel;
}

View File

@ -168,24 +168,23 @@ public:
// the parametric sense) line segments.
static void WriteDrawCubicsIndirectCmd(GrDrawIndexedIndirectWriter* indirectWriter,
int resolveLevel, uint32_t instanceCount,
uint32_t baseInstance, const GrCaps& caps) {
uint32_t baseInstance) {
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);
indirectWriter->writeIndexed(indexCount, 3, instanceCount, baseInstance, 0, caps);
indirectWriter->writeIndexed(indexCount, 3, instanceCount, baseInstance, 0);
}
// 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 void WriteDrawTrianglesIndirectCmd(GrDrawIndexedIndirectWriter* indirectWriter,
uint32_t instanceCount, uint32_t baseInstance,
const GrCaps& caps) {
uint32_t instanceCount, uint32_t baseInstance) {
// Indices 0,1,2 have special index values that emit points P0, P1, and P2 respectively.
indirectWriter->writeIndexed(3, 0, instanceCount, baseInstance, 0, caps);
indirectWriter->writeIndexed(3, 0, instanceCount, baseInstance, 0);
}
// Returns the index buffer that should be bound when drawing with this shader.

View File

@ -614,8 +614,6 @@ void GrStrokeIndirectTessellator::prepare(GrMeshDrawOp::Target* target, const Sk
return;
}
const GrCaps& caps = target->caps();
// Allocate enough indirect commands for every resolve level. We will putBack the unused ones
// at the end.
GrDrawIndirectWriter indirectWriter = target->makeDrawIndirectSpace(kMaxResolveLevel + 1,
@ -649,7 +647,7 @@ void GrStrokeIndirectTessellator::prepare(GrMeshDrawOp::Target* target, const Sk
if (fResolveLevelCounts[i]) {
int numEdges = numExtraEdgesInJoin + num_edges_in_resolve_level(i);
indirectWriter.write(fResolveLevelCounts[i], baseInstance + currentInstanceIdx,
numEdges * 2, 0, caps);
numEdges * 2, 0);
++fDrawIndirectCount;
numEdgesPerResolveLevel[i] = numEdges;
instanceWriters[i] = baseWriter.makeOffset(instanceStride * currentInstanceIdx);

View File

@ -355,11 +355,9 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrMeshTest, reporter, ctxInfo) {
if (indexed) {
int baseIndex = 1 + y * 6;
indexedIndirectWriter.writeIndexed(6, baseIndex, kBoxCountX,
y * kBoxCountX, baseVertex,
*dContext->priv().caps());
y * kBoxCountX, baseVertex);
} else {
indirectWriter.write(kBoxCountX, y * kBoxCountX, 4, baseVertex,
*dContext->priv().caps());
indirectWriter.write(kBoxCountX, y * kBoxCountX, 4, baseVertex);
}
}
},

View File

@ -435,17 +435,15 @@ void GrStrokeIndirectTessellator::verifyBuffers(skiatest::Reporter* r, GrMockOpT
GrStrokeTessellateShader::Tolerances tolerances(viewMatrix.getMaxScale(), stroke.getWidth());
float tolerance = test_tolerance(stroke.getJoin());
for (int i = 0; i < fDrawIndirectCount; ++i) {
// TODO: SkASSERT(caps.drawIndirectCmdSignature() == standard);
auto [vertexCount, instanceCount, baseVertex, baseInstance] = *indirect++;
int numExtraEdgesInJoin = (stroke.getJoin() == SkPaint::kMiter_Join) ? 4 : 3;
int numStrokeEdges = vertexCount/2 - numExtraEdgesInJoin;
int numStrokeEdges = indirect->fVertexCount/2 - numExtraEdgesInJoin;
int numSegments = numStrokeEdges - 1;
bool isPow2 = !(numSegments & (numSegments - 1));
REPORTER_ASSERT(r, isPow2);
int resolveLevel = sk_float_nextlog2(numSegments);
REPORTER_ASSERT(r, 1 << resolveLevel == numSegments);
for (unsigned j = 0; j < instanceCount; ++j) {
SkASSERT(fabsf(instance->fNumTotalEdges) == vertexCount/2);
for (unsigned j = 0; j < indirect->fInstanceCount; ++j) {
SkASSERT(fabsf(instance->fNumTotalEdges) == indirect->fVertexCount/2);
const SkPoint* p = instance->fPts;
float numParametricSegments = GrWangsFormula::cubic(
tolerances.fParametricIntolerance, p);
@ -478,5 +476,6 @@ void GrStrokeIndirectTessellator::verifyBuffers(skiatest::Reporter* r, GrMockOpT
}
++instance;
}
++indirect;
}
}