• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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/DrawWriter.h"
9 
10 #include "src/gpu/BufferWriter.h"
11 #include "src/gpu/graphite/DrawCommands.h"
12 
13 namespace skgpu::graphite {
14 
DrawWriter(DrawPassCommands::List * commandList,DrawBufferManager * bufferManager)15 DrawWriter::DrawWriter(DrawPassCommands::List* commandList, DrawBufferManager* bufferManager)
16         : fCommandList(commandList)
17         , fManager(bufferManager)
18         , fPrimitiveType(PrimitiveType::kTriangles)
19         , fVertexStride(0)
20         , fInstanceStride(0)
21         , fVertices()
22         , fIndices()
23         , fInstances()
24         , fTemplateCount(0)
25         , fPendingCount(0)
26         , fPendingBase(0)
27         , fPendingBufferBinds(true) {
28     SkASSERT(commandList && bufferManager);
29 }
30 
setTemplate(BindBufferInfo vertices,BindBufferInfo indices,BindBufferInfo instances,int templateCount)31 void DrawWriter::setTemplate(BindBufferInfo vertices,
32                              BindBufferInfo indices,
33                              BindBufferInfo instances,
34                              int templateCount) {
35     if (vertices != fVertices || instances != fInstances || fIndices != indices) {
36         if (fPendingCount > 0) {
37             this->flush();
38         }
39 
40         bool willAppendVertices = templateCount == 0;
41         bool isAppendingVertices = fTemplateCount == 0;
42         if (willAppendVertices != isAppendingVertices ||
43             (isAppendingVertices && fVertices != vertices) ||
44             (!isAppendingVertices && fInstances != instances)) {
45             // The buffer binding target for appended data is changing, so reset the base offset
46             fPendingBase = 0;
47         }
48 
49         fVertices = vertices;
50         fInstances = instances;
51         fIndices = indices;
52 
53         fTemplateCount = templateCount;
54 
55         fPendingBufferBinds = true;
56     } else if ((templateCount >= 0 && templateCount != fTemplateCount) || // vtx or reg. instances
57                (templateCount < 0 && fTemplateCount >= 0)) {              // dynamic index instances
58         if (fPendingCount > 0) {
59             this->flush();
60         }
61         if ((templateCount == 0) != (fTemplateCount == 0)) {
62             // Switching from appending vertices to instances, or vice versa, so the pending
63             // base vertex for appended data is invalid
64             fPendingBase = 0;
65         }
66         fTemplateCount = templateCount;
67     }
68 
69     SkASSERT(fVertices  == vertices);
70     SkASSERT(fInstances == instances);
71     SkASSERT(fIndices   == indices);
72     // NOTE: This allows 'fTemplateCount' to update across multiple DynamicInstances as long
73     // as they have the same vertex and index buffers.
74     SkASSERT((fTemplateCount < 0) == (templateCount < 0));
75     SkASSERT(fTemplateCount < 0 || fTemplateCount == templateCount);
76 }
77 
flush()78 void DrawWriter::flush() {
79     // If nothing was appended, or the only appended data was through dynamic instances and the
80     // final vertex count per instance is 0 (-1 in the sign encoded field), nothing should be drawn.
81     if (fPendingCount == 0 || fTemplateCount == -1) {
82         return;
83     }
84     if (fPendingBufferBinds) {
85         fCommandList->bindDrawBuffers(fVertices, fInstances, fIndices, {});
86         fPendingBufferBinds = false;
87     }
88 
89     if (fTemplateCount) {
90         // Instanced drawing
91         unsigned int realVertexCount;
92         if (fTemplateCount < 0) {
93             realVertexCount = -fTemplateCount - 1;
94             fTemplateCount = -1; // reset to re-accumulate max index account for next flush
95         } else {
96             realVertexCount = fTemplateCount;
97         }
98 
99         if (fIndices) {
100             fCommandList->drawIndexedInstanced(fPrimitiveType, 0, realVertexCount, 0,
101                                                fPendingBase, fPendingCount);
102         } else {
103             fCommandList->drawInstanced(fPrimitiveType, 0, realVertexCount,
104                                         fPendingBase, fPendingCount);
105         }
106     } else {
107         SkASSERT(!fInstances);
108         if (fIndices) {
109             fCommandList->drawIndexed(fPrimitiveType, 0, fPendingCount, fPendingBase);
110         } else {
111             fCommandList->draw(fPrimitiveType, fPendingBase, fPendingCount);
112         }
113     }
114 
115     fPendingBase += fPendingCount;
116     fPendingCount = 0;
117 }
118 
119 } // namespace skgpu::graphite
120