• 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             BindUniformBufferInfo 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     int count() const { return fCommands.count(); }
134 
135     void bindGraphicsPipeline(uint32_t pipelineIndex) {
136         this->add<BindGraphicsPipeline>(pipelineIndex);
137     }
138 
139     void setBlendConstants(std::array<float, 4>  blendConstants) {
140         this->add<SetBlendConstants>(this->copy(blendConstants.data(), 4));
141     }
142 
143     void bindUniformBuffer(BindUniformBufferInfo info, UniformSlot slot) {
144         this->add<BindUniformBuffer>(info, slot);
145     }
146 
147     // Caller must write 'numTexSamplers' texture and sampler indices into the two returned arrays.
148     std::pair<int*, int*>
149     bindDeferredTexturesAndSamplers(int numTexSamplers) {
150         int* textureIndices = fAlloc.makeArrayDefault<int>(numTexSamplers);
151         int* samplerIndices = fAlloc.makeArrayDefault<int>(numTexSamplers);
152         this->add<BindTexturesAndSamplers>(numTexSamplers, textureIndices, samplerIndices);
153         return {textureIndices, samplerIndices};
154     }
155 
156     void setScissor(SkIRect scissor) {
157         this->add<SetScissor>(scissor);
158     }
159 
160     void bindDrawBuffers(BindBufferInfo vertexAttribs,
161                          BindBufferInfo instanceAttribs,
162                          BindBufferInfo indices,
163                          BindBufferInfo indirect) {
164         this->add<BindDrawBuffers>(vertexAttribs, instanceAttribs, indices, indirect);
165     }
166 
167     void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) {
168         this->add<Draw>(type, baseVertex, vertexCount);
169     }
170 
171     void drawIndexed(PrimitiveType type, unsigned int baseIndex,
172                      unsigned int indexCount, unsigned int baseVertex) {
173         this->add<DrawIndexed>(type, baseIndex, indexCount, baseVertex);
174     }
175 
176     void drawInstanced(PrimitiveType type,
177                        unsigned int baseVertex, unsigned int vertexCount,
178                        unsigned int baseInstance, unsigned int instanceCount) {
179         this->add<DrawInstanced>(type, baseVertex, vertexCount, baseInstance, instanceCount);
180     }
181 
182     void drawIndexedInstanced(PrimitiveType type,
183                               unsigned int baseIndex, unsigned int indexCount,
184                               unsigned int baseVertex, unsigned int baseInstance,
185                               unsigned int instanceCount) {
186         this->add<DrawIndexedInstanced>(type,
187                                         baseIndex,
188                                         indexCount,
189                                         baseVertex,
190                                         baseInstance,
191                                         instanceCount);
192     }
193 
194     void drawIndirect(PrimitiveType type) {
195         this->add<DrawIndirect>(type);
196     }
197 
198     void drawIndexedIndirect(PrimitiveType type) {
199         this->add<DrawIndexedIndirect>(type);
200     }
201 
202     using Command = std::pair<Type, void*>;
203     using Iter = SkTBlockList<Command, 16>::CIter;
204     Iter commands() const { return fCommands.items(); }
205 
206 private:
207     template <typename T, typename... Args>
208     void add(Args&&... args) {
209         T* cmd = fAlloc.make<T>(T{std::forward<Args>(args)...});
210         fCommands.push_back(std::make_pair(T::kType, cmd));
211     }
212 
213     // This copy() is for arrays.
214     // It will work with POD only arrays.
215     template <typename T>
216     T* copy(const T src[], size_t count) {
217         static_assert(std::is_trivially_copyable<T>::value);
218         T* dst = fAlloc.makeArrayDefault<T>(count);
219         memcpy(dst, src, count*sizeof(T));
220         return dst;
221     }
222 
223     SkTBlockList<Command, 16> fCommands{SkBlockAllocator::GrowthPolicy::kFibonacci};
224 
225     // fAlloc needs to be a data structure which can append variable length data in contiguous
226     // chunks, returning a stable handle to that data for later retrieval.
227     SkArenaAlloc fAlloc{256};
228 };
229 
230 } // namespace DrawPassCommands
231 
232 } // namespace skgpu::graphite
233 
234 #endif // skgpu_graphite_DrawPassCommands_DEFINED
235