Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
#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.
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
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
constexpr DepthStencilSettings kWindingStencilPass
constexpr DepthStencilSettings kEvenOddStencilPass
constexpr size_t PatchStride(PatchAttribs attribs)
SkScalar w