xref: /aosp_15_r20/external/skia/src/gpu/graphite/render/TessellateCurvesRenderStep.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2022 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/render/TessellateCurvesRenderStep.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkSpan_impl.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkEnumBitMask.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkPathPriv.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSLTypeShared.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/BufferWriter.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Attribute.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/BufferManager.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/DrawOrder.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/DrawParams.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/DrawTypes.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PipelineData.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/geom/Geometry.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/geom/Shape.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/geom/Transform_graphite.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/render/CommonDepthStencilSettings.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/render/DynamicInstancesPatchAllocator.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/tessellate/FixedCountBufferUtils.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/tessellate/PatchWriter.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/tessellate/Tessellation.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/tessellate/WangsFormula.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLString.h"
35*c8dee2aaSAndroid Build Coastguard Worker 
36*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
37*c8dee2aaSAndroid Build Coastguard Worker #include <string_view>
38*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
41*c8dee2aaSAndroid Build Coastguard Worker 
42*c8dee2aaSAndroid Build Coastguard Worker namespace {
43*c8dee2aaSAndroid Build Coastguard Worker 
44*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu::tess;
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker // No fan point or stroke params, since this is for filled curves (not strokes or wedges)
47*c8dee2aaSAndroid Build Coastguard Worker // No explicit curve type on platforms that support infinity.
48*c8dee2aaSAndroid Build Coastguard Worker // No color or wide color attribs, since it might always be part of the PaintParams
49*c8dee2aaSAndroid Build Coastguard Worker // or we'll add a color-only fast path to RenderStep later.
50*c8dee2aaSAndroid Build Coastguard Worker static constexpr PatchAttribs kAttribs = PatchAttribs::kPaintDepth |
51*c8dee2aaSAndroid Build Coastguard Worker                                          PatchAttribs::kSsboIndex;
52*c8dee2aaSAndroid Build Coastguard Worker static constexpr PatchAttribs kAttribsWithCurveType = kAttribs | PatchAttribs::kExplicitCurveType;
53*c8dee2aaSAndroid Build Coastguard Worker using Writer = PatchWriter<DynamicInstancesPatchAllocator<FixedCountCurves>,
54*c8dee2aaSAndroid Build Coastguard Worker                            Required<PatchAttribs::kPaintDepth>,
55*c8dee2aaSAndroid Build Coastguard Worker                            Required<PatchAttribs::kSsboIndex>,
56*c8dee2aaSAndroid Build Coastguard Worker                            Optional<PatchAttribs::kExplicitCurveType>,
57*c8dee2aaSAndroid Build Coastguard Worker                            AddTrianglesWhenChopping,
58*c8dee2aaSAndroid Build Coastguard Worker                            DiscardFlatCurves>;
59*c8dee2aaSAndroid Build Coastguard Worker 
60*c8dee2aaSAndroid Build Coastguard Worker // The order of the attribute declarations must match the order used by
61*c8dee2aaSAndroid Build Coastguard Worker // PatchWriter::emitPatchAttribs, i.e.:
62*c8dee2aaSAndroid Build Coastguard Worker //     join << fanPoint << stroke << color << depth << curveType << ssboIndices
63*c8dee2aaSAndroid Build Coastguard Worker static constexpr Attribute kBaseAttributes[] = {
64*c8dee2aaSAndroid Build Coastguard Worker         {"p01", VertexAttribType::kFloat4, SkSLType::kFloat4},
65*c8dee2aaSAndroid Build Coastguard Worker         {"p23", VertexAttribType::kFloat4, SkSLType::kFloat4},
66*c8dee2aaSAndroid Build Coastguard Worker         {"depth", VertexAttribType::kFloat, SkSLType::kFloat},
67*c8dee2aaSAndroid Build Coastguard Worker         {"ssboIndices", VertexAttribType::kUInt2, SkSLType::kUInt2}};
68*c8dee2aaSAndroid Build Coastguard Worker 
69*c8dee2aaSAndroid Build Coastguard Worker static constexpr Attribute kAttributesWithCurveType[] = {
70*c8dee2aaSAndroid Build Coastguard Worker         {"p01", VertexAttribType::kFloat4, SkSLType::kFloat4},
71*c8dee2aaSAndroid Build Coastguard Worker         {"p23", VertexAttribType::kFloat4, SkSLType::kFloat4},
72*c8dee2aaSAndroid Build Coastguard Worker         {"depth", VertexAttribType::kFloat, SkSLType::kFloat},
73*c8dee2aaSAndroid Build Coastguard Worker         {"curveType", VertexAttribType::kFloat, SkSLType::kFloat},
74*c8dee2aaSAndroid Build Coastguard Worker         {"ssboIndices", VertexAttribType::kUInt2, SkSLType::kUInt2}};
75*c8dee2aaSAndroid Build Coastguard Worker 
76*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkSpan<const Attribute> kAttributes[2] = {kAttributesWithCurveType,
77*c8dee2aaSAndroid Build Coastguard Worker                                                            kBaseAttributes};
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker }  // namespace
80*c8dee2aaSAndroid Build Coastguard Worker 
TessellateCurvesRenderStep(bool evenOdd,bool infinitySupport,StaticBufferManager * bufferManager)81*c8dee2aaSAndroid Build Coastguard Worker TessellateCurvesRenderStep::TessellateCurvesRenderStep(bool evenOdd,
82*c8dee2aaSAndroid Build Coastguard Worker                                                        bool infinitySupport,
83*c8dee2aaSAndroid Build Coastguard Worker                                                        StaticBufferManager* bufferManager)
84*c8dee2aaSAndroid Build Coastguard Worker         : RenderStep("TessellateCurvesRenderStep",
85*c8dee2aaSAndroid Build Coastguard Worker                      evenOdd ? "even-odd" : "winding",
86*c8dee2aaSAndroid Build Coastguard Worker                      Flags::kRequiresMSAA,
87*c8dee2aaSAndroid Build Coastguard Worker                      /*uniforms=*/{{"localToDevice", SkSLType::kFloat4x4}},
88*c8dee2aaSAndroid Build Coastguard Worker                      PrimitiveType::kTriangles,
89*c8dee2aaSAndroid Build Coastguard Worker                      evenOdd ? kEvenOddStencilPass : kWindingStencilPass,
90*c8dee2aaSAndroid Build Coastguard Worker                      /*vertexAttrs=*/  {{"resolveLevel_and_idx",
91*c8dee2aaSAndroid Build Coastguard Worker                                          VertexAttribType::kFloat2, SkSLType::kFloat2}},
92*c8dee2aaSAndroid Build Coastguard Worker                      /*instanceAttrs=*/kAttributes[infinitySupport])
93*c8dee2aaSAndroid Build Coastguard Worker         , fInfinitySupport(infinitySupport) {
94*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->instanceStride() ==
95*c8dee2aaSAndroid Build Coastguard Worker              PatchStride(infinitySupport ? kAttribs : kAttribsWithCurveType));
96*c8dee2aaSAndroid Build Coastguard Worker 
97*c8dee2aaSAndroid Build Coastguard Worker     // Initialize the static buffers we'll use when recording draw calls.
98*c8dee2aaSAndroid Build Coastguard Worker     // NOTE: Each instance of this RenderStep gets its own copy of the data. If this ends up causing
99*c8dee2aaSAndroid Build Coastguard Worker     // problems, we can modify StaticBufferManager to de-duplicate requests.
100*c8dee2aaSAndroid Build Coastguard Worker     const size_t vertexSize = FixedCountCurves::VertexBufferSize();
101*c8dee2aaSAndroid Build Coastguard Worker     auto vertexData = bufferManager->getVertexWriter(vertexSize, &fVertexBuffer);
102*c8dee2aaSAndroid Build Coastguard Worker     if (vertexData) {
103*c8dee2aaSAndroid Build Coastguard Worker         FixedCountCurves::WriteVertexBuffer(std::move(vertexData), vertexSize);
104*c8dee2aaSAndroid Build Coastguard Worker     } // otherwise static buffer creation failed, so do nothing; Context initialization will fail.
105*c8dee2aaSAndroid Build Coastguard Worker 
106*c8dee2aaSAndroid Build Coastguard Worker     const size_t indexSize = FixedCountCurves::IndexBufferSize();
107*c8dee2aaSAndroid Build Coastguard Worker     auto indexData = bufferManager->getIndexWriter(indexSize, &fIndexBuffer);
108*c8dee2aaSAndroid Build Coastguard Worker     if (indexData) {
109*c8dee2aaSAndroid Build Coastguard Worker         FixedCountCurves::WriteIndexBuffer(std::move(indexData), indexSize);
110*c8dee2aaSAndroid Build Coastguard Worker     } // ""
111*c8dee2aaSAndroid Build Coastguard Worker }
112*c8dee2aaSAndroid Build Coastguard Worker 
~TessellateCurvesRenderStep()113*c8dee2aaSAndroid Build Coastguard Worker TessellateCurvesRenderStep::~TessellateCurvesRenderStep() {}
114*c8dee2aaSAndroid Build Coastguard Worker 
vertexSkSL() const115*c8dee2aaSAndroid Build Coastguard Worker std::string TessellateCurvesRenderStep::vertexSkSL() const {
116*c8dee2aaSAndroid Build Coastguard Worker     return SkSL::String::printf(
117*c8dee2aaSAndroid Build Coastguard Worker             R"(
118*c8dee2aaSAndroid Build Coastguard Worker                 // TODO: Approximate perspective scaling to match how PatchWriter is configured (or
119*c8dee2aaSAndroid Build Coastguard Worker                 // provide explicit tessellation level in instance data instead of replicating
120*c8dee2aaSAndroid Build Coastguard Worker                 // work).
121*c8dee2aaSAndroid Build Coastguard Worker                 float2x2 vectorXform = float2x2(localToDevice[0].xy, localToDevice[1].xy);
122*c8dee2aaSAndroid Build Coastguard Worker                 float2 localCoord = tessellate_filled_curve(
123*c8dee2aaSAndroid Build Coastguard Worker                         vectorXform, resolveLevel_and_idx.x, resolveLevel_and_idx.y, p01, p23, %s);
124*c8dee2aaSAndroid Build Coastguard Worker                 float4 devPosition = localToDevice * float4(localCoord, 0.0, 1.0);
125*c8dee2aaSAndroid Build Coastguard Worker                 devPosition.z = depth;
126*c8dee2aaSAndroid Build Coastguard Worker                 stepLocalCoords = localCoord;
127*c8dee2aaSAndroid Build Coastguard Worker             )",
128*c8dee2aaSAndroid Build Coastguard Worker             fInfinitySupport ? "curve_type_using_inf_support(p23)" : "curveType");
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker 
writeVertices(DrawWriter * dw,const DrawParams & params,skvx::uint2 ssboIndices) const131*c8dee2aaSAndroid Build Coastguard Worker void TessellateCurvesRenderStep::writeVertices(DrawWriter* dw,
132*c8dee2aaSAndroid Build Coastguard Worker                                                const DrawParams& params,
133*c8dee2aaSAndroid Build Coastguard Worker                                                skvx::uint2 ssboIndices) const {
134*c8dee2aaSAndroid Build Coastguard Worker     SkPath path = params.geometry().shape().asPath(); // TODO: Iterate the Shape directly
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker     int patchReserveCount = FixedCountCurves::PreallocCount(path.countVerbs());
137*c8dee2aaSAndroid Build Coastguard Worker     Writer writer{fInfinitySupport ? kAttribs : kAttribsWithCurveType,
138*c8dee2aaSAndroid Build Coastguard Worker                   *dw,
139*c8dee2aaSAndroid Build Coastguard Worker                   fVertexBuffer,
140*c8dee2aaSAndroid Build Coastguard Worker                   fIndexBuffer,
141*c8dee2aaSAndroid Build Coastguard Worker                   patchReserveCount};
142*c8dee2aaSAndroid Build Coastguard Worker     writer.updatePaintDepthAttrib(params.order().depthAsFloat());
143*c8dee2aaSAndroid Build Coastguard Worker     writer.updateSsboIndexAttrib(ssboIndices);
144*c8dee2aaSAndroid Build Coastguard Worker 
145*c8dee2aaSAndroid Build Coastguard Worker     // The vector xform approximates how the control points are transformed by the shader to
146*c8dee2aaSAndroid Build Coastguard Worker     // more accurately compute how many *parametric* segments are needed.
147*c8dee2aaSAndroid Build Coastguard Worker     // TODO: This doesn't account for perspective division yet, which will require updating the
148*c8dee2aaSAndroid Build Coastguard Worker     // approximate transform based on each verb's control points' bounding box.
149*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(params.transform().type() < Transform::Type::kPerspective);
150*c8dee2aaSAndroid Build Coastguard Worker     writer.setShaderTransform(wangs_formula::VectorXform{params.transform().matrix()},
151*c8dee2aaSAndroid Build Coastguard Worker                               params.transform().maxScaleFactor());
152*c8dee2aaSAndroid Build Coastguard Worker 
153*c8dee2aaSAndroid Build Coastguard Worker     // TODO: For filled curves, the path verb loop is simple enough that it's not too big a deal
154*c8dee2aaSAndroid Build Coastguard Worker     // to copy the logic from PathCurveTessellator::write_patches. It may be required if we end
155*c8dee2aaSAndroid Build Coastguard Worker     // up switching to a shape iterator in graphite vs. a path iterator in ganesh, or if
156*c8dee2aaSAndroid Build Coastguard Worker     // graphite does not control point transformation on the CPU. On the  other hand, if we
157*c8dee2aaSAndroid Build Coastguard Worker     // provide a templated WritePatches function, the iterator could also be a template arg in
158*c8dee2aaSAndroid Build Coastguard Worker     // addition to PatchWriter's traits. Whatever pattern we choose will be based more on what's
159*c8dee2aaSAndroid Build Coastguard Worker     // best for the wedge and stroke case, which have more complex loops.
160*c8dee2aaSAndroid Build Coastguard Worker     for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
161*c8dee2aaSAndroid Build Coastguard Worker         switch (verb) {
162*c8dee2aaSAndroid Build Coastguard Worker             case SkPathVerb::kQuad:  writer.writeQuadratic(pts); break;
163*c8dee2aaSAndroid Build Coastguard Worker             case SkPathVerb::kConic: writer.writeConic(pts, *w); break;
164*c8dee2aaSAndroid Build Coastguard Worker             case SkPathVerb::kCubic: writer.writeCubic(pts);     break;
165*c8dee2aaSAndroid Build Coastguard Worker             default:                                             break;
166*c8dee2aaSAndroid Build Coastguard Worker         }
167*c8dee2aaSAndroid Build Coastguard Worker     }
168*c8dee2aaSAndroid Build Coastguard Worker }
169*c8dee2aaSAndroid Build Coastguard Worker 
writeUniformsAndTextures(const DrawParams & params,PipelineDataGatherer * gatherer) const170*c8dee2aaSAndroid Build Coastguard Worker void TessellateCurvesRenderStep::writeUniformsAndTextures(const DrawParams& params,
171*c8dee2aaSAndroid Build Coastguard Worker                                                           PipelineDataGatherer* gatherer) const {
172*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, this->uniforms());)
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker     gatherer->write(params.transform().matrix());
175*c8dee2aaSAndroid Build Coastguard Worker }
176*c8dee2aaSAndroid Build Coastguard Worker 
177*c8dee2aaSAndroid Build Coastguard Worker }  // namespace skgpu::graphite
178