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