Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
TessellateCurvesRenderStep.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
18
21
22namespace skgpu::graphite {
23
24namespace {
25
26using namespace skgpu::tess;
27
28// No fan point or stroke params, since this is for filled curves (not strokes or wedges)
29// No explicit curve type on platforms that support infinity.
30// No color or wide color attribs, since it might always be part of the PaintParams
31// or we'll add a color-only fast path to RenderStep later.
32static constexpr PatchAttribs kAttribs = PatchAttribs::kPaintDepth |
33 PatchAttribs::kSsboIndex;
34static constexpr PatchAttribs kAttribsWithCurveType = kAttribs | PatchAttribs::kExplicitCurveType;
41
42// The order of the attribute declarations must match the order used by
43// PatchWriter::emitPatchAttribs, i.e.:
44// join << fanPoint << stroke << color << depth << curveType << ssboIndices
45static constexpr Attribute kBaseAttributes[] = {
50
51static constexpr Attribute kAttributesWithCurveType[] = {
57
58static constexpr SkSpan<const Attribute> kAttributes[2] = {kAttributesWithCurveType,
59 kBaseAttributes};
60
61} // namespace
62
64 bool infinitySupport,
65 StaticBufferManager* bufferManager)
66 : RenderStep("TessellateCurvesRenderStep",
67 evenOdd ? "even-odd" : "winding",
68 Flags::kRequiresMSAA,
69 /*uniforms=*/{{"localToDevice", SkSLType::kFloat4x4}},
72 /*vertexAttrs=*/ {{"resolveLevel_and_idx",
74 /*instanceAttrs=*/kAttributes[infinitySupport])
75 , fInfinitySupport(infinitySupport) {
76 SkASSERT(this->instanceStride() ==
77 PatchStride(infinitySupport ? kAttribs : kAttribsWithCurveType));
78
79 // Initialize the static buffers we'll use when recording draw calls.
80 // NOTE: Each instance of this RenderStep gets its own copy of the data. If this ends up causing
81 // problems, we can modify StaticBufferManager to de-duplicate requests.
82 const size_t vertexSize = FixedCountCurves::VertexBufferSize();
83 auto vertexData = bufferManager->getVertexWriter(vertexSize, &fVertexBuffer);
84 if (vertexData) {
85 FixedCountCurves::WriteVertexBuffer(std::move(vertexData), vertexSize);
86 } // otherwise static buffer creation failed, so do nothing; Context initialization will fail.
87
88 const size_t indexSize = FixedCountCurves::IndexBufferSize();
89 auto indexData = bufferManager->getIndexWriter(indexSize, &fIndexBuffer);
90 if (indexData) {
91 FixedCountCurves::WriteIndexBuffer(std::move(indexData), indexSize);
92 } // ""
93}
94
96
99 R"(
100 // TODO: Approximate perspective scaling to match how PatchWriter is configured (or
101 // provide explicit tessellation level in instance data instead of replicating
102 // work).
103 float2x2 vectorXform = float2x2(localToDevice[0].xy, localToDevice[1].xy);
104 float2 localCoord = tessellate_filled_curve(
105 vectorXform, resolveLevel_and_idx.x, resolveLevel_and_idx.y, p01, p23, %s);
106 float4 devPosition = localToDevice * float4(localCoord, 0.0, 1.0);
107 devPosition.z = depth;
108 stepLocalCoords = localCoord;
109 )",
110 fInfinitySupport ? "curve_type_using_inf_support(p23)" : "curveType");
111}
112
114 const DrawParams& params,
115 skvx::ushort2 ssboIndices) const {
116 SkPath path = params.geometry().shape().asPath(); // TODO: Iterate the Shape directly
117
118 int patchReserveCount = FixedCountCurves::PreallocCount(path.countVerbs());
119 Writer writer{fInfinitySupport ? kAttribs : kAttribsWithCurveType,
120 *dw,
121 fVertexBuffer,
122 fIndexBuffer,
123 patchReserveCount};
124 writer.updatePaintDepthAttrib(params.order().depthAsFloat());
125 writer.updateSsboIndexAttrib(ssboIndices);
126
127 // The vector xform approximates how the control points are transformed by the shader to
128 // more accurately compute how many *parametric* segments are needed.
129 // TODO: This doesn't account for perspective division yet, which will require updating the
130 // approximate transform based on each verb's control points' bounding box.
131 SkASSERT(params.transform().type() < Transform::Type::kPerspective);
132 writer.setShaderTransform(wangs_formula::VectorXform{params.transform().matrix()},
133 params.transform().maxScaleFactor());
134
135 // TODO: For filled curves, the path verb loop is simple enough that it's not too big a deal
136 // to copy the logic from PathCurveTessellator::write_patches. It may be required if we end
137 // up switching to a shape iterator in graphite vs. a path iterator in ganesh, or if
138 // graphite does not control point transformation on the CPU. On the other hand, if we
139 // provide a templated WritePatches function, the iterator could also be a template arg in
140 // addition to PatchWriter's traits. Whatever pattern we choose will be based more on what's
141 // best for the wedge and stroke case, which have more complex loops.
142 for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
143 switch (verb) {
144 case SkPathVerb::kQuad: writer.writeQuadratic(pts); break;
145 case SkPathVerb::kConic: writer.writeConic(pts, *w); break;
146 case SkPathVerb::kCubic: writer.writeCubic(pts); break;
147 default: break;
148 }
149 }
150}
151
153 PipelineDataGatherer* gatherer) const {
154 SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, this->uniforms());)
155
156 gatherer->write(params.transform().matrix());
157}
158
159} // 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.
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
TessellateCurvesRenderStep(bool evenOdd, bool infinitySupport, StaticBufferManager *bufferManager)
void writeUniformsAndTextures(const DrawParams &, PipelineDataGatherer *) const override
void writeVertices(DrawWriter *, const DrawParams &, skvx::ushort2 ssboIndices) const override
static void WriteIndexBuffer(VertexWriter, size_t bufferSize)
static constexpr size_t VertexBufferSize()
static constexpr int PreallocCount(int totalCombinedPathVerbCnt)
static constexpr size_t IndexBufferSize()
static void WriteVertexBuffer(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 DepthStencilSettings kWindingStencilPass
constexpr DepthStencilSettings kEvenOddStencilPass
constexpr size_t PatchStride(PatchAttribs attribs)
Definition: Tessellation.h:114
SkScalar w
Definition: SkVx.h:83