Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 012f849

Browse files
csmartdalton86Skia Commit-Bot
authored andcommitted
Migrate the GPU tessellator to the new bind/draw GrOpsRenderPass API
Change-Id: I4f42a95dad4a5f5221c0150f76e0941873a8726b Reviewed-on: https://skia-review.googlesource.com/c/skia/+/274919 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
1 parent 8c1ae63 commit 012f849

File tree

8 files changed

+111
-77
lines changed

8 files changed

+111
-77
lines changed

src/gpu/GrAppliedClip.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ class GrAppliedHardClip {
2626
GrAppliedHardClip(const GrAppliedHardClip&) = delete;
2727

2828
const GrScissorState& scissorState() const { return fScissorState; }
29+
const SkIRect* scissorRectIfEnabled() const {
30+
return fScissorState.enabled() ? &fScissorState.rect() : nullptr;
31+
}
2932
const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; }
3033
uint32_t stencilStackID() const { return fStencilStackID; }
3134
bool hasStencilClip() const { return SkClipStack::kInvalidGenID != fStencilStackID; }
@@ -81,6 +84,7 @@ class GrAppliedClip {
8184
GrAppliedClip(const GrAppliedClip&) = delete;
8285

8386
const GrScissorState& scissorState() const { return fHardClip.scissorState(); }
87+
const SkIRect* scissorRectIfEnabled() const { return fHardClip.scissorRectIfEnabled(); }
8488
const GrWindowRectsState& windowRectsState() const { return fHardClip.windowRectsState(); }
8589
uint32_t stencilStackID() const { return fHardClip.stencilStackID(); }
8690
bool hasStencilClip() const { return fHardClip.hasStencilClip(); }

src/gpu/GrOpsRenderPass.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ void GrOpsRenderPass::executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler
4242
this->onExecuteDrawable(std::move(drawable));
4343
}
4444

