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