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