[graphite] Encapsulate various RenderStep constructors better Originally when we allowed RendererProvider to pass in the depth/stencil settings to specific RenderStep variations, there was no render step ID and no Flags that also needed to be kept in sync. Now there are too many parameters that have to be adjusted together to match the specific variant. Exposing static factories for the explicitly supported options (vs. arbitrary settings) makes it possible for them to set the ID, flags, and depth/stencil settings directly without leaking the constraints up to RendererProvider. Bug: 500416105 Change-Id: Iee935219b0d5a9f0151b83f5eab78adb8daee874 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1378976 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/graphite/RendererProvider.cpp b/src/gpu/graphite/RendererProvider.cpp index 9a8737b..6075ae8 100644 --- a/src/gpu/graphite/RendererProvider.cpp +++ b/src/gpu/graphite/RendererProvider.cpp
@@ -129,9 +129,7 @@ // CoverageMaskRenderStep because it is used for mask filters even when the path renderer // strategy wouldn't use it to sample an atlas. initFromStep(&fConvexTessellatedWedges, - std::make_unique<TessellateWedgesRenderStep>(layout, - RenderStep::RenderStepID::kTessellateWedges_Convex, - infinitySupport, kDirectDepthLEqualPass, bufferManager), + TessellateWedgesRenderStep::ConvexFill(layout, infinitySupport, bufferManager), DrawTypeFlags::kNonSimpleShape); initFromStep(&fCoverageMask, std::make_unique<CoverageMaskRenderStep>(layout), @@ -169,9 +167,7 @@ std::make_unique<PerEdgeAAQuadRenderStep>(layout, bufferManager), DrawTypeFlags::kPerEdgeAAQuad); initFromStep(&fNonAABoundsFill, - std::make_unique<CoverBoundsRenderStep>(layout, - RenderStep::RenderStepID::kCoverBounds_NonAAFill, - kDirectDepthLEqualPass), + CoverBoundsRenderStep::NonAAInnerFill(layout), DrawTypeFlags::kNonAAFillRect); initFromStep(&fCircularArc, std::make_unique<CircularArcRenderStep>(layout, bufferManager), @@ -202,23 +198,16 @@ initFromStep(&fMesh, std::make_unique<MeshRenderStep>(layout), DrawTypeFlags::kDrawMesh); // The tessellating path renderers that use stencil can share the cover steps. - auto coverFill = std::make_unique<CoverBoundsRenderStep>( - layout, RenderStep::RenderStepID::kCoverBounds_RegularCover, kRegularCoverPass); - auto coverInverse = std::make_unique<CoverBoundsRenderStep>( - layout, RenderStep::RenderStepID::kCoverBounds_InverseCover, kInverseCoverPass); + auto coverFill = CoverBoundsRenderStep::StencilCover(layout, /*inverseFill=*/false); + auto coverInverse = CoverBoundsRenderStep::StencilCover(layout, /*inverseFill=*/true); for (bool evenOdd : {false, true}) { // These steps can be shared by regular and inverse fills auto stencilFan = std::make_unique<MiddleOutFanRenderStep>(layout, evenOdd); auto stencilCurve = std::make_unique<TessellateCurvesRenderStep>( layout, evenOdd, infinitySupport, bufferManager); - auto stencilWedge = - evenOdd ? std::make_unique<TessellateWedgesRenderStep>(layout, - RenderStep::RenderStepID::kTessellateWedges_EvenOdd, - infinitySupport, kEvenOddStencilPass, bufferManager) - : std::make_unique<TessellateWedgesRenderStep>(layout, - RenderStep::RenderStepID::kTessellateWedges_Winding, - infinitySupport, kWindingStencilPass, bufferManager); + auto stencilWedge = TessellateWedgesRenderStep::StencilFill( + layout, evenOdd, infinitySupport, bufferManager); for (bool inverse : {false, true}) { static const char* kTessVariants[4] =
diff --git a/src/gpu/graphite/render/CoverBoundsRenderStep.cpp b/src/gpu/graphite/render/CoverBoundsRenderStep.cpp index 7d5c210..1025981 100644 --- a/src/gpu/graphite/render/CoverBoundsRenderStep.cpp +++ b/src/gpu/graphite/render/CoverBoundsRenderStep.cpp
@@ -23,6 +23,7 @@ #include "src/gpu/graphite/geom/Rect.h" #include "src/gpu/graphite/geom/Shape.h" #include "src/gpu/graphite/geom/Transform.h" +#include "src/gpu/graphite/render/CommonDepthStencilSettings.h" namespace skgpu::graphite { @@ -39,15 +40,28 @@ dsSettings, /*staticAttrs=*/ {}, /*appendAttrs=*/{{{"bounds", VertexAttribType::kFloat4, SkSLType::kFloat4}, - {"depth", VertexAttribType::kFloat, SkSLType::kFloat}, - {"ssboIndex", VertexAttribType::kUInt, SkSLType::kUInt}, - {"mat0", VertexAttribType::kFloat3, SkSLType::kFloat3}, - {"mat1", VertexAttribType::kFloat3, SkSLType::kFloat3}, - {"mat2", VertexAttribType::kFloat3, SkSLType::kFloat3}}}, + {"depth", VertexAttribType::kFloat, SkSLType::kFloat}, + {"ssboIndex", VertexAttribType::kUInt, SkSLType::kUInt}, + {"mat0", VertexAttribType::kFloat3, SkSLType::kFloat3}, + {"mat1", VertexAttribType::kFloat3, SkSLType::kFloat3}, + {"mat2", VertexAttribType::kFloat3, SkSLType::kFloat3}}}, /*storageUniforms=*/{}) {} CoverBoundsRenderStep::~CoverBoundsRenderStep() {} +std::unique_ptr<CoverBoundsRenderStep> CoverBoundsRenderStep::NonAAInnerFill(Layout layout) { + return std::unique_ptr<CoverBoundsRenderStep>(new CoverBoundsRenderStep( + layout, RenderStepID::kCoverBounds_NonAAFill, kDirectDepthLEqualPass)); +} + +std::unique_ptr<CoverBoundsRenderStep> CoverBoundsRenderStep::StencilCover( + Layout layout, bool inverseFill) { + RenderStepID id = inverseFill ? RenderStepID::kCoverBounds_InverseCover + : RenderStepID::kCoverBounds_RegularCover; + DepthStencilSettings dss = inverseFill ? kInverseCoverPass : kRegularCoverPass; + return std::unique_ptr<CoverBoundsRenderStep>(new CoverBoundsRenderStep(layout, id, dss)); +} + std::string CoverBoundsRenderStep::vertexSkSL(const RootNodesInfo&) const { // Returns the body of a vertex function, which must define a float4 devPosition variable and // must write to an already-defined float2 stepLocalCoords variable.
diff --git a/src/gpu/graphite/render/CoverBoundsRenderStep.h b/src/gpu/graphite/render/CoverBoundsRenderStep.h index 0a7489b..20bf8d4 100644 --- a/src/gpu/graphite/render/CoverBoundsRenderStep.h +++ b/src/gpu/graphite/render/CoverBoundsRenderStep.h
@@ -8,21 +8,19 @@ #ifndef skgpu_graphite_render_CoverBoundsRenderStep_DEFINED #define skgpu_graphite_render_CoverBoundsRenderStep_DEFINED -#include "src/core/SkVx.h" #include "src/gpu/graphite/Renderer.h" -#include <string> - namespace skgpu::graphite { class DrawParams; class DrawWriter; class PipelineDataGatherer; -struct DepthStencilSettings; class CoverBoundsRenderStep final : public RenderStep { public: - CoverBoundsRenderStep(Layout, RenderStep::RenderStepID, DepthStencilSettings); + // Three variants of the CoverBoundsRenderStep differ in their depth/stencil settings. + static std::unique_ptr<CoverBoundsRenderStep> StencilCover(Layout, bool inverseFill); + static std::unique_ptr<CoverBoundsRenderStep> NonAAInnerFill(Layout); ~CoverBoundsRenderStep() override; @@ -34,6 +32,7 @@ void writeUniformsAndTextures(const DrawParams&, PipelineDataGatherer*) const override; private: + CoverBoundsRenderStep(Layout, RenderStepID, DepthStencilSettings); }; } // namespace skgpu::graphite
diff --git a/src/gpu/graphite/render/TessellateWedgesRenderStep.cpp b/src/gpu/graphite/render/TessellateWedgesRenderStep.cpp index 88256a2..c6a3ed0 100644 --- a/src/gpu/graphite/render/TessellateWedgesRenderStep.cpp +++ b/src/gpu/graphite/render/TessellateWedgesRenderStep.cpp
@@ -25,6 +25,7 @@ #include "src/gpu/graphite/geom/Geometry.h" #include "src/gpu/graphite/geom/Shape.h" #include "src/gpu/graphite/geom/Transform.h" +#include "src/gpu/graphite/render/CommonDepthStencilSettings.h" #include "src/gpu/graphite/render/DynamicInstancesPatchAllocator.h" #include "src/gpu/tessellate/FixedCountBufferUtils.h" #include "src/gpu/tessellate/MidpointContourParser.h" @@ -86,16 +87,14 @@ TessellateWedgesRenderStep::TessellateWedgesRenderStep(Layout layout, RenderStepID renderStepID, bool infinitySupport, + SkEnumBitMask<Flags> xtraFlags, DepthStencilSettings depthStencilSettings, StaticBufferManager* bufferManager) : RenderStep(layout, renderStepID, Flags::kRequiresMSAA | Flags::kAppendDynamicInstances | Flags::kIgnoreInverseFill - | (renderStepID == RenderStepID::kTessellateWedges_Convex - ? Flags::kPerformsShading - | Flags::kNoSelfIntersections - : Flags::kAllowsSelfIntersection), + | xtraFlags, /*uniforms=*/{{"localToDevice", SkSLType::kFloat4x4}}, PrimitiveType::kTriangles, depthStencilSettings, @@ -124,6 +123,32 @@ TessellateWedgesRenderStep::~TessellateWedgesRenderStep() {} +std::unique_ptr<TessellateWedgesRenderStep> TessellateWedgesRenderStep::StencilFill( + Layout layout, bool evenOdd, bool infinitySupport, StaticBufferManager* bufferManager) { + // For stencil fills, allow self intersections to update the stencil buffer counts appropriately + // The final winding rule will be evaluated by a separate cover step that won't result in + // double blending for its shading pass. + static constexpr SkEnumBitMask<Flags> kStencilFlags = Flags::kAllowsSelfIntersection; + + RenderStepID id = evenOdd ? RenderStepID::kTessellateWedges_EvenOdd + : RenderStepID::kTessellateWedges_Winding; + auto dss = evenOdd ? kEvenOddStencilPass : kWindingStencilPass; + return std::unique_ptr<TessellateWedgesRenderStep>(new TessellateWedgesRenderStep( + layout, id, infinitySupport, kStencilFlags, dss, bufferManager)); +} + +std::unique_ptr<TessellateWedgesRenderStep> TessellateWedgesRenderStep::ConvexFill( + Layout layout, bool infinitySupport, StaticBufferManager* bufferManager) { + // When convex, the render step shades and doesn't use the stencil buffer at all. Since the + // paths are known to be convex, the emitted triangles should not produce self intersections. + static constexpr SkEnumBitMask<Flags> kConvexFlags = + Flags::kPerformsShading | Flags::kNoSelfIntersections; + + return std::unique_ptr<TessellateWedgesRenderStep>(new TessellateWedgesRenderStep( + layout, RenderStepID::kTessellateWedges_Convex, infinitySupport, + kConvexFlags, kDirectDepthLEqualPass, bufferManager)); +} + std::string TessellateWedgesRenderStep::vertexSkSL(const RootNodesInfo&) const { return SkSL::String::printf( "float2 localCoord;\n"
diff --git a/src/gpu/graphite/render/TessellateWedgesRenderStep.h b/src/gpu/graphite/render/TessellateWedgesRenderStep.h index c7669ad..8f86695 100644 --- a/src/gpu/graphite/render/TessellateWedgesRenderStep.h +++ b/src/gpu/graphite/render/TessellateWedgesRenderStep.h
@@ -8,32 +8,28 @@ #ifndef skgpu_graphite_render_TessellateWedgesRenderStep_DEFINED #define skgpu_graphite_render_TessellateWedgesRenderStep_DEFINED -#include "src/core/SkVx.h" #include "src/gpu/graphite/Renderer.h" #include "src/gpu/graphite/ResourceTypes.h" -#include <string> -#include <utility> - namespace skgpu::graphite { class DrawParams; class DrawWriter; class PipelineDataGatherer; class StaticBufferManager; -struct DepthStencilSettings; class TessellateWedgesRenderStep final : public RenderStep { public: - // 'vertexBuffer' and 'indexBuffer' must have been returned by CreateVertexTemplate(), but they - // can be shared by all instances of TessellateWedgesRenderStep. - TessellateWedgesRenderStep(Layout, RenderStepID, bool infinitySupport, DepthStencilSettings, - StaticBufferManager*); + // Three variants of TessellateWedgesRenderStep differ in their depth/stencil settings and + // whether or not they are a stencil pre-pass or a standalone step. + static std::unique_ptr<TessellateWedgesRenderStep> StencilFill( + Layout, bool evenOdd, bool infinitySupport, StaticBufferManager*); + + static std::unique_ptr<TessellateWedgesRenderStep> ConvexFill( + Layout, bool infinitySupport, StaticBufferManager*); ~TessellateWedgesRenderStep() override; - static std::pair<BindBufferInfo, BindBufferInfo> CreateVertexTemplate(StaticBufferManager*); - std::string vertexSkSL(const RootNodesInfo&) const override; void writeVertices(DrawWriter*, StorageContext*, @@ -42,6 +38,10 @@ void writeUniformsAndTextures(const DrawParams&, PipelineDataGatherer*) const override; private: + TessellateWedgesRenderStep(Layout, RenderStepID, bool infinitySupport, + SkEnumBitMask<Flags> xtraFlags, DepthStencilSettings, + StaticBufferManager*); + // Points to the static buffers holding the fixed indexed vertex template for drawing instances. BindBufferInfo fVertexBuffer; BindBufferInfo fIndexBuffer;