Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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.
151 MidpointContourParser parser{path};
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
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
@ 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.
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
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
constexpr size_t PatchStride(PatchAttribs attribs)
parser
Definition zip.py:78
SkScalar w