• 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 #ifndef skgpu_graphite_DrawPassCommands_DEFINED
9 #define skgpu_graphite_DrawPassCommands_DEFINED
10 
11 #include "include/core/SkRect.h"
12 #include "src/base/SkArenaAlloc.h"
13 #include "src/base/SkTBlockList.h"
14 #include "src/gpu/graphite/DrawTypes.h"
15 
16 namespace skgpu::graphite {
17 
18 namespace DrawPassCommands {
19 
20 // A list of all the commands types used by a DrawPass.
21 // Each of these is reified into a struct below.
22 //
23 // The design of this systems is based on SkRecords.
24 
25 // (We're using the macro-of-macro trick here to do several different things with the same list.)
26 //
27 // We leave this SKGPU_DRAW_COMMAND_TYPES macro defined for use by code that wants to operate on
28 // DrawPassCommands types polymorphically.
29 #define SKGPU_DRAW_PASS_COMMAND_TYPES(M) \
30     M(BindGraphicsPipeline)              \
31     M(SetBlendConstants)                 \
32     M(BindUniformBuffer)                 \
33     M(BindDrawBuffers)                   \
34     M(BindTexturesAndSamplers)           \
35     M(SetScissor)                        \
36     M(Draw)                              \
37     M(DrawIndexed)                       \
38     M(DrawInstanced)                     \
39     M(DrawIndexedInstanced)              \
40     M(DrawIndirect)                      \
41     M(DrawIndexedIndirect)
42 
43 // Defines DrawPassCommands::Type, an enum of all draw command types.
44 #define ENUM(T) k##T,
45 enum class Type { SKGPU_DRAW_PASS_COMMAND_TYPES(ENUM) };
46 #undef ENUM
47 
48 #define ACT_AS_PTR(ptr)                 \
49     operator T*() const { return ptr; } \
50     T* operator->() const { return ptr; }
51 
52 // PODArray doesn't own the pointer's memory, and we assume the data is POD.
53 template <typename T>
54 class PODArray {
55 public:
PODArray()56     PODArray() {}
PODArray(T * ptr)57     PODArray(T* ptr) : fPtr(ptr) {}
58     // Default copy and assign.
59 
60     ACT_AS_PTR(fPtr)
61 private:
62     T* fPtr;
63 };
64 
65 #undef ACT_AS_PTR
66 
67 // A macro to make it a little easier to define a struct that can be stored in DrawPass.
68 #define COMMAND(T, ...)                    \
69 struct T {                                 \
70 static constexpr Type kType = Type::k##T;  \
71     __VA_ARGS__;                           \
72 };
73 
74 COMMAND(BindGraphicsPipeline,
75             uint32_t fPipelineIndex);
76 COMMAND(SetBlendConstants,
77             PODArray<float> fBlendConstants);
78 COMMAND(BindUniformBuffer,
79             BindBufferInfo fInfo;
80             UniformSlot fSlot);
81 COMMAND(BindDrawBuffers,
82             BindBufferInfo fVertices;
83             BindBufferInfo fInstances;
84             BindBufferInfo fIndices;
85             BindBufferInfo fIndirect);
86 COMMAND(BindTexturesAndSamplers,
87             int fNumTexSamplers;
88             PODArray<int> fTextureIndices;
89             PODArray<int> fSamplerIndices);
90 COMMAND(SetScissor,
91             SkIRect fScissor);
92 COMMAND(Draw,
93             PrimitiveType fType;
94             uint32_t fBaseVertex;
95             uint32_t fVertexCount);
96 COMMAND(DrawIndexed,
97             PrimitiveType fType;
98             uint32_t fBaseIndex;
99             uint32_t fIndexCount;
100             uint32_t fBaseVertex);
101 COMMAND(DrawInstanced,
102             PrimitiveType fType;
103             uint32_t fBaseVertex;
104             uint32_t fVertexCount;
105             uint32_t fBaseInstance;
106             uint32_t fInstanceCount);
107 COMMAND(DrawIndexedInstanced,
108             PrimitiveType fType;
109             uint32_t fBaseIndex;
110             uint32_t fIndexCount;
111             uint32_t fBaseVertex;
112             uint32_t fBaseInstance;
113             uint32_t fInstanceCount);
114 COMMAND(DrawIndirect,
115             PrimitiveType fType);
116 COMMAND(DrawIndexedIndirect,
117             PrimitiveType fType);
118 
119 #undef COMMAND
120 
121 #define ASSERT_TRIV_DES(T) static_assert(std::is_trivially_destructible<T>::value);
122 SKGPU_DRAW_PASS_COMMAND_TYPES(ASSERT_TRIV_DES)
123 #undef ASSERT_TRIV_DES
124 #define ASSERT_TRIV_CPY(T) static_assert(std::is_trivially_copyable<T>::value);
125 SKGPU_DRAW_PASS_COMMAND_TYPES(ASSERT_TRIV_CPY)
126 #undef ASSERT_TRIV_CPY
127 
128 class List {
129 public:
130     List() = default;
131     ~List() = default;
132 
133     void bindGraphicsPipeline(uint32_t pipelineIndex) {
134         this->add<BindGraphicsPipeline>(pipelineIndex);
135     }
136 
137     void setBlendConstants(std::array<float, 4>  blendConstants) {
138         this->add<SetBlendConstants>(this->copy(blendConstants.data(), 4));
139     }
140 
141     void bindUniformBuffer(BindBufferInfo info, UniformSlot slot) {
142         this->add<BindUniformBuffer>(info, slot);
143     }
144 
145     // Caller must write 'numTexSamplers' texture and sampler indices into the two returned arrays.
146     std::pair<int*, int*>
147     bindDeferredTexturesAndSamplers(int numTexSamplers) {
148         int* textureIndices = fAlloc.makeArrayDefault<int>(numTexSamplers);
149         int* samplerIndices = fAlloc.makeArrayDefault<int>(numTexSamplers);
150         this->add<BindTexturesAndSamplers>(numTexSamplers, textureIndices, samplerIndices);
151         return {textureIndices, samplerIndices};
152     }
153 
154     void setScissor(SkIRect scissor) {
155         this->add<SetScissor>(scissor);
156     }
157 
158     void bindDrawBuffers(BindBufferInfo vertexAttribs,
159                          BindBufferInfo instanceAttribs,
160                          BindBufferInfo indices,
161                          BindBufferInfo indirect) {
162         this->add<BindDrawBuffers>(vertexAttribs, instanceAttribs, indices, indirect);
163     }
164 
165     void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) {
166         this->add<Draw>(type, baseVertex, vertexCount);
167     }
168 
169     void drawIndexed(PrimitiveType type, unsigned int baseIndex,
170                      unsigned int indexCount, unsigned int baseVertex) {
171         this->add<DrawIndexed>(type, baseIndex, indexCount, baseVertex);
172     }
173 
174     void drawInstanced(PrimitiveType type,
175                        unsigned int baseVertex, unsigned int vertexCount,
176                        unsigned int baseInstance, unsigned int instanceCount) {
177         this->add<DrawInstanced>(type, baseVertex, vertexCount, baseInstance, instanceCount);
178     }
179 
180     void drawIndexedInstanced(PrimitiveType type,
181                               unsigned int baseIndex, unsigned int indexCount,
182                               unsigned int baseVertex, unsigned int baseInstance,
183                               unsigned int instanceCount) {
184         this->add<DrawIndexedInstanced>(type,
185                                         baseIndex,
186                                         indexCount,
187                                         baseVertex,
188                                         baseInstance,
189                                         instanceCount);
190     }
191 
192     void drawIndirect(PrimitiveType type) {
193         this->add<DrawIndirect>(type);
194     }
195 
196     void drawIndexedIndirect(PrimitiveType type) {
197         this->add<DrawIndexedIndirect>(type);
198     }
199 
200     using Command = std::pair<Type, void*>;
201     using Iter = SkTBlockList<Command>::CIter;
202     Iter commands() const { return fCommands.items(); }
203 
204 private:
205     template <typename T, typename... Args>
206     void add(Args&&... args) {
207         T* cmd = fAlloc.make<T>(T{std::forward<Args>(args)...});
208         fCommands.push_back(std::make_pair(T::kType, cmd));
209     }
210 
211     // This copy() is for arrays.
212     // It will work with POD only arrays.
213     template <typename T>
214     T* copy(const T src[], size_t count) {
215         static_assert(std::is_trivially_copyable<T>::value);
216         T* dst = fAlloc.makeArrayDefault<T>(count);
217         memcpy(dst, src, count*sizeof(T));
218         return dst;
219     }
220 
221     SkTBlockList<Command> fCommands;
222 
223     // fAlloc needs to be a data structure which can append variable length data in contiguous
224     // chunks, returning a stable handle to that data for later retrieval.
225     SkArenaAlloc fAlloc{256};
226 };
227 
228 } // namespace DrawPassCommands
229 
230 } // namespace skgpu::graphite
231 
232 #endif // skgpu_graphite_DrawPassCommands_DEFINED
233