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