• 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/VerticesRenderStep.h"
9 
10 #include "src/core/SkSLTypeShared.h"
11 #include "src/core/SkVertState.h"
12 #include "src/core/SkVerticesPriv.h"
13 #include "src/gpu/graphite/DrawParams.h"
14 #include "src/gpu/graphite/DrawTypes.h"
15 #include "src/gpu/graphite/DrawWriter.h"
16 #include "src/gpu/graphite/PipelineData.h"
17 #include "src/gpu/graphite/render/CommonDepthStencilSettings.h"
18 
19 namespace skgpu::graphite {
20 
21 namespace {
22 
23 static constexpr Attribute kPositionAttr =
24         {"position", VertexAttribType::kFloat2, SkSLType::kFloat2};
25 static constexpr Attribute kTexCoordAttr =
26         {"texCoords", VertexAttribType::kFloat2, SkSLType::kFloat2};
27 static constexpr Attribute kColorAttr =
28         {"vertColor", VertexAttribType::kUByte4_norm, SkSLType::kHalf4};
29 static constexpr Attribute kSsboIndexAttr =
30         {"ssboIndices", VertexAttribType::kUShort2, SkSLType::kUShort2};
31 
32 static constexpr Attribute kAttributePositionOnly[] =
33         {kPositionAttr, kSsboIndexAttr};
34 static constexpr Attribute kAttributeColor[] =
35         {kPositionAttr, kColorAttr, kSsboIndexAttr};
36 static constexpr Attribute kAttributeTexCoords[] =
37         {kPositionAttr, kTexCoordAttr, kSsboIndexAttr};
38 static constexpr Attribute kAttributeColorAndTexCoords[] =
39         {kPositionAttr, kColorAttr, kTexCoordAttr, kSsboIndexAttr};
40 
41 static constexpr SkSpan<const Attribute> kAttributes[4] = {
42         kAttributePositionOnly,
43         kAttributeColor,
44         kAttributeTexCoords,
45         kAttributeColorAndTexCoords,
46     };
47 
48 static constexpr Varying kVaryingColor[] =
49         {{"color", SkSLType::kHalf4}};
50 
51 static constexpr SkSpan<const Varying> kVaryings[2] = {
52         /*none*/  {},
53         /*color*/ kVaryingColor
54     };
55 
variant_name(PrimitiveType type,bool hasColor,bool hasTexCoords)56 std::string variant_name(PrimitiveType type, bool hasColor, bool hasTexCoords) {
57     SkASSERT(type == PrimitiveType::kTriangles || type == PrimitiveType::kTriangleStrip);
58     std::string name = (type == PrimitiveType::kTriangles ? "tris" : "tristrips");
59     if (hasColor) {
60         name += "-color";
61     }
62     if (hasTexCoords) {
63         name += "-texCoords";
64     }
65     return name;
66 }
67 
68 }  // namespace
69 
VerticesRenderStep(PrimitiveType type,bool hasColor,bool hasTexCoords)70 VerticesRenderStep::VerticesRenderStep(PrimitiveType type, bool hasColor, bool hasTexCoords)
71         : RenderStep("VerticesRenderStep",
72                      variant_name(type, hasColor, hasTexCoords),
73                      hasColor ? Flags::kEmitsPrimitiveColor | Flags::kPerformsShading
74                               : Flags::kPerformsShading,
75                      /*uniforms=*/{{"localToDevice", SkSLType::kFloat4x4},
76                                    {"depth", SkSLType::kFloat}},
77                      type,
78                      kDirectDepthGEqualPass,
79                      /*vertexAttrs=*/  kAttributes[2*hasTexCoords + hasColor],
80                      /*instanceAttrs=*/{},
81                      /*varyings=*/     kVaryings[hasColor])
82         , fHasColor(hasColor)
83         , fHasTexCoords(hasTexCoords) {}
84 
~VerticesRenderStep()85 VerticesRenderStep::~VerticesRenderStep() {}
86 
vertexSkSL() const87 std::string VerticesRenderStep::vertexSkSL() const {
88     if (fHasColor && fHasTexCoords) {
89         return R"(
90             color = half4(vertColor.bgr * vertColor.a, vertColor.a);
91             float4 devPosition = localToDevice * float4(position, 0.0, 1.0);
92             devPosition.z = depth;
93             stepLocalCoords = texCoords;
94         )";
95     } else if (fHasTexCoords) {
96         return R"(
97             float4 devPosition = localToDevice * float4(position, 0.0, 1.0);
98             devPosition.z = depth;
99             stepLocalCoords = texCoords;
100         )";
101     } else if (fHasColor) {
102         return R"(
103             color = half4(vertColor.bgr * vertColor.a, vertColor.a);
104             float4 devPosition = localToDevice * float4(position, 0.0, 1.0);
105             devPosition.z = depth;
106             stepLocalCoords = position;
107         )";
108     } else {
109         return R"(
110             float4 devPosition = localToDevice * float4(position, 0.0, 1.0);
111             devPosition.z = depth;
112             stepLocalCoords = position;
113         )";
114     }
115 }
116 
fragmentColorSkSL() const117 const char* VerticesRenderStep::fragmentColorSkSL() const {
118     if (fHasColor) {
119         return "primitiveColor = color;\n";
120     } else {
121         return "";
122     }
123 }
124 
writeVertices(DrawWriter * writer,const DrawParams & params,skvx::ushort2 ssboIndices) const125 void VerticesRenderStep::writeVertices(DrawWriter* writer,
126                                        const DrawParams& params,
127                                        skvx::ushort2 ssboIndices) const {
128     SkVerticesPriv info(params.geometry().vertices()->priv());
129     const int vertexCount = info.vertexCount();
130     const int indexCount = info.indexCount();
131     const SkPoint* positions = info.positions();
132     const uint16_t* indices = info.indices();
133     const SkColor* colors = info.colors();
134     const SkPoint* texCoords = info.texCoords();
135 
136     // This should always be the case if the Renderer was chosen appropriately, but the vertex
137     // writing loop is set up in such a way that if the shader expects color or tex coords and they
138     // are missing, it will just read 0s, so release builds are safe.
139     SkASSERT(fHasColor == SkToBool(colors));
140     SkASSERT(fHasTexCoords == SkToBool(texCoords));
141 
142     // TODO: We could access the writer's DrawBufferManager and upload the SkVertices index buffer
143     // but that would require we manually manage the VertexWriter for interleaving the position,
144     // color, and tex coord arrays together. This wouldn't be so bad if we let ::Vertices() take
145     // a CPU index buffer that indexes into the accumulated vertex data (and handles offsetting for
146     // merged drawIndexed calls), or if we could bind multiple attribute sources and copy the
147     // position/color/texCoord data separately in bulk w/o using an Appender.
148     DrawWriter::Vertices verts{*writer};
149     verts.reserve(indices ? indexCount : vertexCount);
150 
151     VertState state(vertexCount, indices, indexCount);
152     VertState::Proc vertProc = state.chooseProc(info.mode());
153     while (vertProc(&state)) {
154         verts.append(3) << positions[state.f0]
155                         << VertexWriter::If(fHasColor, colors ? colors[state.f0]
156                                                               : SK_ColorTRANSPARENT)
157                         << VertexWriter::If(fHasTexCoords, texCoords ? texCoords[state.f0]
158                                                                      : SkPoint{0.f, 0.f})
159                         << ssboIndices
160                         << positions[state.f1]
161                         << VertexWriter::If(fHasColor, colors ? colors[state.f1]
162                                                               : SK_ColorTRANSPARENT)
163                         << VertexWriter::If(fHasTexCoords, texCoords ? texCoords[state.f1]
164                                                                      : SkPoint{0.f, 0.f})
165                         << ssboIndices
166                         << positions[state.f2]
167                         << VertexWriter::If(fHasColor, colors ? colors[state.f2]
168                                                               : SK_ColorTRANSPARENT)
169                         << VertexWriter::If(fHasTexCoords, texCoords ? texCoords[state.f2]
170                                                                      : SkPoint{0.f, 0.f})
171                         << ssboIndices;
172     }
173 }
174 
writeUniformsAndTextures(const DrawParams & params,PipelineDataGatherer * gatherer) const175 void VerticesRenderStep::writeUniformsAndTextures(const DrawParams& params,
176                                                   PipelineDataGatherer* gatherer) const {
177     // Vertices are transformed on the GPU. Store PaintDepth as a uniform to avoid copying the
178     // same depth for each vertex.
179     SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, this->uniforms());)
180     gatherer->write(params.transform().matrix());
181     gatherer->write(params.order().depthAsFloat());
182 }
183 
184 }  // namespace skgpu::graphite
185