Flutter Engine
The Flutter Engine
TessellateWedgesRenderStep.cpp
Go to the documentation of this file.
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
9
10#include "src/sksl/SkSLString.h"
11
17
21
22namespace skgpu::graphite {
23
24namespace {
25
26using namespace skgpu::tess;
27
28// Only kFanPoint, no stroke params, since this is for filled wedges.
29// No color or wide color attribs, since it might always be part of the PaintParams
30// or we'll add a color-only fast path to RenderStep later.
31// No explicit curve type on platforms that support infinity.
32static constexpr PatchAttribs kAttribs = PatchAttribs::kFanPoint |
33 PatchAttribs::kPaintDepth |
34 PatchAttribs::kSsboIndex;
35static constexpr PatchAttribs kAttribsWithCurveType = kAttribs | PatchAttribs::kExplicitCurveType;
36
42
43// The order of the attribute declarations must match the order used by
44// PatchWriter::emitPatchAttribs, i.e.:
45// join << fanPoint << stroke << color << depth << curveType << ssboIndices
46static constexpr Attribute kBaseAttributes[] = {
52
53static constexpr Attribute kAttributesWithCurveType[] = {
60
61static constexpr SkSpan<const Attribute> kAttributes[2] = {kAttributesWithCurveType,
62 kBaseAttributes};
63
64} // namespace
65
67 bool infinitySupport,
68 DepthStencilSettings depthStencilSettings,
69 StaticBufferManager* bufferManager)
70 : RenderStep("TessellateWedgesRenderStep",
71 variantName,
72 Flags::kRequiresMSAA |
73 (depthStencilSettings.fDepthWriteEnabled ? Flags::kPerformsShading
74 : Flags::kNone),
75 /*uniforms=*/{{"localToDevice", SkSLType::kFloat4x4}},
77 depthStencilSettings,
78 /*vertexAttrs=*/ {{"resolveLevel_and_idx",
80 /*instanceAttrs=*/kAttributes[infinitySupport])
81 , fInfinitySupport(infinitySupport) {
82 SkASSERT(this->instanceStride() ==
83 PatchStride(infinitySupport ? kAttribs : kAttribsWithCurveType));
84
85 // Initialize the static buffers we'll use when recording draw calls.
86 // NOTE: Each instance of this RenderStep gets its own copy of the data. If this ends up causing
87 // problems, we can modify StaticBufferManager to de-duplicate requests.
88 const size_t vertexSize = FixedCountWedges::VertexBufferSize();
89 auto vertexData = bufferManager->getVertexWriter(vertexSize, &fVertexBuffer);
90 if (vertexData) {
91 FixedCountWedges::WriteVertexBuffer(std::move(vertexData), vertexSize);
92 } // otherwise static buffer creation failed, so do nothing; Context initialization will fail.
93
94 const size_t indexSize = FixedCountWedges::IndexBufferSize();
95 auto indexData = bufferManager->getIndexWriter(indexSize, &fIndexBuffer);
96 if (indexData) {
97 FixedCountWedges::WriteIndexBuffer(std::move(indexData), indexSize);
98 } // otherwise static buffer creation failed, so do nothing; Context initialization will fail.
99}
100
102
105 R"(
106 float2 localCoord;
107 if (resolveLevel_and_idx.x < 0) {
108 // A negative resolve level means this is the fan point.
109 localCoord = fanPointAttrib;
110 } else {
111 // TODO: Approximate perspective scaling to match how PatchWriter is configured
112 // (or provide explicit tessellation level in instance data instead of
113 // replicating work)
114 float2x2 vectorXform = float2x2(localToDevice[0].xy, localToDevice[1].xy);
115 localCoord = tessellate_filled_curve(
116 vectorXform, resolveLevel_and_idx.x, resolveLevel_and_idx.y, p01, p23, %s);
117 }
118 float4 devPosition = localToDevice * float4(localCoord, 0.0, 1.0);
119 devPosition.z = depth;
120 stepLocalCoords = localCoord;
121 )",
122 fInfinitySupport ? "curve_type_using_inf_support(p23)" : "curveType");
123}
124
126 const DrawParams& params,
127 skvx::ushort2 ssboIndices) const {
128 SkPath path = params.geometry().shape().asPath(); // TODO: Iterate the Shape directly
129
130 int patchReserveCount = FixedCountWedges::PreallocCount(path.countVerbs());
131 Writer writer{fInfinitySupport ? kAttribs : kAttribsWithCurveType,
132 *dw,
133 fVertexBuffer,
134 fIndexBuffer,
135 patchReserveCount};
136 writer.updatePaintDepthAttrib(params.order().depthAsFloat());
137 writer.updateSsboIndexAttrib(ssboIndices);
138
139 // The vector xform approximates how the control points are transformed by the shader to
140 // more accurately compute how many *parametric* segments are needed.
141 // TODO: This doesn't account for perspective division yet, which will require updating the
142 // approximate transform based on each verb's control points' bounding box.
143 SkASSERT(params.transform().type() < Transform::Type::kPerspective);
144 writer.setShaderTransform(wangs_formula::VectorXform{params.transform().matrix()},
145 params.transform().maxScaleFactor());
146
147 // TODO: Essentially the same as PathWedgeTessellator::write_patches but with a different
148 // PatchWriter template.
149 // For wedges, we iterate over each contour explicitly, using a fan point position that is in
150 // the midpoint of the current contour.
152 while (parser.parseNextContour()) {
153 writer.updateFanPointAttrib(parser.currentMidpoint());
154 SkPoint lastPoint = {0, 0};
155 SkPoint startPoint = {0, 0};
156 for (auto [verb, pts, w] : parser.currentContour()) {
157 switch (verb) {
159 startPoint = lastPoint = pts[0];
160 break;
162 // Unlike curve tessellation, wedges have to handle lines as part of the patch,
163 // effectively forming a single triangle with the fan point.
164 writer.writeLine(pts[0], pts[1]);
165 lastPoint = pts[1];
166 break;
168 writer.writeQuadratic(pts);
169 lastPoint = pts[2];
170 break;
172 writer.writeConic(pts, *w);
173 lastPoint = pts[2];
174 break;
176 writer.writeCubic(pts);
177 lastPoint = pts[3];
178 break;
179 default: break;
180 }
181 }
182
183 // Explicitly close the contour with another line segment, which also differs from curve
184 // tessellation since that approach's triangle step automatically closes the contour.
185 if (lastPoint != startPoint) {
186 writer.writeLine(lastPoint, startPoint);
187 }
188 }
189}
190
192 PipelineDataGatherer* gatherer) const {
193 SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, this->uniforms());)
194
195 gatherer->write(params.transform().matrix());
196}
197
198} // namespace skgpu::graphite
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
Definition: SkPath.h:59
size_t instanceStride() const
Definition: Renderer.h:128
SkSpan< const Uniform > uniforms() const
Definition: Renderer.h:143
void writeVertices(DrawWriter *, const DrawParams &, skvx::ushort2 ssboIndices) const override
void writeUniformsAndTextures(const DrawParams &, PipelineDataGatherer *) const override
TessellateWedgesRenderStep(std::string_view variantName, bool infinitySupport, DepthStencilSettings depthStencilSettings, StaticBufferManager *bufferManager)
static constexpr size_t IndexBufferSize()
static constexpr int PreallocCount(int totalCombinedPathVerbCnt)
static constexpr size_t VertexBufferSize()
static void WriteVertexBuffer(VertexWriter, size_t bufferSize)
static void WriteIndexBuffer(VertexWriter, size_t bufferSize)
const EmbeddedViewParams * params
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: SkSLString.cpp:83
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
static const std::map< std::string, VerticesBuilder::AttributeType > kAttributes
constexpr size_t PatchStride(PatchAttribs attribs)
Definition: Tessellation.h:114
parser
Definition: zip.py:78
SkScalar w
Definition: SkVx.h:83