diff options
57 files changed, 321 insertions, 197 deletions
diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp index 26da791746..9f3bcd74ec 100644 --- a/gm/beziereffects.cpp +++ b/gm/beziereffects.cpp @@ -50,7 +50,7 @@ protected: this->setBounds(rect, HasAABloat::kYes, IsZeroArea::kNo); } - const GrPipeline* makePipeline(Target* target) { + Target::PipelineAndFixedDynamicState makePipeline(Target* target) { return target->makePipeline(0, std::move(fProcessorSet), target->detachAppliedClip()); } @@ -100,7 +100,8 @@ private: } SkRect rect = this->rect(); SkPointPriv::SetRectTriStrip(pts, rect, sizeof(SkPoint)); - helper.recordDraw(target, this->gp(), this->makePipeline(target)); + auto pipe = this->makePipeline(target); + helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState); } static constexpr int kVertsPerCubic = 4; @@ -296,7 +297,8 @@ private: SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f}; fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1); } - helper.recordDraw(target, this->gp(), this->makePipeline(target)); + auto pipe = this->makePipeline(target); + helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState); } SkMatrix fKLM; @@ -513,7 +515,8 @@ private: SkRect rect = this->rect(); SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex)); fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts); - helper.recordDraw(target, this->gp(), this->makePipeline(target)); + auto pipe = this->makePipeline(target); + helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState); } GrPathUtils::QuadUVMatrix fDevToUV; diff --git a/gm/convexpolyeffect.cpp b/gm/convexpolyeffect.cpp index 496b6b173f..3c825dc78a 100644 --- a/gm/convexpolyeffect.cpp +++ b/gm/convexpolyeffect.cpp @@ -92,9 +92,8 @@ private: SkPointPriv::SetRectTriStrip(verts, fRect, sizeof(SkPoint)); - helper.recordDraw( - target, gp.get(), - target->makePipeline(0, std::move(fProcessors), target->detachAppliedClip())); + auto pipe = target->makePipeline(0, std::move(fProcessors), target->detachAppliedClip()); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* op, const GrCaps& caps) override { return false; } diff --git a/samplecode/SampleCCPRGeometry.cpp b/samplecode/SampleCCPRGeometry.cpp index f2f88bff45..13cc0a0690 100644 --- a/samplecode/SampleCCPRGeometry.cpp +++ b/samplecode/SampleCCPRGeometry.cpp @@ -359,7 +359,7 @@ void CCPRGeometryView::DrawCoverageCountOp::onExecute(GrOpFlushState* state) { if (!mesh.empty()) { SkASSERT(1 == mesh.count()); - proc.draw(state, pipeline, mesh.begin(), nullptr, 1, this->bounds()); + proc.draw(state, pipeline, nullptr, mesh.begin(), 1, this->bounds()); } if (glGpu) { diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp index 617ed75ae7..42e00f355f 100644 --- a/src/gpu/GrGpuCommandBuffer.cpp +++ b/src/gpu/GrGpuCommandBuffer.cpp @@ -26,12 +26,10 @@ void GrGpuRTCommandBuffer::clearStencilClip(const GrFixedClip& clip, bool inside this->onClearStencilClip(clip, insideStencilMask); } -bool GrGpuRTCommandBuffer::draw(const GrPrimitiveProcessor& primProc, - const GrPipeline& pipeline, - const GrMesh meshes[], - const GrPipeline::DynamicState dynamicStates[], - int meshCount, - const SkRect& bounds) { +bool GrGpuRTCommandBuffer::draw(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, + const GrPipeline::DynamicStateArrays* dynamicStateArrays, + const GrMesh meshes[], int meshCount, const SkRect& bounds) { #ifdef SK_DEBUG SkASSERT(!primProc.hasInstanceAttributes() || this->gpu()->caps()->instanceAttribSupport()); for (int i = 0; i < meshCount; ++i) { @@ -41,6 +39,9 @@ bool GrGpuRTCommandBuffer::draw(const GrPrimitiveProcessor& primProc, SkASSERT(primProc.hasInstanceAttributes() == meshes[i].isInstanced()); } #endif + SkASSERT(!pipeline.isScissorEnabled() || fixedDynamicState || + (dynamicStateArrays && dynamicStateArrays->fScissorRects)); + auto resourceProvider = this->gpu()->getContext()->contextPriv().resourceProvider(); if (pipeline.isBad() || !primProc.instantiate(resourceProvider)) { @@ -51,6 +52,7 @@ bool GrGpuRTCommandBuffer::draw(const GrPrimitiveProcessor& primProc, this->gpu()->stats()->incNumFailedDraws(); return false; } - this->onDraw(primProc, pipeline, meshes, dynamicStates, meshCount, bounds); + this->onDraw(primProc, pipeline, fixedDynamicState, dynamicStateArrays, meshes, meshCount, + bounds); return true; } diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h index 4fae620625..fe0edc9619 100644 --- a/src/gpu/GrGpuCommandBuffer.h +++ b/src/gpu/GrGpuCommandBuffer.h @@ -99,8 +99,9 @@ public: // number of vertex attributes is too large). bool draw(const GrPrimitiveProcessor&, const GrPipeline&, + const GrPipeline::FixedDynamicState*, + const GrPipeline::DynamicStateArrays*, const GrMesh[], - const GrPipeline::DynamicState[], int meshCount, const SkRect& bounds); @@ -134,8 +135,9 @@ private: // overridden by backend-specific derived class to perform the draw call. virtual void onDraw(const GrPrimitiveProcessor&, const GrPipeline&, + const GrPipeline::FixedDynamicState*, + const GrPipeline::DynamicStateArrays*, const GrMesh[], - const GrPipeline::DynamicState[], int meshCount, const SkRect& bounds) = 0; diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp index b24e89abb0..d0a8538e93 100644 --- a/src/gpu/GrOpFlushState.cpp +++ b/src/gpu/GrOpFlushState.cpp @@ -44,8 +44,8 @@ void GrOpFlushState::executeDrawsAndUploadsForMeshDrawOp(uint32_t opID, const Sk } SkASSERT(fCurrDraw->fPipeline->proxy() == this->drawOpArgs().fProxy); this->rtCommandBuffer()->draw(*fCurrDraw->fGeometryProcessor, *fCurrDraw->fPipeline, - fMeshes.begin() + fCurrMesh, nullptr, fCurrDraw->fMeshCnt, - opBounds); + fCurrDraw->fFixedDynamicState, fCurrDraw->fDynamicStateArrays, + fMeshes.begin() + fCurrMesh, fCurrDraw->fMeshCnt, opBounds); fCurrMesh += fCurrDraw->fMeshCnt; fTokenTracker->flushToken(); ++fCurrDraw; @@ -105,6 +105,7 @@ GrDeferredUploadToken GrOpFlushState::addASAPUpload(GrDeferredTextureUploadFn&& } void GrOpFlushState::draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, const GrMesh& mesh) { SkASSERT(fOpArgs); SkASSERT(fOpArgs->fOp); @@ -114,7 +115,10 @@ void GrOpFlushState::draw(const GrGeometryProcessor* gp, const GrPipeline* pipel Draw& lastDraw = *fDraws.begin(); // If the last draw shares a geometry processor and pipeline and there are no intervening // uploads, add this mesh to it. - if (lastDraw.fGeometryProcessor == gp && lastDraw.fPipeline == pipeline) { + // Note, we could attempt to convert fixed dynamic states into dynamic state arrays here + // if everything else is equal. Maybe it's better to rely on Ops to do that? + if (lastDraw.fGeometryProcessor == gp && lastDraw.fPipeline == pipeline && + lastDraw.fFixedDynamicState == fixedDynamicState) { if (fInlineUploads.begin() == fInlineUploads.end() || fInlineUploads.tail()->fUploadBeforeToken != fTokenTracker->nextDrawToken()) { ++lastDraw.fMeshCnt; @@ -127,6 +131,8 @@ void GrOpFlushState::draw(const GrGeometryProcessor* gp, const GrPipeline* pipel draw.fGeometryProcessor.reset(gp); draw.fPipeline = pipeline; + draw.fFixedDynamicState = fixedDynamicState; + draw.fDynamicStateArrays = nullptr; draw.fMeshCnt = 1; draw.fOpID = fOpArgs->fOp->uniqueID(); if (firstDraw) { diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h index a6f0c26e5e..28e0f68e6a 100644 --- a/src/gpu/GrOpFlushState.h +++ b/src/gpu/GrOpFlushState.h @@ -74,7 +74,8 @@ public: /** Overrides of GrMeshDrawOp::Target. */ - void draw(const GrGeometryProcessor*, const GrPipeline*, const GrMesh&) final; + void draw(const GrGeometryProcessor*, const GrPipeline*, const GrPipeline::FixedDynamicState*, + const GrMesh&) final; void* makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer**, int* startVertex) final; uint16_t* makeIndexSpace(int indexCount, const GrBuffer**, int* startIndex) final; @@ -120,6 +121,8 @@ private: int fMeshCnt = 0; GrPendingProgramElement<const GrGeometryProcessor> fGeometryProcessor; const GrPipeline* fPipeline; + const GrPipeline::FixedDynamicState* fFixedDynamicState; + const GrPipeline::DynamicStateArrays* fDynamicStateArrays; uint32_t fOpID; }; diff --git a/src/gpu/GrPathRendering.cpp b/src/gpu/GrPathRendering.cpp index 1af220cd24..614d014146 100644 --- a/src/gpu/GrPathRendering.cpp +++ b/src/gpu/GrPathRendering.cpp @@ -51,6 +51,7 @@ void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* pat void GrPathRendering::drawPath(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState& fixedDynamicState, // Cover pass settings in pipeline. const GrStencilSettings& stencilPassSettings, const GrPath* path) { @@ -58,5 +59,5 @@ void GrPathRendering::drawPath(const GrPrimitiveProcessor& primProc, if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) { fGpu->xferBarrier(pipeline.renderTarget(), barrierType); } - this->onDrawPath(primProc, pipeline, stencilPassSettings, path); + this->onDrawPath(primProc, pipeline, fixedDynamicState, stencilPassSettings, path); } diff --git a/src/gpu/GrPathRendering.h b/src/gpu/GrPathRendering.h index ab13674c15..3ae52e9883 100644 --- a/src/gpu/GrPathRendering.h +++ b/src/gpu/GrPathRendering.h @@ -111,6 +111,7 @@ public: void drawPath(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState&, const GrStencilSettings& stencilPassSettings, // Cover pass settings in pipeline. const GrPath* path); @@ -120,6 +121,7 @@ protected: virtual void onStencilPath(const StencilPathArgs&, const GrPath*) = 0; virtual void onDrawPath(const GrPrimitiveProcessor&, const GrPipeline&, + const GrPipeline::FixedDynamicState&, const GrStencilSettings&, const GrPath*) = 0; diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp index a0eceb32af..6608d7c7d2 100644 --- a/src/gpu/GrPipeline.cpp +++ b/src/gpu/GrPipeline.cpp @@ -16,7 +16,8 @@ #include "ops/GrOp.h" -GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors, +GrPipeline::GrPipeline(const InitArgs& args, + GrProcessorSet&& processors, GrAppliedClip&& appliedClip) { SkASSERT(args.fProxy); SkASSERT(processors.isFinalized()); @@ -24,10 +25,13 @@ GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors, fProxy.reset(args.fProxy); fFlags = args.fFlags; - fScissorState = appliedClip.scissorState(); if (appliedClip.hasStencilClip()) { fFlags |= kHasStencilClip_Flag; } + if (appliedClip.scissorState().enabled()) { + fFlags |= kScissorEnabled_Flag; + } + fWindowRectsState = appliedClip.windowRectsState(); if (!args.fUserStencil->isDisabled(fFlags & kHasStencilClip_Flag)) { fFlags |= kStencilEnabled_Flag; @@ -97,7 +101,6 @@ GrXferBarrierType GrPipeline::xferBarrierType(const GrCaps& caps) const { GrPipeline::GrPipeline(GrRenderTargetProxy* proxy, ScissorState scissorState, SkBlendMode blendmode) : fProxy(proxy) - , fScissorState() , fWindowRectsState() , fUserStencilSettings(&GrUserStencilSettings::kUnused) , fFlags() @@ -105,7 +108,7 @@ GrPipeline::GrPipeline(GrRenderTargetProxy* proxy, ScissorState scissorState, Sk , fFragmentProcessors() , fNumColorProcessors(0) { SkASSERT(proxy); - if (ScissorState::kEnabled == scissorState) { - fScissorState.set({0, 0, 0, 0}); // caller will use the DynamicState struct. + if (scissorState) { + fFlags |= kScissorEnabled_Flag; } } diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h index 3ace0f0a1c..f60a6d410b 100644 --- a/src/gpu/GrPipeline.h +++ b/src/gpu/GrPipeline.h @@ -79,16 +79,26 @@ public: }; /** - * Graphics state that can change dynamically without creating a new pipeline. + * Some state can be changed between GrMeshes without changing GrPipelines. This is generally + * less expensive then using multiple pipelines. Such state is called "dynamic state". It can + * be specified in two ways: + * 1) FixedDynamicState - use this to specify state that does not vary between GrMeshes. + * 2) DynamicStateArrays - use this to specify per mesh values for dynamic state. **/ - struct DynamicState { - // Overrides the scissor rectangle (if scissor is enabled in the pipeline). - // TODO: eventually this should be the only way to specify a scissor rectangle, as is the - // case with the simple constructor. + struct FixedDynamicState { + FixedDynamicState(const SkIRect& scissorRect) : fScissorRect(scissorRect) {} SkIRect fScissorRect; }; /** + * Any non-null array overrides the FixedDynamicState on a mesh-by-mesh basis. Arrays must + * have one entry for each GrMesh. + */ + struct DynamicStateArrays { + const SkIRect* fScissorRects = nullptr; + }; + + /** * Creates a simple pipeline with default settings and no processors. The provided blend mode * must be "Porter Duff" (<= kLastCoeffMode). If using ScissorState::kEnabled, the caller must * specify a scissor rectangle through the DynamicState struct. @@ -169,7 +179,9 @@ public: const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; } - const GrScissorState& getScissorState() const { return fScissorState; } + ScissorState isScissorEnabled() const { + return ScissorState(SkToBool(fFlags & kScissorEnabled_Flag)); + } const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; } @@ -214,7 +226,8 @@ private: enum PrivateFlags { kHasStencilClip_Flag = 0x10, kStencilEnabled_Flag = 0x20, - kIsBad_Flag = 0x40, + kScissorEnabled_Flag = 0x40, + kIsBad_Flag = 0x80, }; using RenderTargetProxy = GrPendingIOResource<GrRenderTargetProxy, kWrite_GrIOType>; @@ -225,7 +238,6 @@ private: SkIPoint fDstTextureOffset; // MDB TODO: do we still need the destination proxy here? RenderTargetProxy fProxy; - GrScissorState fScissorState; GrWindowRectsState fWindowRectsState; const GrUserStencilSettings* fUserStencilSettings; uint16_t fFlags; diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp index 94b027abe9..e9720213ec 100644 --- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp +++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp @@ -224,16 +224,18 @@ void GrCCCoverageProcessor::Shader::emitFragmentCode(const GrCCCoverageProcessor } void GrCCCoverageProcessor::draw(GrOpFlushState* flushState, const GrPipeline& pipeline, - const GrMesh meshes[], - const GrPipeline::DynamicState dynamicStates[], int meshCount, + const SkIRect scissorRects[], const GrMesh meshes[], int meshCount, const SkRect& drawBounds) const { + GrPipeline::DynamicStateArrays dynamicStateArrays; + dynamicStateArrays.fScissorRects = scissorRects; GrGpuRTCommandBuffer* cmdBuff = flushState->rtCommandBuffer(); - cmdBuff->draw(*this, pipeline, meshes, dynamicStates, meshCount, drawBounds); + cmdBuff->draw(*this, pipeline, nullptr, &dynamicStateArrays, meshes, meshCount, drawBounds); // Geometry shader backend draws primitives in two subpasses. if (Impl::kGeometryShader == fImpl) { SkASSERT(GSSubpass::kHulls == fGSSubpass); GrCCCoverageProcessor cornerProc(*this, GSSubpass::kCorners); - cmdBuff->draw(cornerProc, pipeline, meshes, dynamicStates, meshCount, drawBounds); + cmdBuff->draw(cornerProc, pipeline, nullptr, &dynamicStateArrays, meshes, meshCount, + drawBounds); } } diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.h b/src/gpu/ccpr/GrCCCoverageProcessor.h index 89890486d3..e5b6bc1119 100644 --- a/src/gpu/ccpr/GrCCCoverageProcessor.h +++ b/src/gpu/ccpr/GrCCCoverageProcessor.h @@ -105,7 +105,7 @@ public: } } - void draw(GrOpFlushState*, const GrPipeline&, const GrMesh[], const GrPipeline::DynamicState[], + void draw(GrOpFlushState*, const GrPipeline&, const SkIRect scissorRects[], const GrMesh[], int meshCount, const SkRect& drawBounds) const; // The Shader provides code to calculate each pixel's coverage in a RenderPass. It also diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp index db5ea355aa..bbe3df29eb 100644 --- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp +++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp @@ -337,7 +337,9 @@ void GrCCDrawPathsOp::onExecute(GrOpFlushState* flushState) { initArgs.fCaps = &flushState->caps(); initArgs.fResourceProvider = flushState->resourceProvider(); initArgs.fDstProxy = flushState->drawOpArgs().fDstProxy; - GrPipeline pipeline(initArgs, std::move(fProcessors), flushState->detachAppliedClip()); + auto clip = flushState->detachAppliedClip(); + GrPipeline::FixedDynamicState fixedDynamicState(clip.scissorState().rect()); + GrPipeline pipeline(initArgs, std::move(fProcessors), std::move(clip)); int baseInstance = fBaseInstance; SkASSERT(baseInstance >= 0); // Make sure setupResources() has been called. @@ -347,8 +349,8 @@ void GrCCDrawPathsOp::onExecute(GrOpFlushState* flushState) { GrCCPathProcessor pathProc(flushState->resourceProvider(), sk_ref_sp(range.fAtlasProxy), fViewMatrixIfUsingLocalCoords); - pathProc.drawPaths(flushState, pipeline, *resources, baseInstance, range.fEndInstanceIdx, - this->bounds()); + pathProc.drawPaths(flushState, pipeline, &fixedDynamicState, *resources, baseInstance, + range.fEndInstanceIdx, this->bounds()); baseInstance = range.fEndInstanceIdx; } diff --git a/src/gpu/ccpr/GrCCPathParser.cpp b/src/gpu/ccpr/GrCCPathParser.cpp index 6f9b2240d7..1935385eeb 100644 --- a/src/gpu/ccpr/GrCCPathParser.cpp +++ b/src/gpu/ccpr/GrCCPathParser.cpp @@ -517,7 +517,7 @@ bool GrCCPathParser::finalize(GrOnFlushResourceProvider* onFlushRP) { SkASSERT(instanceIndices[1].fConics == quadEndIdx); fMeshesScratchBuffer.reserve(fMaxMeshesPerDraw); - fDynamicStatesScratchBuffer.reserve(fMaxMeshesPerDraw); + fScissorRectScratchBuffer.reserve(fMaxMeshesPerDraw); return true; } @@ -564,11 +564,11 @@ void GrCCPathParser::drawPrimitives(GrOpFlushState* flushState, const GrPipeline GrCCCoverageProcessor::PrimitiveType primitiveType, int PrimitiveTallies::*instanceType, const SkIRect& drawBounds) const { - SkASSERT(pipeline.getScissorState().enabled()); + SkASSERT(pipeline.isScissorEnabled()); // Don't call reset(), as that also resets the reserve count. fMeshesScratchBuffer.pop_back_n(fMeshesScratchBuffer.count()); - fDynamicStatesScratchBuffer.pop_back_n(fDynamicStatesScratchBuffer.count()); + fScissorRectScratchBuffer.pop_back_n(fScissorRectScratchBuffer.count()); GrCCCoverageProcessor proc(flushState->resourceProvider(), primitiveType); @@ -584,8 +584,8 @@ void GrCCPathParser::drawPrimitives(GrOpFlushState* flushState, const GrPipeline int baseInstance = fBaseInstances[(int)ScissorMode::kNonScissored].*instanceType + previousBatch.fEndNonScissorIndices.*instanceType; proc.appendMesh(fInstanceBuffer.get(), instanceCount, baseInstance, &fMeshesScratchBuffer); - fDynamicStatesScratchBuffer.push_back().fScissorRect.setXYWH(0, 0, drawBounds.width(), - drawBounds.height()); + fScissorRectScratchBuffer.push_back().setXYWH(0, 0, drawBounds.width(), + drawBounds.height()); SkDEBUGCODE(totalInstanceCount += instanceCount); } @@ -603,17 +603,17 @@ void GrCCPathParser::drawPrimitives(GrOpFlushState* flushState, const GrPipeline SkASSERT(instanceCount > 0); proc.appendMesh(fInstanceBuffer.get(), instanceCount, baseScissorInstance + startIndex, &fMeshesScratchBuffer); - fDynamicStatesScratchBuffer.push_back().fScissorRect = scissorSubBatch.fScissor; + fScissorRectScratchBuffer.push_back() = scissorSubBatch.fScissor; SkDEBUGCODE(totalInstanceCount += instanceCount); } - SkASSERT(fMeshesScratchBuffer.count() == fDynamicStatesScratchBuffer.count()); + SkASSERT(fMeshesScratchBuffer.count() == fScissorRectScratchBuffer.count()); SkASSERT(fMeshesScratchBuffer.count() <= fMaxMeshesPerDraw); SkASSERT(totalInstanceCount == batch.fTotalPrimitiveCounts.*instanceType); if (!fMeshesScratchBuffer.empty()) { - proc.draw(flushState, pipeline, fMeshesScratchBuffer.begin(), - fDynamicStatesScratchBuffer.begin(), fMeshesScratchBuffer.count(), + proc.draw(flushState, pipeline, fScissorRectScratchBuffer.begin(), + fMeshesScratchBuffer.begin(), fMeshesScratchBuffer.count(), SkRect::Make(drawBounds)); } } diff --git a/src/gpu/ccpr/GrCCPathParser.h b/src/gpu/ccpr/GrCCPathParser.h index 1c09b98024..57b1ce6e97 100644 --- a/src/gpu/ccpr/GrCCPathParser.h +++ b/src/gpu/ccpr/GrCCPathParser.h @@ -157,7 +157,7 @@ private: sk_sp<GrBuffer> fInstanceBuffer; PrimitiveTallies fBaseInstances[kNumScissorModes]; mutable SkSTArray<32, GrMesh> fMeshesScratchBuffer; - mutable SkSTArray<32, GrPipeline::DynamicState> fDynamicStatesScratchBuffer; + mutable SkSTArray<32, SkIRect> fScissorRectScratchBuffer; }; inline void GrCCPathParser::PathStats::statPath(const SkPath& path) { diff --git a/src/gpu/ccpr/GrCCPathProcessor.cpp b/src/gpu/ccpr/GrCCPathProcessor.cpp index e1a508619a..450b74c6a2 100644 --- a/src/gpu/ccpr/GrCCPathProcessor.cpp +++ b/src/gpu/ccpr/GrCCPathProcessor.cpp @@ -130,6 +130,7 @@ GrGLSLPrimitiveProcessor* GrCCPathProcessor::createGLSLInstance(const GrShaderCa } void GrCCPathProcessor::drawPaths(GrOpFlushState* flushState, const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, const GrCCPerFlushResources& resources, int baseInstance, int endInstance, const SkRect& bounds) const { const GrCaps& caps = flushState->caps(); @@ -147,7 +148,8 @@ void GrCCPathProcessor::drawPaths(GrOpFlushState* flushState, const GrPipeline& enablePrimitiveRestart); mesh.setVertexData(resources.vertexBuffer()); - flushState->rtCommandBuffer()->draw(*this, pipeline, &mesh, nullptr, 1, bounds); + flushState->rtCommandBuffer()->draw(*this, pipeline, fixedDynamicState, nullptr, &mesh, 1, + bounds); } void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { diff --git a/src/gpu/ccpr/GrCCPathProcessor.h b/src/gpu/ccpr/GrCCPathProcessor.h index 54c1b7e2ed..878cd1c76d 100644 --- a/src/gpu/ccpr/GrCCPathProcessor.h +++ b/src/gpu/ccpr/GrCCPathProcessor.h @@ -8,16 +8,16 @@ #ifndef GrCCPathProcessor_DEFINED #define GrCCPathProcessor_DEFINED +#include <array> #include "GrCaps.h" #include "GrGeometryProcessor.h" +#include "GrPipeline.h" #include "SkPath.h" -#include <array> class GrCCPathCacheEntry; class GrCCPerFlushResources; class GrOnFlushResourceProvider; class GrOpFlushState; -class GrPipeline; /** * This class draws AA paths using the coverage count masks produced by GrCCCoverageProcessor. @@ -86,8 +86,9 @@ public: void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {} GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; - void drawPaths(GrOpFlushState*, const GrPipeline&, const GrCCPerFlushResources&, - int baseInstance, int endInstance, const SkRect& bounds) const; + void drawPaths(GrOpFlushState*, const GrPipeline&, const GrPipeline::FixedDynamicState*, + const GrCCPerFlushResources&, int baseInstance, int endInstance, + const SkRect& bounds) const; private: const Attribute& onVertexAttribute(int i) const override { return kEdgeNormsAttrib; } diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp index 362ae77d79..dd0bf1b473 100644 --- a/src/gpu/ccpr/GrCCPerFlushResources.cpp +++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp @@ -67,7 +67,7 @@ public: GrPipeline pipeline(flushState->proxy(), GrPipeline::ScissorState::kDisabled, SkBlendMode::kSrc); GrCCPathProcessor pathProc(flushState->resourceProvider(), std::move(fStashedAtlasProxy)); - pathProc.drawPaths(flushState, pipeline, *fResources, fBaseInstance, fEndInstance, + pathProc.drawPaths(flushState, pipeline, nullptr, *fResources, fBaseInstance, fEndInstance, this->bounds()); // Ensure we released the stashed atlas proxy. This allows its underlying texture to be // reused as the current flush's mainline CCPR atlas if needed. diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 97dc3d17ab..6f34912faa 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -1683,7 +1683,9 @@ void GrGLGpu::flushMinSampleShading(float minSampleShading) { } } -bool GrGLGpu::flushGLState(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, +bool GrGLGpu::flushGLState(const GrPrimitiveProcessor& primProc, + const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, bool willDrawPoints) { sk_sp<GrGLProgram> program(fProgramCache->refProgram(this, primProc, pipeline, willDrawPoints)); if (!program) { @@ -1719,7 +1721,13 @@ bool GrGLGpu::flushGLState(const GrPrimitiveProcessor& primProc, const GrPipelin glRT->renderTargetPriv().numStencilBits()); } this->flushStencil(stencil); - this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), pipeline.proxy()->origin()); + if (pipeline.isScissorEnabled()) { + static constexpr SkIRect kBogusScissor{0, 0, 1, 1}; + GrScissorState state(fixedDynamicState ? fixedDynamicState->fScissorRect : kBogusScissor); + this->flushScissor(state, glRT->getViewport(), pipeline.proxy()->origin()); + } else { + this->disableScissor(); + } this->flushWindowRectangles(pipeline.getWindowRectsState(), glRT, pipeline.proxy()->origin()); this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !stencil.isDisabled()); @@ -2250,8 +2258,9 @@ void GrGLGpu::flushViewport(const GrGLIRect& viewport) { void GrGLGpu::draw(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, + const GrPipeline::DynamicStateArrays* dynamicStateArrays, const GrMesh meshes[], - const GrPipeline::DynamicState dynamicStates[], int meshCount) { this->handleDirtyContext(); @@ -2262,21 +2271,21 @@ void GrGLGpu::draw(const GrPrimitiveProcessor& primProc, break; } } - if (!this->flushGLState(primProc, pipeline, hasPoints)) { + if (!this->flushGLState(primProc, pipeline, fixedDynamicState, hasPoints)) { return; } + bool dynamicScissor = + pipeline.isScissorEnabled() && dynamicStateArrays && dynamicStateArrays->fScissorRects; for (int i = 0; i < meshCount; ++i) { if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) { this->xferBarrier(pipeline.renderTarget(), barrierType); } - if (dynamicStates) { - if (pipeline.getScissorState().enabled()) { - GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.renderTarget()); - this->flushScissor(dynamicStates[i].fScissorRect, - glRT->getViewport(), pipeline.proxy()->origin()); - } + if (dynamicScissor) { + GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.renderTarget()); + this->flushScissor(GrScissorState(dynamicStateArrays->fScissorRects[i]), + glRT->getViewport(), pipeline.proxy()->origin()); } if (this->glCaps().requiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines() && GrIsPrimTypeLines(meshes[i].primitiveType()) && diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 782b0b0540..765d5f67ee 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -84,8 +84,9 @@ public: // on GrGLRTGpuCommandBuffer. void draw(const GrPrimitiveProcessor&, const GrPipeline&, + const GrPipeline::FixedDynamicState*, + const GrPipeline::DynamicStateArrays*, const GrMesh[], - const GrPipeline::DynamicState[], int meshCount); // GrMesh::SendToGpuImpl methods. These issue the actual GL draw calls. @@ -253,7 +254,8 @@ private: // Flushes state from GrPipeline to GL. Returns false if the state couldn't be set. // willDrawPoints must be true if point primitives will be rendered after setting the GL state. - bool flushGLState(const GrPrimitiveProcessor&, const GrPipeline&, bool willDrawPoints); + bool flushGLState(const GrPrimitiveProcessor&, const GrPipeline&, + const GrPipeline::FixedDynamicState*, bool willDrawPoints); void flushProgram(sk_sp<GrGLProgram>); diff --git a/src/gpu/gl/GrGLGpuCommandBuffer.h b/src/gpu/gl/GrGLGpuCommandBuffer.h index 84e05a8998..fd3417a79b 100644 --- a/src/gpu/gl/GrGLGpuCommandBuffer.h +++ b/src/gpu/gl/GrGLGpuCommandBuffer.h @@ -86,12 +86,13 @@ private: void onDraw(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, + const GrPipeline::DynamicStateArrays* dynamicStateArrays, const GrMesh mesh[], - const GrPipeline::DynamicState dynamicStates[], int meshCount, const SkRect& bounds) override { SkASSERT(pipeline.renderTarget() == fRenderTarget); - fGpu->draw(primProc, pipeline, mesh, dynamicStates, meshCount); + fGpu->draw(primProc, pipeline, fixedDynamicState, dynamicStateArrays, mesh, meshCount); } void onClear(const GrFixedClip& clip, GrColor color) override { diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp index 79481290f4..85c129f8b0 100644 --- a/src/gpu/gl/GrGLPathRendering.cpp +++ b/src/gpu/gl/GrGLPathRendering.cpp @@ -113,9 +113,10 @@ void GrGLPathRendering::onStencilPath(const StencilPathArgs& args, const GrPath* void GrGLPathRendering::onDrawPath(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState& fixedDynamicState, const GrStencilSettings& stencilPassSettings, const GrPath* path) { - if (!this->gpu()->flushGLState(primProc, pipeline, false)) { + if (!this->gpu()->flushGLState(primProc, pipeline, &fixedDynamicState, false)) { return; } const GrGLPath* glPath = static_cast<const GrGLPath*>(path); diff --git a/src/gpu/gl/GrGLPathRendering.h b/src/gpu/gl/GrGLPathRendering.h index 1dfb756f3e..74c5fcec9c 100644 --- a/src/gpu/gl/GrGLPathRendering.h +++ b/src/gpu/gl/GrGLPathRendering.h @@ -67,6 +67,7 @@ protected: void onStencilPath(const StencilPathArgs&, const GrPath*) override; void onDrawPath(const GrPrimitiveProcessor&, const GrPipeline&, + const GrPipeline::FixedDynamicState&, const GrStencilSettings&, const GrPath*) override; diff --git a/src/gpu/mock/GrMockGpuCommandBuffer.h b/src/gpu/mock/GrMockGpuCommandBuffer.h index 7a94e9a7b4..d3e26fa503 100644 --- a/src/gpu/mock/GrMockGpuCommandBuffer.h +++ b/src/gpu/mock/GrMockGpuCommandBuffer.h @@ -50,8 +50,9 @@ public: void submit() override { fGpu->submitCommandBuffer(this); } private: - void onDraw(const GrPrimitiveProcessor&, const GrPipeline&, const GrMesh[], - const GrPipeline::DynamicState[], int meshCount, const SkRect& bounds) override { + void onDraw(const GrPrimitiveProcessor&, const GrPipeline&, + const GrPipeline::FixedDynamicState*, const GrPipeline::DynamicStateArrays*, + const GrMesh[], int meshCount, const SkRect& bounds) override { ++fNumDraws; } void onClear(const GrFixedClip&, GrColor) override {} diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp index 566eebd827..37cb23bdf8 100644 --- a/src/gpu/ops/GrAAConvexPathRenderer.cpp +++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp @@ -807,7 +807,7 @@ private: GrAAConvexTessellator tess; int instanceCount = fPaths.count(); - const GrPipeline* pipeline = fHelper.makePipeline(target); + auto pipe = fHelper.makePipeline(target); for (int i = 0; i < instanceCount; i++) { tess.rewind(); @@ -843,7 +843,7 @@ private: mesh.setIndexed(indexBuffer, tess.numIndices(), firstIndex, 0, tess.numPts() - 1, GrPrimitiveRestart::kNo); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(gp.get(), pipeline, mesh); + target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } } @@ -854,7 +854,7 @@ private: return; } #endif - const GrPipeline* pipeline = fHelper.makePipeline(target); + auto pipe = fHelper.makePipeline(target); int instanceCount = fPaths.count(); SkMatrix invert; @@ -931,7 +931,7 @@ private: mesh.setIndexed(indexBuffer, draw.fIndexCnt, firstIndex, 0, draw.fVertexCnt - 1, GrPrimitiveRestart::kNo); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(quadProcessor.get(), pipeline, mesh); + target->draw(quadProcessor.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); firstIndex += draw.fIndexCnt; firstVertex += draw.fVertexCnt; } diff --git a/src/gpu/ops/GrAAFillRectOp.cpp b/src/gpu/ops/GrAAFillRectOp.cpp index 76bc8128cf..cbd1ad5c30 100644 --- a/src/gpu/ops/GrAAFillRectOp.cpp +++ b/src/gpu/ops/GrAAFillRectOp.cpp @@ -291,7 +291,8 @@ private: fHelper.compatibleWithAlphaAsCoverage(), localMatrix); info = this->next(info); } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp index 89dedc48a4..af5cb3dbbc 100644 --- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp @@ -939,7 +939,7 @@ void AAHairlineOp::onPrepareDraws(Target* target) { return; } - const GrPipeline* pipeline = fHelper.makePipeline(target); + auto pipe = fHelper.makePipeline(target); // do lines first if (lineCount) { sk_sp<GrGeometryProcessor> lineGP; @@ -977,7 +977,7 @@ void AAHairlineOp::onPrepareDraws(Target* target) { mesh.setIndexedPatterned(linesIndexBuffer.get(), kIdxsPerLineSeg, kLineSegNumVertices, lineCount, kLineSegsNumInIdxBuffer); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(lineGP.get(), pipeline, mesh); + target->draw(lineGP.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } if (quadCount || conicCount) { @@ -1032,7 +1032,7 @@ void AAHairlineOp::onPrepareDraws(Target* target) { mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices, quadCount, kQuadsNumInIdxBuffer); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(quadGP.get(), pipeline, mesh); + target->draw(quadGP.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); firstVertex += quadCount * kQuadNumVertices; } @@ -1041,7 +1041,7 @@ void AAHairlineOp::onPrepareDraws(Target* target) { mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices, conicCount, kQuadsNumInIdxBuffer); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(conicGP.get(), pipeline, mesh); + target->draw(conicGP.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } } } diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp index b6b70779ff..1876d6c531 100644 --- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp +++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp @@ -206,9 +206,9 @@ public: } private: - void draw(GrMeshDrawOp::Target* target, const GrGeometryProcessor* gp, - const GrPipeline* pipeline, int vertexCount, size_t vertexStride, void* vertices, - int indexCount, uint16_t* indices) const { + void draw(Target* target, const GrGeometryProcessor* gp, const GrPipeline* pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, int vertexCount, + size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) const { if (vertexCount == 0 || indexCount == 0) { return; } @@ -234,12 +234,11 @@ private: mesh.setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1, GrPrimitiveRestart::kNo); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(gp, pipeline, mesh); + target->draw(gp, pipeline, fixedDynamicState, mesh); } void onPrepareDraws(Target* target) override { - const GrPipeline* pipeline = fHelper.makePipeline(target); - + auto pipe = fHelper.makePipeline(target); // Setup GrGeometryProcessor sk_sp<GrGeometryProcessor> gp(create_lines_only_gp(fHelper.compatibleWithAlphaAsCoverage(), this->viewMatrix(), @@ -275,8 +274,8 @@ private: if (vertexCount + currentVertices > static_cast<int>(UINT16_MAX)) { // if we added the current instance, we would overflow the indices we can store in a // uint16_t. Draw what we've got so far and reset. - this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, - indexCount, indices); + this->draw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, vertexCount, + vertexStride, vertices, indexCount, indices); vertexCount = 0; indexCount = 0; } @@ -307,8 +306,8 @@ private: indexCount += currentIndices; } if (vertexCount <= SK_MaxS32 && indexCount <= SK_MaxS32) { - this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount, - indices); + this->draw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, vertexCount, + vertexStride, vertices, indexCount, indices); } sk_free(vertices); sk_free(indices); diff --git a/src/gpu/ops/GrAAStrokeRectOp.cpp b/src/gpu/ops/GrAAStrokeRectOp.cpp index 3347227f04..651f839af8 100644 --- a/src/gpu/ops/GrAAStrokeRectOp.cpp +++ b/src/gpu/ops/GrAAStrokeRectOp.cpp @@ -304,7 +304,8 @@ void AAStrokeRectOp::onPrepareDraws(Target* target) { info.fDegenerate, fHelper.compatibleWithAlphaAsCoverage()); } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } sk_sp<const GrBuffer> AAStrokeRectOp::GetIndexBuffer(GrResourceProvider* resourceProvider, diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp index fc5e5804eb..29a5938c62 100644 --- a/src/gpu/ops/GrAtlasTextOp.cpp +++ b/src/gpu/ops/GrAtlasTextOp.cpp @@ -297,9 +297,13 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { } SkASSERT(proxies[0]); - FlushInfo flushInfo; - flushInfo.fPipeline = + auto pipe = target->makePipeline(fSRGBFlags, std::move(fProcessors), target->detachAppliedClip()); + + FlushInfo flushInfo; + flushInfo.fPipeline = pipe.fPipeline; + flushInfo.fFixedDynamicState = pipe.fFixedDynamicState; + bool vmPerspective = fGeoData[0].fViewMatrix.hasPerspective(); if (this->usesDistanceFields()) { flushInfo.fGeometryProcessor = this->setupDfProcessor(proxies, numActiveProxies); @@ -419,7 +423,8 @@ void GrAtlasTextOp::flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) co mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerGlyph, kVerticesPerGlyph, flushInfo->fGlyphsToFlush, maxGlyphsPerDraw); mesh.setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset); - target->draw(flushInfo->fGeometryProcessor.get(), flushInfo->fPipeline, mesh); + target->draw(flushInfo->fGeometryProcessor.get(), flushInfo->fPipeline, + flushInfo->fFixedDynamicState, mesh); flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush; flushInfo->fGlyphsToFlush = 0; } diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h index 0318a90f8f..a1f8f8965f 100644 --- a/src/gpu/ops/GrAtlasTextOp.h +++ b/src/gpu/ops/GrAtlasTextOp.h @@ -109,6 +109,7 @@ private: sk_sp<const GrBuffer> fIndexBuffer; sk_sp<GrGeometryProcessor> fGeometryProcessor; const GrPipeline* fPipeline; + const GrPipeline::FixedDynamicState* fFixedDynamicState; int fGlyphsToFlush; int fVertexOffset; }; diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp index 968d169376..d38bb9f3e6 100644 --- a/src/gpu/ops/GrDashOp.cpp +++ b/src/gpu/ops/GrDashOp.cpp @@ -697,9 +697,9 @@ private: if (fDisableSRGBOutputConversion) { pipelineFlags |= GrPipeline::kDisableOutputConversionToSRGB_Flag; } - const GrPipeline* pipeline = target->makePipeline(pipelineFlags, std::move(fProcessorSet), - target->detachAppliedClip()); - helper.recordDraw(target, gp.get(), pipeline); + auto pipe = target->makePipeline(pipelineFlags, std::move(fProcessorSet), + target->detachAppliedClip()); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp index aa0963b02a..af4546cbb1 100644 --- a/src/gpu/ops/GrDefaultPathRenderer.cpp +++ b/src/gpu/ops/GrDefaultPathRenderer.cpp @@ -63,12 +63,14 @@ namespace { class PathGeoBuilder { public: PathGeoBuilder(GrPrimitiveType primitiveType, GrMeshDrawOp::Target* target, - GrGeometryProcessor* geometryProcessor, const GrPipeline* pipeline) + GrGeometryProcessor* geometryProcessor, const GrPipeline* pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState) : fMesh(primitiveType) , fTarget(target) , fVertexStride(sizeof(SkPoint)) , fGeometryProcessor(geometryProcessor) , fPipeline(pipeline) + , fFixedDynamicState(fixedDynamicState) , fIndexBuffer(nullptr) , fFirstIndex(0) , fIndicesInChunk(0) @@ -274,7 +276,7 @@ private: GrPrimitiveRestart::kNo); } fMesh.setVertexData(fVertexBuffer, fFirstVertex); - fTarget->draw(fGeometryProcessor, fPipeline, fMesh); + fTarget->draw(fGeometryProcessor, fPipeline, fFixedDynamicState, fMesh); } fTarget->putBackIndices((size_t)(fIndicesInChunk - indexCount)); @@ -312,6 +314,7 @@ private: size_t fVertexStride; GrGeometryProcessor* fGeometryProcessor; const GrPipeline* fPipeline; + const GrPipeline::FixedDynamicState* fFixedDynamicState; const GrBuffer* fVertexBuffer; int fFirstVertex; @@ -419,9 +422,9 @@ private: } else { primitiveType = GrPrimitiveType::kTriangles; } - - PathGeoBuilder pathGeoBuilder(primitiveType, target, gp.get(), - fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + PathGeoBuilder pathGeoBuilder(primitiveType, target, gp.get(), pipe.fPipeline, + pipe.fFixedDynamicState); // fill buffers for (int i = 0; i < instanceCount; i++) { diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp index 47bad8b2a4..4c25edc207 100644 --- a/src/gpu/ops/GrDrawAtlasOp.cpp +++ b/src/gpu/ops/GrDrawAtlasOp.cpp @@ -142,7 +142,8 @@ void GrDrawAtlasOp::onPrepareDraws(Target* target) { memcpy(vertPtr, args.fVerts.begin(), allocSize); vertPtr += allocSize; } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool GrDrawAtlasOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { diff --git a/src/gpu/ops/GrDrawPathOp.cpp b/src/gpu/ops/GrDrawPathOp.cpp index 185b3c07f2..98a4775d5a 100644 --- a/src/gpu/ops/GrDrawPathOp.cpp +++ b/src/gpu/ops/GrDrawPathOp.cpp @@ -75,13 +75,16 @@ std::unique_ptr<GrDrawOp> GrDrawPathOp::Make(GrContext* context, } void GrDrawPathOp::onExecute(GrOpFlushState* state) { + GrAppliedClip appliedClip = state->detachAppliedClip(); + GrPipeline::FixedDynamicState fixedDynamicState(appliedClip.scissorState().rect()); GrPipeline pipeline(this->pipelineInitArgs(*state), this->detachProcessors(), - state->detachAppliedClip()); + std::move(appliedClip)); sk_sp<GrPathProcessor> pathProc(GrPathProcessor::Create(this->color(), this->viewMatrix())); GrStencilSettings stencil; init_stencil_pass_settings(*state, this->fillType(), &stencil); - state->gpu()->pathRendering()->drawPath(*pathProc, pipeline, stencil, fPath.get()); + state->gpu()->pathRendering()->drawPath(*pathProc, pipeline, fixedDynamicState, stencil, + fPath.get()); } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp index 8f6ad9745d..ad5aba2b2c 100644 --- a/src/gpu/ops/GrDrawVerticesOp.cpp +++ b/src/gpu/ops/GrDrawVerticesOp.cpp @@ -245,7 +245,8 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) { GrPrimitiveRestart::kNo); } mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(gp.get(), fHelper.makePipeline(target), mesh); + auto pipe = fHelper.makePipeline(target); + target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp index 7bfa72ec94..92bcb0c563 100644 --- a/src/gpu/ops/GrLatticeOp.cpp +++ b/src/gpu/ops/GrLatticeOp.cpp @@ -280,7 +280,8 @@ private: kVertsPerRect * patch.fIter->numRectsToDraw()); } } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp index 0bc782c4a0..349f8327ab 100644 --- a/src/gpu/ops/GrMeshDrawOp.cpp +++ b/src/gpu/ops/GrMeshDrawOp.cpp @@ -40,9 +40,10 @@ void* GrMeshDrawOp::PatternHelper::init(Target* target, size_t vertexStride, return vertices; } -void GrMeshDrawOp::PatternHelper::recordDraw(Target* target, const GrGeometryProcessor* gp, - const GrPipeline* pipeline) { - target->draw(gp, pipeline, fMesh); +void GrMeshDrawOp::PatternHelper::recordDraw( + Target* target, const GrGeometryProcessor* gp, const GrPipeline* pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState) { + target->draw(gp, pipeline, fixedDynamicState, fMesh); } void* GrMeshDrawOp::QuadHelper::init(Target* target, size_t vertexStride, int quadsToDraw) { diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h index cb2c3326f3..ddc29f1dab 100644 --- a/src/gpu/ops/GrMeshDrawOp.h +++ b/src/gpu/ops/GrMeshDrawOp.h @@ -8,6 +8,7 @@ #ifndef GrMeshDrawOp_DEFINED #define GrMeshDrawOp_DEFINED +#include "GrAppliedClip.h" #include "GrDrawOp.h" #include "GrGeometryProcessor.h" #include "GrMesh.h" @@ -40,7 +41,8 @@ protected: int indicesPerRepetition, int repeatCount); /** Call after init() to issue draws to the GrMeshDrawOp::Target.*/ - void recordDraw(Target*, const GrGeometryProcessor*, const GrPipeline*); + void recordDraw(Target*, const GrGeometryProcessor*, const GrPipeline*, + const GrPipeline::FixedDynamicState*); private: GrMesh fMesh; @@ -76,7 +78,8 @@ public: virtual ~Target() {} /** Adds a draw of a mesh. */ - virtual void draw(const GrGeometryProcessor*, const GrPipeline*, const GrMesh&) = 0; + virtual void draw(const GrGeometryProcessor*, const GrPipeline*, + const GrPipeline::FixedDynamicState*, const GrMesh&) = 0; /** * Makes space for vertex data. The returned pointer is the location where vertex data @@ -129,19 +132,35 @@ public: return this->pipelineArena()->make<GrPipeline>(std::forward<Args>(args)...); } + template <typename... Args> + GrPipeline::FixedDynamicState* allocFixedDynamicState(Args&... args) { + return this->pipelineArena()->make<GrPipeline::FixedDynamicState>( + std::forward<Args>(args)...); + } + + // Once we have C++17 structured bindings make this just be a tuple because then we can do: + // auto [pipeline, fixedDynamicState] = target->makePipeline(...); + // in addition to: + // std::tie(flushInfo.fPipeline, flushInfo.fFixedState) = target->makePipeline(...); + struct PipelineAndFixedDynamicState { + const GrPipeline* fPipeline; + const GrPipeline::FixedDynamicState* fFixedDynamicState; + }; + /** * Helper that makes a pipeline targeting the op's render target that incorporates the op's - * GrAppliedClip. + * GrAppliedClip and uses a fixed dynamic state. */ - GrPipeline* makePipeline(uint32_t pipelineFlags, GrProcessorSet&& processorSet, - GrAppliedClip&& clip) { + PipelineAndFixedDynamicState makePipeline(uint32_t pipelineFlags, GrProcessorSet&& processorSet, + GrAppliedClip&& clip) { GrPipeline::InitArgs pipelineArgs; pipelineArgs.fFlags = pipelineFlags; pipelineArgs.fProxy = this->proxy(); pipelineArgs.fDstProxy = this->dstProxy(); pipelineArgs.fCaps = &this->caps(); pipelineArgs.fResourceProvider = this->resourceProvider(); - return this->allocPipeline(pipelineArgs, std::move(processorSet), std::move(clip)); + const auto* state = this->allocFixedDynamicState(clip.scissorState().rect()); + return {this->allocPipeline(pipelineArgs, std::move(processorSet), std::move(clip)), state}; } virtual GrRenderTargetProxy* proxy() const = 0; diff --git a/src/gpu/ops/GrNonAAFillRectOp.cpp b/src/gpu/ops/GrNonAAFillRectOp.cpp index d4ebedc6e1..8af9651a46 100644 --- a/src/gpu/ops/GrNonAAFillRectOp.cpp +++ b/src/gpu/ops/GrNonAAFillRectOp.cpp @@ -203,7 +203,8 @@ private: tesselate(verts, kVertexStride, fRects[i].fColor, &fRects[i].fViewMatrix, fRects[i].fRect, &fRects[i].fLocalQuad); } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { @@ -339,7 +340,8 @@ private: tesselate(verts, vertexStride, info.fColor, nullptr, info.fRect, nullptr); } } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { diff --git a/src/gpu/ops/GrNonAAStrokeRectOp.cpp b/src/gpu/ops/GrNonAAStrokeRectOp.cpp index 11c2f8cda5..4090e3437d 100644 --- a/src/gpu/ops/GrNonAAStrokeRectOp.cpp +++ b/src/gpu/ops/GrNonAAStrokeRectOp.cpp @@ -191,7 +191,8 @@ private: GrMesh mesh(primType); mesh.setNonIndexedNonInstanced(vertexCount); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(gp.get(), fHelper.makePipeline(target), mesh); + auto pipe = fHelper.makePipeline(target); + target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } bool onCombineIfPossible(GrOp* t, const GrCaps&) override { diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp index 1655b76326..ca209e02fe 100644 --- a/src/gpu/ops/GrOvalOpFactory.cpp +++ b/src/gpu/ops/GrOvalOpFactory.cpp @@ -1445,7 +1445,8 @@ private: mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1, GrPrimitiveRestart::kNo); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(gp.get(), fHelper.makePipeline(target), mesh); + auto pipe = fHelper.makePipeline(target); + target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { @@ -1761,7 +1762,8 @@ private: mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1, GrPrimitiveRestart::kNo); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(gp.get(), fHelper.makePipeline(target), mesh); + auto pipe = fHelper.makePipeline(target); + target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { @@ -2005,7 +2007,8 @@ private: verts += kVerticesPerQuad; } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { @@ -2239,7 +2242,8 @@ private: verts += kVerticesPerQuad; } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { @@ -2695,7 +2699,8 @@ private: mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1, GrPrimitiveRestart::kNo); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(gp.get(), fHelper.makePipeline(target), mesh); + auto pipe = fHelper.makePipeline(target); + target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { @@ -2953,7 +2958,8 @@ private: verts++; } } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp index 9a9814e0be..cd51152b8c 100644 --- a/src/gpu/ops/GrRegionOp.cpp +++ b/src/gpu/ops/GrRegionOp.cpp @@ -142,7 +142,8 @@ private: int numRectsInRegion = fRegions[i].fRegion.computeRegionComplexity(); verts += numRectsInRegion * kVertsPerInstance * kVertexStride; } - helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); + auto pipe = fHelper.makePipeline(target); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp index afb084dc36..220556ffdb 100644 --- a/src/gpu/ops/GrShadowRRectOp.cpp +++ b/src/gpu/ops/GrShadowRRectOp.cpp @@ -625,14 +625,14 @@ private: } static const uint32_t kPipelineFlags = 0; - const GrPipeline* pipeline = target->makePipeline( - kPipelineFlags, GrProcessorSet::MakeEmptySet(), target->detachAppliedClip()); + auto pipe = target->makePipeline(kPipelineFlags, GrProcessorSet::MakeEmptySet(), + target->detachAppliedClip()); GrMesh mesh(GrPrimitiveType::kTriangles); mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1, GrPrimitiveRestart::kNo); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(gp.get(), pipeline, mesh); + target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp index 8b83271105..fc54475bb6 100644 --- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp +++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp @@ -134,17 +134,21 @@ GrPipeline::InitArgs GrSimpleMeshDrawOpHelper::pipelineInitArgs( return args; } -GrPipeline* GrSimpleMeshDrawOpHelper::internalMakePipeline(GrMeshDrawOp::Target* target, - const GrPipeline::InitArgs& args) { +auto GrSimpleMeshDrawOpHelper::internalMakePipeline(GrMeshDrawOp::Target* target, + const GrPipeline::InitArgs& args) + -> PipelineAndFixedDynamicState { // A caller really should only call this once as the processor set and applied clip get // moved into the GrPipeline. SkASSERT(!fMadePipeline); SkDEBUGCODE(fMadePipeline = true); + auto clip = target->detachAppliedClip(); + auto* dynamicState = target->allocFixedDynamicState(clip.scissorState().rect()); if (fProcessors) { - return target->allocPipeline(args, std::move(*fProcessors), target->detachAppliedClip()); + return {target->allocPipeline(args, std::move(*fProcessors), std::move(clip)), + dynamicState}; } else { - return target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), - target->detachAppliedClip()); + return {target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), std::move(clip)), + dynamicState}; } } @@ -169,8 +173,8 @@ bool GrSimpleMeshDrawOpHelperWithStencil::isCompatible( fStencilSettings == that.fStencilSettings; } -const GrPipeline* GrSimpleMeshDrawOpHelperWithStencil::makePipeline( - GrMeshDrawOp::Target* target) { +auto GrSimpleMeshDrawOpHelperWithStencil::makePipeline(GrMeshDrawOp::Target* target) + -> PipelineAndFixedDynamicState { auto args = INHERITED::pipelineInitArgs(target); args.fUserStencil = fStencilSettings; return this->internalMakePipeline(target, args); diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h index e5229a713a..cbf41a7128 100644 --- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h +++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h @@ -88,8 +88,9 @@ public: bool compatibleWithAlphaAsCoverage() const { return fCompatibleWithAlphaAsCoveage; } + using PipelineAndFixedDynamicState = GrOpFlushState::PipelineAndFixedDynamicState; /** Makes a pipeline that consumes the processor set and the op's applied clip. */ - GrPipeline* makePipeline(GrMeshDrawOp::Target* target) { + PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target* target) { return this->internalMakePipeline(target, this->pipelineInitArgs(target)); } @@ -117,7 +118,8 @@ protected: GrPipeline::InitArgs pipelineInitArgs(GrMeshDrawOp::Target* target) const; - GrPipeline* internalMakePipeline(GrMeshDrawOp::Target*, const GrPipeline::InitArgs&); + PipelineAndFixedDynamicState internalMakePipeline(GrMeshDrawOp::Target*, + const GrPipeline::InitArgs&); private: GrProcessorSet* fProcessors; @@ -139,6 +141,8 @@ class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper { public: using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs; using Flags = GrSimpleMeshDrawOpHelper::Flags; + using PipelineAndFixedDynamicState = GrOpFlushState::PipelineAndFixedDynamicState; + using GrSimpleMeshDrawOpHelper::visitProxies; // using declarations can't be templated, so this is a pass through function instead. @@ -161,7 +165,7 @@ public: bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps&, const SkRect& thisBounds, const SkRect& thatBounds) const; - const GrPipeline* makePipeline(GrMeshDrawOp::Target*); + PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target*); SkString dumpInfo() const; diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp index a0c9f9cf2b..0cd99d7469 100644 --- a/src/gpu/ops/GrSmallPathRenderer.cpp +++ b/src/gpu/ops/GrSmallPathRenderer.cpp @@ -303,6 +303,7 @@ private: sk_sp<const GrBuffer> fIndexBuffer; sk_sp<GrGeometryProcessor> fGeometryProcessor; const GrPipeline* fPipeline; + const GrPipeline::FixedDynamicState* fFixedDynamicState; int fVertexOffset; int fInstancesToFlush; }; @@ -310,8 +311,12 @@ private: void onPrepareDraws(Target* target) override { int instanceCount = fShapes.count(); + auto pipe = fHelper.makePipeline(target); + FlushInfo flushInfo; - flushInfo.fPipeline = fHelper.makePipeline(target); + flushInfo.fPipeline = pipe.fPipeline; + flushInfo.fFixedDynamicState = pipe.fFixedDynamicState; + // Setup GrGeometryProcessor const SkMatrix& ctm = fShapes[0].fViewMatrix; if (fUsesDistanceField) { @@ -821,7 +826,8 @@ private: kVerticesPerQuad, flushInfo->fInstancesToFlush, maxInstancesPerDraw); mesh.setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset); - target->draw(flushInfo->fGeometryProcessor.get(), flushInfo->fPipeline, mesh); + target->draw(flushInfo->fGeometryProcessor.get(), flushInfo->fPipeline, + flushInfo->fFixedDynamicState, mesh); flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFlush; flushInfo->fInstancesToFlush = 0; } diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp index 4c436c291d..ed59834a87 100644 --- a/src/gpu/ops/GrTessellatingPathRenderer.cpp +++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp @@ -358,7 +358,8 @@ private: GrMesh mesh(TESSELLATOR_WIREFRAME ? GrPrimitiveType::kLines : GrPrimitiveType::kTriangles); mesh.setNonIndexedNonInstanced(count); mesh.setVertexData(vb, firstVertex); - target->draw(gp, fHelper.makePipeline(target), mesh); + auto pipe = fHelper.makePipeline(target); + target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh); } bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; } diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp index a895230241..bced31dbc5 100644 --- a/src/gpu/ops/GrTextureOp.cpp +++ b/src/gpu/ops/GrTextureOp.cpp @@ -793,8 +793,10 @@ __attribute__((no_sanitize("float-cast-overflow"))) args.fFlags |= GrPipeline::kHWAntialias_Flag; } - const GrPipeline* pipeline = target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), - target->detachAppliedClip()); + auto clip = target->detachAppliedClip(); + const auto* fixedDynamicState = target->allocFixedDynamicState(clip.scissorState().rect()); + const auto* pipeline = + target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), std::move(clip)); using TessFn = decltype(&TextureOp::tess<SkPoint, MultiTexture::kNo, Domain::kNo, GrAA::kNo>); #define TESS_FN_AND_VERTEX_SIZE(Point, MT, Domain, AA) \ @@ -866,7 +868,7 @@ __attribute__((no_sanitize("float-cast-overflow"))) mesh.setNonIndexedNonInstanced(4); } mesh.setVertexData(vbuffer, vstart); - target->draw(gp.get(), pipeline, mesh); + target->draw(gp.get(), pipeline, fixedDynamicState, mesh); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp index 95bcb13cbf..91adb5a778 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp +++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp @@ -560,10 +560,12 @@ void GrVkGpuRTCommandBuffer::bindGeometry(const GrBuffer* indexBuffer, } } -GrVkPipelineState* GrVkGpuRTCommandBuffer::prepareDrawState(const GrPrimitiveProcessor& primProc, - const GrPipeline& pipeline, - GrPrimitiveType primitiveType, - bool hasDynamicState) { +GrVkPipelineState* GrVkGpuRTCommandBuffer::prepareDrawState( + const GrPrimitiveProcessor& primProc, + const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, + const GrPipeline::DynamicStateArrays* dynamicStateArrays, + GrPrimitiveType primitiveType) { CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo]; SkASSERT(cbInfo.fRenderPass); @@ -589,14 +591,15 @@ GrVkPipelineState* GrVkGpuRTCommandBuffer::prepareDrawState(const GrPrimitivePro GrRenderTarget* rt = pipeline.renderTarget(); - if (!pipeline.getScissorState().enabled()) { + if (!pipeline.isScissorEnabled()) { GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), rt, pipeline.proxy()->origin(), SkIRect::MakeWH(rt->width(), rt->height())); - } else if (!hasDynamicState) { - GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), - rt, pipeline.proxy()->origin(), - pipeline.getScissorState().rect()); + } else if (!dynamicStateArrays || !dynamicStateArrays->fScissorRects) { + SkASSERT(fixedDynamicState); + GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), rt, + pipeline.proxy()->origin(), + fixedDynamicState->fScissorRect); } GrVkPipeline::SetDynamicViewportState(fGpu, cbInfo.currentCmdBuf(), rt); GrVkPipeline::SetDynamicBlendConstantState(fGpu, cbInfo.currentCmdBuf(), rt->config(), @@ -631,8 +634,9 @@ static void prepare_sampled_images(const GrResourceIOProcessor& processor, void GrVkGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, + const GrPipeline::DynamicStateArrays* dynamicStateArrays, const GrMesh meshes[], - const GrPipeline::DynamicState dynamicStates[], int meshCount, const SkRect& bounds) { SkASSERT(pipeline.renderTarget() == fRenderTarget); @@ -653,12 +657,15 @@ void GrVkGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc, } GrPrimitiveType primitiveType = meshes[0].primitiveType(); - GrVkPipelineState* pipelineState = - this->prepareDrawState(primProc, pipeline, primitiveType, SkToBool(dynamicStates)); + GrVkPipelineState* pipelineState = this->prepareDrawState(primProc, pipeline, fixedDynamicState, + dynamicStateArrays, primitiveType); if (!pipelineState) { return; } + bool dynamicScissor = + pipeline.isScissorEnabled() && dynamicStateArrays && dynamicStateArrays->fScissorRects; + for (int i = 0; i < meshCount; ++i) { const GrMesh& mesh = meshes[i]; if (mesh.primitiveType() != primitiveType) { @@ -668,19 +675,17 @@ void GrVkGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc, pipelineState->freeTempResources(fGpu); SkDEBUGCODE(pipelineState = nullptr); primitiveType = mesh.primitiveType(); - pipelineState = this->prepareDrawState( - primProc, pipeline, primitiveType, SkToBool(dynamicStates)); + pipelineState = this->prepareDrawState(primProc, pipeline, fixedDynamicState, + dynamicStateArrays, primitiveType); if (!pipelineState) { return; } } - if (dynamicStates) { - if (pipeline.getScissorState().enabled()) { - GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), - fRenderTarget, pipeline.proxy()->origin(), - dynamicStates[i].fScissorRect); - } + if (dynamicScissor) { + GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), fRenderTarget, + pipeline.proxy()->origin(), + dynamicStateArrays->fScissorRects[i]); } SkASSERT(pipelineState); diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h index b56d157d25..01b2693ba3 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.h +++ b/src/gpu/vk/GrVkGpuCommandBuffer.h @@ -88,13 +88,15 @@ private: GrVkPipelineState* prepareDrawState(const GrPrimitiveProcessor&, const GrPipeline&, - GrPrimitiveType, - bool hasDynamicState); - - void onDraw(const GrPrimitiveProcessor& primProc, - const GrPipeline& pipeline, - const GrMesh mesh[], - const GrPipeline::DynamicState[], + const GrPipeline::FixedDynamicState*, + const GrPipeline::DynamicStateArrays*, + GrPrimitiveType); + + void onDraw(const GrPrimitiveProcessor&, + const GrPipeline&, + const GrPipeline::FixedDynamicState*, + const GrPipeline::DynamicStateArrays*, + const GrMesh[], int meshCount, const SkRect& bounds) override; diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp index 385cc8b48b..91f42ade37 100644 --- a/src/gpu/vk/GrVkPipeline.cpp +++ b/src/gpu/vk/GrVkPipeline.cpp @@ -441,15 +441,11 @@ static void setup_dynamic_state(VkPipelineDynamicStateCreateInfo* dynamicInfo, dynamicInfo->pDynamicStates = dynamicStates; } -GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, - const GrPrimitiveProcessor& primProc, - const GrPipeline& pipeline, - const GrStencilSettings& stencil, +GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPrimitiveProcessor& primProc, + const GrPipeline& pipeline, const GrStencilSettings& stencil, VkPipelineShaderStageCreateInfo* shaderStageInfo, - int shaderStageCount, - GrPrimitiveType primitiveType, - const GrVkRenderPass& renderPass, - VkPipelineLayout layout, + int shaderStageCount, GrPrimitiveType primitiveType, + const GrVkRenderPass& renderPass, VkPipelineLayout layout, VkPipelineCache cache) { VkPipelineVertexInputStateCreateInfo vertexInputInfo; SkSTArray<2, VkVertexInputBindingDescription, true> bindingDescs; diff --git a/tests/GrMeshTest.cpp b/tests/GrMeshTest.cpp index af6633fce7..aa951c0364 100644 --- a/tests/GrMeshTest.cpp +++ b/tests/GrMeshTest.cpp @@ -394,7 +394,7 @@ void DrawMeshHelper::drawMesh(const GrMesh& mesh) { GrRenderTargetProxy* proxy = fState->drawOpArgs().fProxy; GrPipeline pipeline(proxy, GrPipeline::ScissorState::kDisabled, SkBlendMode::kSrc); GrMeshTestProcessor mtp(mesh.isInstanced(), mesh.hasVertexData()); - fState->rtCommandBuffer()->draw(mtp, pipeline, &mesh, nullptr, 1, + fState->rtCommandBuffer()->draw(mtp, pipeline, nullptr, nullptr, &mesh, 1, SkRect::MakeIWH(kImageWidth, kImageHeight)); } diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp index b8e893be6e..b2aaecc48b 100644 --- a/tests/GrPipelineDynamicStateTest.cpp +++ b/tests/GrPipelineDynamicStateTest.cpp @@ -35,11 +35,11 @@ static constexpr int kNumMeshes = 4; static constexpr int kScreenSplitX = kScreenSize/2; static constexpr int kScreenSplitY = kScreenSize/2; -static const GrPipeline::DynamicState kDynamicStates[kNumMeshes] = { - {SkIRect::MakeLTRB(0, 0, kScreenSplitX, kScreenSplitY)}, - {SkIRect::MakeLTRB(0, kScreenSplitY, kScreenSplitX, kScreenSize)}, - {SkIRect::MakeLTRB(kScreenSplitX, 0, kScreenSize, kScreenSplitY)}, - {SkIRect::MakeLTRB(kScreenSplitX, kScreenSplitY, kScreenSize, kScreenSize)}, +static const SkIRect kDynamicScissors[kNumMeshes] = { + SkIRect::MakeLTRB(0, 0, kScreenSplitX, kScreenSplitY), + SkIRect::MakeLTRB(0, kScreenSplitY, kScreenSplitX, kScreenSize), + SkIRect::MakeLTRB(kScreenSplitX, 0, kScreenSize, kScreenSplitY), + SkIRect::MakeLTRB(kScreenSplitX, kScreenSplitY, kScreenSize, kScreenSize), }; static const GrColor kMeshColors[kNumMeshes] { @@ -148,8 +148,10 @@ private: mesh.setNonIndexedNonInstanced(4); mesh.setVertexData(fVertexBuffer.get(), 4 * i); } - state->rtCommandBuffer()->draw(GrPipelineDynamicStateTestProcessor(), pipeline, - meshes.begin(), kDynamicStates, 4, + GrPipeline::DynamicStateArrays dynamicState; + dynamicState.fScissorRects = kDynamicScissors; + state->rtCommandBuffer()->draw(GrPipelineDynamicStateTestProcessor(), pipeline, nullptr, + &dynamicState, meshes.begin(), 4, SkRect::MakeIWH(kScreenSize, kScreenSize)); } diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp index a8752057c8..c60ae7c7da 100644 --- a/tests/OnFlushCallbackTest.cpp +++ b/tests/OnFlushCallbackTest.cpp @@ -163,7 +163,8 @@ private: mesh.setIndexed(indexBuffer, 6, firstIndex, 0, 3, GrPrimitiveRestart::kNo); mesh.setVertexData(vertexBuffer, firstVertex); - target->draw(gp.get(), fHelper.makePipeline(target), mesh); + auto pipe = fHelper.makePipeline(target); + target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } Helper fHelper; diff --git a/tests/PrimitiveProcessorTest.cpp b/tests/PrimitiveProcessorTest.cpp index 60b2205cf7..e9fbfd101a 100644 --- a/tests/PrimitiveProcessorTest.cpp +++ b/tests/PrimitiveProcessorTest.cpp @@ -111,9 +111,9 @@ private: SkASSERT(vertexStride == gp->debugOnly_vertexStride()); SkPoint* vertices = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1)); SkPointPriv::SetRectTriStrip(vertices, 0.f, 0.f, 1.f, 1.f, vertexStride); - helper.recordDraw(target, gp.get(), - target->makePipeline(0, GrProcessorSet::MakeEmptySet(), - target->detachAppliedClip())); + auto pipe = target->makePipeline(0, GrProcessorSet::MakeEmptySet(), + target->detachAppliedClip()); + helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState); } int fNumAttribs; |