45-
void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) {
45+
void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds,
46+
const SkIRect* optionalScissorRect) {
4647
#ifdef SK_DEBUG
4748
if (programInfo.primProc().hasInstanceAttributes()) {
4849
SkASSERT(this->gpu()->caps()->instanceAttribSupport());
@@ -101,6 +102,11 @@ void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRec
101102
fDrawPipelineStatus = DrawPipelineStatus::kOk;
102103
fXferBarrierType = programInfo.pipeline().xferBarrierType(fRenderTarget->asTexture(),
103104
*this->gpu()->caps());
105+
106+
if (optionalScissorRect) {
107+
SkASSERT(programInfo.pipeline().isScissorTestEnabled());
108+
this->setScissorRect(*optionalScissorRect);
109+
}
104110
}
105111

106112
void GrOpsRenderPass::setScissorRect(const SkIRect& scissor) {
@@ -140,6 +146,14 @@ void GrOpsRenderPass::bindTextures(const GrPrimitiveProcessor& primProc,
140146
SkDEBUGCODE(fTextureBindingStatus = DynamicStateStatus::kConfigured);
141147
}
142148

149+
void GrOpsRenderPass::bindTextures(const GrPrimitiveProcessor& primProc,
150+
const GrSurfaceProxy& singlePrimProcTexture,
151+
const GrPipeline& pipeline) {
152+
SkASSERT(primProc.numTextureSamplers() == 1);
153+
const GrSurfaceProxy* ptr = &singlePrimProcTexture;
154+
this->bindTextures(primProc, &ptr, pipeline);
155+
}
156+
143157
void GrOpsRenderPass::drawMeshes(const GrProgramInfo& programInfo, const GrMesh meshes[],
144158
int meshCount) {
145159
if (programInfo.hasFixedScissor()) {

src/gpu/GrOpsRenderPass.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ class GrOpsRenderPass {
5050
// Signals the end of recording to the GrOpsRenderPass and that it can now be submitted.
5151
virtual void end() = 0;
5252

53-
// Updates the internal pipeline state for drawing with the provided GrProgramInfo.
54-
// Enters an internal "bad" state if the pipeline could not be set.
55-
void bindPipeline(const GrProgramInfo&, const SkRect& drawBounds);
53+
// Updates the internal pipeline state for drawing with the provided GrProgramInfo. If an
54+
// optional scissor rect is provided, then this method calls setScissor for convenience after
55+
// binding the pipeline. Enters an internal "bad" state if the pipeline could not be set.
56+
void bindPipeline(const GrProgramInfo&, const SkRect& drawBounds,
57+
const SkIRect* optionalScissorRect = nullptr);
5658

5759
// The scissor rect is always dynamic state and therefore not stored on GrPipeline. If scissor
5860
// test is enabled on the current pipeline, then the client must call setScissorRect() before
@@ -72,6 +74,11 @@ class GrOpsRenderPass {
7274
void bindTextures(const GrPrimitiveProcessor&, const GrSurfaceProxy* const primProcTextures[],
7375
const GrPipeline&);
7476

77+
// This is a convenience overload for when the primitive processor has exactly one texture. It
78+
// binds one texture for the primitive processor, and any others for FPs on the pipeline.
79+
void bindTextures(const GrPrimitiveProcessor&, const GrSurfaceProxy& singlePrimProcTexture,
80+
const GrPipeline&);
81+
7582
void bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
7683
const GrBuffer* vertexBuffer, GrPrimitiveRestart = GrPrimitiveRestart::kNo);
7784

src/gpu/GrProgramInfo.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,27 @@ void GrProgramInfo::validate(bool flushTime) const {
3535
SkASSERT(fPrimProc->numTextureSamplers());
3636
} else if (this->hasFixedPrimProcTextures()) {
3737
SkASSERT(fPrimProc->numTextureSamplers());
38-
} else {
39-
SkASSERT(!fPrimProc->numTextureSamplers());
38+
// TODO: We will soon remove dynamic state from GrProgramInfo. But while migrating to the new
39+
// bind/draw API on GrOpsRenderPass, some code will not set the dynamic state because it calls
40+
// bindTextures() directly. Once dynamic state (including this validation code) is moved out of
41+
// GrProgramInfo, we can restore this assert.
42+
// } else {
43+
// SkASSERT(!fPrimProc->numTextureSamplers());
4044
}
4145

42-
SkASSERT(!fPipeline->isScissorTestEnabled() || this->hasFixedScissor() ||
43-
this->hasDynamicScissors());
46+
47+
// TODO: We will soon remove dynamic state from GrProgramInfo. But while migrating to the new
48+
// bind/draw API on GrOpsRenderPass, some code will not set the dynamic state because it calls
49+
// setScissorRect() directly. Once dynamic state (including this validation code) is moved out
50+
// of GrProgramInfo, we can restore this assert.
51+
#if 0
52+
SkASSERT((fPipeline->isScissorTestEnabled()) ==
53+
(this->hasFixedScissor() || this->hasDynamicScissors()));
54+
#else
55+
if (!fPipeline->isScissorTestEnabled()) {
56+
SkASSERT(!this->hasFixedScissor() && !this->hasDynamicScissors());
57+
}
58+
#endif
4459

4560
if (this->hasDynamicPrimProcTextures()) {
4661
// Check that, for a given sampler, the properties of the dynamic textures remain

src/gpu/tessellate/GrDrawAtlasPathOp.cpp

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -156,36 +156,32 @@ void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* state) {
156156
void GrDrawAtlasPathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
157157
SkASSERT(fAtlasProxy->isInstantiated());
158158

159+
GrAppliedClip clip = state->detachAppliedClip();
160+
const SkIRect* scissorRectIfEnabled = clip.scissorRectIfEnabled();
161+
159162
GrPipeline::InitArgs initArgs;
160163
if (fEnableHWAA) {
161164
initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias;
162165
}
163166
initArgs.fCaps = &state->caps();
164167
initArgs.fDstProxyView = state->drawOpArgs().dstProxyView();
165168
initArgs.fOutputSwizzle = state->drawOpArgs().outputSwizzle();
166-
167-
GrAppliedClip clip = state->detachAppliedClip();
168-
GrPipeline::FixedDynamicState fixedDynamicState;
169-
if (clip.scissorState().enabled()) {
170-
fixedDynamicState.fScissorRect = clip.scissorState().rect();
171-
}
172-
GrSurfaceProxy* atlasSurfaceProxy = fAtlasProxy.get();
173-
fixedDynamicState.fPrimitiveProcessorTextures = &atlasSurfaceProxy;
174-
175169
GrPipeline pipeline(initArgs, std::move(fProcessors), std::move(clip));
176170

177171
GrSwizzle swizzle = state->caps().getReadSwizzle(fAtlasProxy->backendFormat(),
178172
GrColorType::kAlpha_8);
173+
179174
DrawAtlasPathShader shader(fAtlasProxy.get(), swizzle, fUsesLocalCoords);
180175
SkASSERT(shader.instanceStride() == Instance::Stride(fUsesLocalCoords));
181176

182177
GrProgramInfo programInfo(state->proxy()->numSamples(), state->proxy()->numStencilSamples(),
183178
state->proxy()->backendFormat(), state->outputView()->origin(),
184-
&pipeline, &shader, &fixedDynamicState, nullptr, 0,
179+
&pipeline, &shader, nullptr, nullptr, 0,
185180
GrPrimitiveType::kTriangleStrip);
186181

187-
GrMesh mesh;
188-
mesh.setInstanced(fInstanceBuffer, fInstanceCount, fBaseInstance, 4);
189-
state->opsRenderPass()->bindPipeline(programInfo, this->bounds());
190-
state->opsRenderPass()->drawMeshes(programInfo, &mesh, 1);
182+
GrOpsRenderPass* renderPass = state->opsRenderPass();
183+
renderPass->bindPipeline(programInfo, this->bounds(), scissorRectIfEnabled);
184+
renderPass->bindTextures(shader, *fAtlasProxy, pipeline);
185+
renderPass->bindBuffers(nullptr, fInstanceBuffer.get(), nullptr);
186+
renderPass->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
191187
}

src/gpu/tessellate/GrPathShader.h

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,22 @@ class GrPathShader : public GrGeometryProcessor {
2828
}
2929

3030
const SkMatrix& viewMatrix() const { return fViewMatrix; }
31-
GrPrimitiveType primitiveType() const { return fPrimitiveType; }
32-
int tessellationPatchVertexCount() const { return fTessellationPatchVertexCount; }
33-
34-
void issueDraw(GrOpFlushState* state, const GrPipeline* pipeline,
35-
const GrPipeline::FixedDynamicState* fixedDynamicState,
36-
sk_sp<const GrBuffer> vertexBuffer, int vertexCount, int baseVertex,
37-
const SkRect& bounds) {
38-
GrMesh mesh;
39-
mesh.setNonIndexedNonInstanced(vertexCount);
40-
mesh.setVertexData(std::move(vertexBuffer), baseVertex);
41-
this->issueDraw(state, pipeline, fixedDynamicState, mesh, bounds);
42-
}
4331

44-
void issueDraw(GrOpFlushState* state, const GrPipeline* pipeline,
45-
const GrPipeline::FixedDynamicState* fixedDynamicState, const GrMesh& mesh,
46-
const SkRect& bounds) {
47-
GrProgramInfo programInfo(state->proxy()->numSamples(), state->proxy()->numStencilSamples(),
48-
state->proxy()->backendFormat(), state->outputView()->origin(),
49-
pipeline, this, fixedDynamicState, nullptr, 0,
50-
fPrimitiveType, fTessellationPatchVertexCount);
51-
state->opsRenderPass()->bindPipeline(programInfo, bounds);
52-
state->opsRenderPass()->drawMeshes(programInfo, &mesh, 1);
53-
}
32+
// This subclass is used to simplify the argument list for constructing GrProgramInfo from a
33+
// GrPathShader.
34+
class ProgramInfo : public GrProgramInfo {
35+
public:
36+
ProgramInfo(const GrSurfaceProxyView* view, const GrPipeline* pipeline,
37+
const GrPathShader* shader)
38+
: ProgramInfo(view->asRenderTargetProxy(), view->origin(), pipeline, shader) {
39+
}
40+
ProgramInfo(const GrRenderTargetProxy* proxy, GrSurfaceOrigin origin,
41+
const GrPipeline* pipeline, const GrPathShader* shader)
42+
: GrProgramInfo(proxy->numSamples(), proxy->numStencilSamples(),
43+
proxy->backendFormat(), origin, pipeline, shader, nullptr, nullptr,
44+
0, shader->fPrimitiveType, shader->fTessellationPatchVertexCount) {
45+
}
46+
};
5447

5548
private:
5649
const SkMatrix fViewMatrix;

src/gpu/tessellate/GrTessellatePathOp.cpp

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -91,20 +91,13 @@ void GrTessellatePathOp::onPrepare(GrOpFlushState* state) {
9191

9292
void GrTessellatePathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
9393
GrAppliedClip clip = state->detachAppliedClip();
94-
GrPipeline::FixedDynamicState fixedDynamicState;
95-
if (clip.scissorState().enabled()) {
96-
fixedDynamicState.fScissorRect = clip.scissorState().rect();
97-
}
98-
99-
this->drawStencilPass(state, clip.hardClip(), &fixedDynamicState);
100-
94+
this->drawStencilPass(state, clip.hardClip());
10195
if (!(Flags::kStencilOnly & fFlags)) {
102-
this->drawCoverPass(state, std::move(clip), &fixedDynamicState);
96+
this->drawCoverPass(state, std::move(clip));
10397
}
10498
}
10599

106-
void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state, const GrAppliedHardClip& hardClip,
107-
const GrPipeline::FixedDynamicState* fixedDynamicState) {
100+
void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state, const GrAppliedHardClip& hardClip) {
108101
// Increments clockwise triangles and decrements counterclockwise. Used for "winding" fill.
109102
constexpr static GrUserStencilSettings kIncrDecrStencil(
110103
GrUserStencilSettings::StaticInitSeparate<
@@ -140,19 +133,24 @@ void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state, const GrAppliedH
140133

141134
GrPipeline pipeline(initArgs, GrDisableColorXPFactory::MakeXferProcessor(), hardClip);
142135

136+
GrOpsRenderPass* renderPass = state->opsRenderPass();
137+
143138
if (fStencilPathShader) {
144139
SkASSERT(fPathVertexBuffer);
145-
fStencilPathShader->issueDraw(state, &pipeline, fixedDynamicState, fPathVertexBuffer,
146-
fPathVertexCount, fBasePathVertex, this->bounds());
140+
GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, fStencilPathShader);
141+
renderPass->bindPipeline(programInfo, this->bounds(), hardClip.scissorRectIfEnabled());
142+
renderPass->bindBuffers(nullptr, nullptr, fPathVertexBuffer.get());
143+
renderPass->draw(fPathVertexCount, fBasePathVertex);
147144
}
148145

149146
if (fCubicInstanceBuffer) {
150147
// Here we treat the cubic instance buffer as tessellation patches to stencil the curves.
151-
GrMesh mesh;
152-
mesh.setNonIndexedNonInstanced(fCubicInstanceCount * 4);
153-
mesh.setVertexData(fCubicInstanceBuffer, fBaseCubicInstance * 4);
154-
GrStencilCubicShader(fViewMatrix).issueDraw(
155-
state, &pipeline, fixedDynamicState, mesh, this->bounds());
148+
GrStencilCubicShader shader(fViewMatrix);
149+
GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, &shader);
150+
renderPass->bindPipeline(programInfo, this->bounds(), hardClip.scissorRectIfEnabled());
151+
// Bind instancedBuff as vertex.
152+
renderPass->bindBuffers(nullptr, nullptr, fCubicInstanceBuffer.get());
153+
renderPass->draw(fCubicInstanceCount * 4, fBaseCubicInstance * 4);
156154
}
157155

158156
// http://skbug.com/9739
@@ -161,8 +159,10 @@ void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state, const GrAppliedH
161159
}
162160
}
163161

164-
void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state, GrAppliedClip&& clip,
165-
const GrPipeline::FixedDynamicState* fixedDynamicState) {
162+
void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state, GrAppliedClip&& clip) {
163+
GrOpsRenderPass* renderPass = state->opsRenderPass();
164+
const SkIRect* scissorRectIfEnabled = clip.scissorRectIfEnabled();
165+
166166
// Allows non-zero stencil values to pass and write a color, and resets the stencil value back
167167
// to zero; discards immediately on stencil values of zero.
168168
// NOTE: It's ok to not check the clip here because the previous stencil pass only wrote to
@@ -191,7 +191,6 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state, GrAppliedClip&& cl
191191
initArgs.fCaps = &state->caps();
192192
initArgs.fDstProxyView = state->drawOpArgs().dstProxyView();
193193
initArgs.fOutputSwizzle = state->drawOpArgs().outputSwizzle();
194-
195194
GrPipeline pipeline(initArgs, std::move(fProcessors), std::move(clip));
196195

197196
if (fFillPathShader) {
@@ -237,25 +236,32 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state, GrAppliedClip&& cl
237236
SkASSERT(!pipeline.hasStencilClip());
238237
pipeline.setUserStencil(&kFillOrInvertStencil);
239238
}
240-
fFillPathShader->issueDraw(state, &pipeline, fixedDynamicState, fPathVertexBuffer,
241-
fPathVertexCount, fBasePathVertex, this->bounds());
239+
GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, fFillPathShader);
240+
renderPass->bindPipeline(programInfo, this->bounds(), scissorRectIfEnabled);
241+
renderPass->bindTextures(*fFillPathShader, nullptr, pipeline);
242+
renderPass->bindBuffers(nullptr, nullptr, fPathVertexBuffer.get());
243+
renderPass->draw(fPathVertexCount, fBasePathVertex);
242244

243245
if (fCubicInstanceBuffer) {
244246
// At this point, every pixel is filled in except the ones touched by curves. Issue a
245247
// final cover pass over the curves by drawing their convex hulls. This will fill in any
246248
// remaining samples and reset the stencil buffer.
247-
GrMesh mesh;
248-
mesh.setInstanced(fCubicInstanceBuffer, fCubicInstanceCount, fBaseCubicInstance, 4);
249249
pipeline.setUserStencil(&kTestAndResetStencil);
250-
GrFillCubicHullShader(fViewMatrix, fColor).issueDraw(
251-
state, &pipeline, fixedDynamicState, mesh, this->bounds());
250+
GrFillCubicHullShader shader(fViewMatrix, fColor);
251+
GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, &shader);
252+
renderPass->bindPipeline(programInfo, this->bounds(), scissorRectIfEnabled);
253+
renderPass->bindTextures(shader, nullptr, pipeline);
254+
renderPass->bindBuffers(nullptr, fCubicInstanceBuffer.get(), nullptr);
255+
renderPass->drawInstanced(fCubicInstanceCount, fBaseCubicInstance, 4, 0);
252256
}
253257
} else {
254258
// There is not a fill shader for the path. Just draw a bounding box.
255-
GrMesh mesh;
256-
mesh.setNonIndexedNonInstanced(4);
257259
pipeline.setUserStencil(&kTestAndResetStencil);
258-
GrFillBoundingBoxShader(fViewMatrix, fColor, fPath.getBounds()).issueDraw(
259-
state, &pipeline, fixedDynamicState, mesh, this->bounds());
260+
GrFillBoundingBoxShader shader(fViewMatrix, fColor, fPath.getBounds());
261+
GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, &shader);
262+
renderPass->bindPipeline(programInfo, this->bounds(), scissorRectIfEnabled);
263+
renderPass->bindTextures(shader, nullptr, pipeline);
264+
renderPass->bindBuffers(nullptr, nullptr, nullptr);
265+
renderPass->draw(4, 0);
260266
}
261267
}

src/gpu/tessellate/GrTessellatePathOp.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,8 @@ class GrTessellatePathOp : public GrDrawOp {
5656
void onPrepare(GrOpFlushState* state) override;
5757
void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
5858

59-
void drawStencilPass(GrOpFlushState*, const GrAppliedHardClip&,
60-
const GrPipeline::FixedDynamicState*);
61-
void drawCoverPass(GrOpFlushState*, GrAppliedClip&&, const GrPipeline::FixedDynamicState*);
59+
void drawStencilPass(GrOpFlushState*, const GrAppliedHardClip&);
60+
void drawCoverPass(GrOpFlushState*, GrAppliedClip&&);
6261

6362
const Flags fFlags;
6463
const SkMatrix fViewMatrix;

0 commit comments

Comments
 (0)