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