Create indirect index buffer for tessellation during onPrepare

Change-Id: I78d74976fa2252da2a40862c241a99b68d27fb40
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/292259
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2020-05-27 09:43:34 -06:00 committed by Skia Commit-Bot
parent 66cfc1c637
commit 1443c9df58
3 changed files with 37 additions and 5 deletions

View File

@ -34,6 +34,26 @@ static SkPath make_cubic_path() {
// pre-allocated CPU buffers, rather than allocating and mapping GPU buffers. // pre-allocated CPU buffers, rather than allocating and mapping GPU buffers.
class BenchmarkTarget : public GrMeshDrawOp::Target { class BenchmarkTarget : public GrMeshDrawOp::Target {
public: public:
BenchmarkTarget() {
GrMockOptions mockOptions;
mockOptions.fDrawInstancedSupport = true;
mockOptions.fTessellationSupport = true;
mockOptions.fMapBufferFlags = GrCaps::kCanMap_MapFlag;
mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fRenderability =
GrMockOptions::ConfigOptions::Renderability::kMSAA;
mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fTexturable = true;
mockOptions.fIntegerSupport = true;
GrContextOptions ctxOptions;
ctxOptions.fGpuPathRenderers = GpuPathRenderers::kTessellation;
fMockContext = GrContext::MakeMock(&mockOptions, ctxOptions);
}
const GrContext* mockContext() const { return fMockContext.get(); }
const GrCaps& caps() const override { return *fMockContext->priv().caps(); }
GrResourceProvider* resourceProvider() const override {
return fMockContext->priv().resourceProvider();
}
void resetAllocator() { fAllocator.reset(); } void resetAllocator() { fAllocator.reset(); }
SkArenaAlloc* allocator() override { return &fAllocator; } SkArenaAlloc* allocator() override { return &fAllocator; }
void putBackVertices(int vertices, size_t vertexStride) override { /* no-op */ } void putBackVertices(int vertices, size_t vertexStride) override { /* no-op */ }
@ -73,15 +93,14 @@ public:
UNIMPL(const GrAppliedClip* appliedClip() const) UNIMPL(const GrAppliedClip* appliedClip() const)
UNIMPL(GrAppliedClip detachAppliedClip()) UNIMPL(GrAppliedClip detachAppliedClip())
UNIMPL(const GrXferProcessor::DstProxyView& dstProxyView() const) UNIMPL(const GrXferProcessor::DstProxyView& dstProxyView() const)
UNIMPL(GrResourceProvider* resourceProvider() const)
UNIMPL(GrStrikeCache* strikeCache() const) UNIMPL(GrStrikeCache* strikeCache() const)
UNIMPL(GrAtlasManager* atlasManager() const) UNIMPL(GrAtlasManager* atlasManager() const)
UNIMPL(SkTArray<GrSurfaceProxy*, true>* sampledProxyArray()) UNIMPL(SkTArray<GrSurfaceProxy*, true>* sampledProxyArray())
UNIMPL(const GrCaps& caps() const)
UNIMPL(GrDeferredUploadTarget* deferredUploadTarget()) UNIMPL(GrDeferredUploadTarget* deferredUploadTarget())
#undef UNIMPL #undef UNIMPL
private: private:
sk_sp<GrContext> fMockContext;
SkPoint fStaticVertexData[(kNumCubicsInChalkboard + 2) * 8]; SkPoint fStaticVertexData[(kNumCubicsInChalkboard + 2) * 8];
GrDrawIndexedIndirectCommand fStaticDrawIndexedIndirectData[32]; GrDrawIndexedIndirectCommand fStaticDrawIndexedIndirectData[32];
SkSTArenaAlloc<1024 * 1024> fAllocator; SkSTArenaAlloc<1024 * 1024> fAllocator;
@ -110,6 +129,10 @@ public:
private: private:
void onDraw(int loops, SkCanvas*) final { void onDraw(int loops, SkCanvas*) final {
if (!fTarget.mockContext()) {
SkDebugf("ERROR: could not create mock context.");
return;
}
for (int i = 0; i < loops; ++i) { for (int i = 0; i < loops; ++i) {
fOp.fTriangleBuffer.reset(); fOp.fTriangleBuffer.reset();
fOp.fDoStencilTriangleBuffer = false; fOp.fDoStencilTriangleBuffer = false;

View File

@ -275,10 +275,17 @@ void GrTessellatePathOp::prepareIndirectOuterCubics(
void GrTessellatePathOp::prepareIndirectOuterCubicsAndTriangles( void GrTessellatePathOp::prepareIndirectOuterCubicsAndTriangles(
GrMeshDrawOp::Target* target, const GrResolveLevelCounter& resolveLevelCounter, GrMeshDrawOp::Target* target, const GrResolveLevelCounter& resolveLevelCounter,
SkPoint* cubicData, int numTrianglesAtBeginningOfData) { SkPoint* cubicData, int numTrianglesAtBeginningOfData) {
SkASSERT(target->caps().drawInstancedSupport());
SkASSERT(numTrianglesAtBeginningOfData + resolveLevelCounter.totalCubicInstanceCount() > 0); SkASSERT(numTrianglesAtBeginningOfData + resolveLevelCounter.totalCubicInstanceCount() > 0);
SkASSERT(!fStencilCubicsShader); SkASSERT(!fStencilCubicsShader);
SkASSERT(cubicData); SkASSERT(cubicData);
fIndirectIndexBuffer = GrMiddleOutCubicShader::FindOrMakeMiddleOutIndexBuffer(
target->resourceProvider());
if (!fIndirectIndexBuffer) {
return;
}
// Here we treat fCubicBuffer as an instance buffer. It should have been prepared with the base // Here we treat fCubicBuffer as an instance buffer. It should have been prepared with the base
// vertex on an instance boundary in order to accommodate this. // vertex on an instance boundary in order to accommodate this.
SkASSERT(fBaseCubicVertex % 4 == 0); SkASSERT(fBaseCubicVertex % 4 == 0);
@ -378,6 +385,7 @@ void GrTessellatePathOp::prepareIndirectOuterCubicsAndTriangles(
void GrTessellatePathOp::prepareTessellatedOuterCubics(GrMeshDrawOp::Target* target, void GrTessellatePathOp::prepareTessellatedOuterCubics(GrMeshDrawOp::Target* target,
int numCountedCurves) { int numCountedCurves) {
SkASSERT(target->caps().shaderCaps()->tessellationSupport());
SkASSERT(numCountedCurves >= 0); SkASSERT(numCountedCurves >= 0);
SkASSERT(!fCubicBuffer); SkASSERT(!fCubicBuffer);
SkASSERT(!fStencilCubicsShader); SkASSERT(!fStencilCubicsShader);
@ -414,6 +422,7 @@ void GrTessellatePathOp::prepareTessellatedOuterCubics(GrMeshDrawOp::Target* tar
} }
void GrTessellatePathOp::prepareTessellatedCubicWedges(GrMeshDrawOp::Target* target) { void GrTessellatePathOp::prepareTessellatedCubicWedges(GrMeshDrawOp::Target* target) {
SkASSERT(target->caps().shaderCaps()->tessellationSupport());
SkASSERT(!fCubicBuffer); SkASSERT(!fCubicBuffer);
SkASSERT(!fStencilCubicsShader); SkASSERT(!fStencilCubicsShader);
@ -531,9 +540,8 @@ void GrTessellatePathOp::drawStencilPass(GrOpFlushState* flushState) {
fStencilCubicsShader); fStencilCubicsShader);
flushState->bindPipelineAndScissorClip(programInfo, this->bounds()); flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
if (fIndirectDrawBuffer) { if (fIndirectDrawBuffer) {
auto indexBuffer = GrMiddleOutCubicShader::FindOrMakeMiddleOutIndexBuffer( SkASSERT(fIndirectIndexBuffer);
flushState->resourceProvider()); flushState->bindBuffers(fIndirectIndexBuffer.get(), fCubicBuffer.get(), nullptr);
flushState->bindBuffers(indexBuffer.get(), fCubicBuffer.get(), nullptr);
flushState->drawIndexedIndirect(fIndirectDrawBuffer.get(), fIndirectDrawOffset, flushState->drawIndexedIndirect(fIndirectDrawBuffer.get(), fIndirectDrawOffset,
fIndirectDrawCount); fIndirectDrawCount);
} else { } else {

View File

@ -160,6 +160,7 @@ private:
sk_sp<const GrBuffer> fIndirectDrawBuffer; sk_sp<const GrBuffer> fIndirectDrawBuffer;
size_t fIndirectDrawOffset; size_t fIndirectDrawOffset;
int fIndirectDrawCount; int fIndirectDrawCount;
sk_sp<const GrBuffer> fIndirectIndexBuffer;
friend class GrOpMemoryPool; // For ctor. friend class GrOpMemoryPool; // For ctor.