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