| /* | |
| * Copyright 2022 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef skgpu_graphite_DrawPassCommands_DEFINED | |
| #define skgpu_graphite_DrawPassCommands_DEFINED | |
| #include "include/core/SkRect.h" | |
| #include "src/core/SkArenaAlloc.h" | |
| #include "src/core/SkBlockAllocator.h" | |
| #include "src/core/SkTBlockList.h" | |
| #include "src/gpu/graphite/CommandTypes.h" | |
| #include "src/gpu/graphite/ResourceTypes.h" | |
| #include <array> | |
| #include <cstdint> | |
| #include <type_traits> | |
| #include <utility> | |
| namespace skgpu::graphite { | |
| enum class BarrierType : uint8_t; | |
| enum class PrimitiveType : uint8_t; | |
| enum class UniformSlot; | |
| class TextureProxy; | |
| namespace DrawPassCommands { | |
| struct AddBarrier; | |
| struct BindAppendDataBuffer; | |
| struct BindGraphicsPipeline; | |
| struct BindIndexBuffer; | |
| struct BindIndirectBuffer; | |
| struct BindStaticDataBuffer; | |
| struct BindTexturesAndSamplers; | |
| struct BindUniformBuffer; | |
| struct Draw; | |
| struct DrawIndexed; | |
| struct DrawIndexedIndirect; | |
| struct DrawIndexedInstanced; | |
| struct DrawIndirect; | |
| struct DrawInstanced; | |
| struct SetBlendConstants; | |
| struct SetScissor; | |
| // A list of all the commands types used by a DrawPass. | |
| // Each of these is reified into a struct below. | |
| // | |
| // The design of this systems is based on SkRecords. | |
| // (We're using the macro-of-macro trick here to do several different things with the same list.) | |
| // | |
| // We leave this SKGPU_DRAW_COMMAND_TYPES macro defined for use by code that wants to operate on | |
| // DrawPassCommands types polymorphically. | |
| #define SKGPU_DRAW_PASS_COMMAND_TYPES(M) \ | |
| M(BindGraphicsPipeline) \ | |
| M(SetBlendConstants) \ | |
| M(BindUniformBuffer) \ | |
| M(BindStaticDataBuffer) \ | |
| M(BindAppendDataBuffer) \ | |
| M(BindIndirectBuffer) \ | |
| M(BindIndexBuffer) \ | |
| M(BindTexturesAndSamplers) \ | |
| M(SetScissor) \ | |
| M(Draw) \ | |
| M(DrawIndexed) \ | |
| M(DrawInstanced) \ | |
| M(DrawIndexedInstanced) \ | |
| M(DrawIndirect) \ | |
| M(DrawIndexedIndirect) \ | |
| M(AddBarrier) | |
| // Defines DrawPassCommands::Type, an enum of all draw command types. | |
| #define ENUM(T) k##T, | |
| enum class Type { SKGPU_DRAW_PASS_COMMAND_TYPES(ENUM) }; | |
| #undef ENUM | |
| #define ACT_AS_PTR(ptr) \ | |
| operator T*() const { return ptr; } \ | |
| T* operator->() const { return ptr; } | |
| // PODArray doesn't own the pointer's memory, and we assume the data is POD. | |
| template <typename T> | |
| class PODArray { | |
| public: | |
| PODArray() {} | |
| PODArray(T* ptr) : fPtr(ptr) {} | |
| // Default copy and assign. | |
| ACT_AS_PTR(fPtr) | |
| private: | |
| T* fPtr; | |
| }; | |
| #undef ACT_AS_PTR | |
| // A macro to make it a little easier to define a struct that can be stored in DrawPass. | |
| #define COMMAND(T, ...) \ | |
| struct T { \ | |
| static constexpr Type kType = Type::k##T; \ | |
| __VA_ARGS__; \ | |
| }; | |
| COMMAND(BindGraphicsPipeline, | |
| uint32_t fPipelineIndex) | |
| COMMAND(SetBlendConstants, | |
| std::array<float, 4> fBlendConstants) | |
| COMMAND(BindUniformBuffer, | |
| BindBufferInfo fInfo; | |
| UniformSlot fSlot) | |
| COMMAND(BindStaticDataBuffer, | |
| BindBufferInfo fStaticData) | |
| COMMAND(BindAppendDataBuffer, | |
| BindBufferInfo fAppendData) | |
| COMMAND(BindIndexBuffer, | |
| BindBufferInfo fIndices) | |
| COMMAND(BindIndirectBuffer, | |
| BindBufferInfo fIndirect) | |
| COMMAND(BindTexturesAndSamplers, | |
| int fNumTexSamplers; | |
| PODArray<const TextureProxy*> fTextures; | |
| PODArray<SamplerDesc> fSamplers) | |
| COMMAND(SetScissor, | |
| Scissor fScissor) | |
| COMMAND(Draw, | |
| PrimitiveType fType; | |
| uint32_t fBaseVertex; | |
| uint32_t fVertexCount) | |
| COMMAND(DrawIndexed, | |
| PrimitiveType fType; | |
| uint32_t fBaseIndex; | |
| uint32_t fIndexCount; | |
| uint32_t fBaseVertex) | |
| COMMAND(DrawInstanced, | |
| PrimitiveType fType; | |
| uint32_t fBaseVertex; | |
| uint32_t fVertexCount; | |
| uint32_t fBaseInstance; | |
| uint32_t fInstanceCount) | |
| COMMAND(DrawIndexedInstanced, | |
| PrimitiveType fType; | |
| uint32_t fBaseIndex; | |
| uint32_t fIndexCount; | |
| uint32_t fBaseVertex; | |
| uint32_t fBaseInstance; | |
| uint32_t fInstanceCount) | |
| COMMAND(DrawIndirect, | |
| PrimitiveType fType) | |
| COMMAND(DrawIndexedIndirect, | |
| PrimitiveType fType) | |
| COMMAND(AddBarrier, | |
| BarrierType fType) | |
| #undef COMMAND | |
| #define ASSERT_TRIV_DES(T) static_assert(std::is_trivially_destructible<T>::value); | |
| SKGPU_DRAW_PASS_COMMAND_TYPES(ASSERT_TRIV_DES) | |
| #undef ASSERT_TRIV_DES | |
| #define ASSERT_TRIV_CPY(T) static_assert(std::is_trivially_copyable<T>::value); | |
| SKGPU_DRAW_PASS_COMMAND_TYPES(ASSERT_TRIV_CPY) | |
| #undef ASSERT_TRIV_CPY | |
| class List { | |
| public: | |
| List() = default; | |
| ~List() = default; | |
| int count() const { return fCommands.count(); } | |
| void bindGraphicsPipeline(uint32_t pipelineIndex) { | |
| this->add<BindGraphicsPipeline>(pipelineIndex); | |
| } | |
| void setBlendConstants(std::array<float, 4> blendConstants) { | |
| this->add<SetBlendConstants>(blendConstants); | |
| } | |
| void bindUniformBuffer(BindBufferInfo info, UniformSlot slot) { | |
| this->add<BindUniformBuffer>(info, slot); | |
| } | |
| // Caller must write 'numTexSamplers' textures and sampler descriptions into the two returned | |
| // arrays. The texture proxies must have refs held for the lifetime of this command list. | |
| std::pair<const TextureProxy**, SamplerDesc*> | |
| bindDeferredTexturesAndSamplers(int numTexSamplers) { | |
| const TextureProxy** textures = fAlloc.makeArrayDefault<const TextureProxy*>(numTexSamplers); | |
| SamplerDesc* samplers = fAlloc.makeArrayDefault<SamplerDesc>(numTexSamplers); | |
| this->add<BindTexturesAndSamplers>(numTexSamplers, textures, samplers); | |
| return {textures, samplers}; | |
| } | |
| void setScissor(SkIRect scissor) { | |
| this->add<SetScissor>(Scissor(scissor)); | |
| } | |
| void bindStaticDataBuffer(BindBufferInfo staticAttribs) { | |
| this->add<BindStaticDataBuffer>(staticAttribs); | |
| } | |
| void bindAppendDataBuffer(BindBufferInfo appendAttribs) { | |
| this->add<BindAppendDataBuffer>(appendAttribs); | |
| } | |
| void bindIndexBuffer(BindBufferInfo indices) { | |
| this->add<BindIndexBuffer>(indices); | |
| } | |
| void bindIndirectBuffer(BindBufferInfo indirect) { | |
| this->add<BindIndirectBuffer>(indirect); | |
| } | |
| void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) { | |
| this->add<Draw>(type, baseVertex, vertexCount); | |
| } | |
| void drawIndexed(PrimitiveType type, unsigned int baseIndex, | |
| unsigned int indexCount, unsigned int baseVertex) { | |
| this->add<DrawIndexed>(type, baseIndex, indexCount, baseVertex); | |
| } | |
| void drawInstanced(PrimitiveType type, | |
| unsigned int baseVertex, unsigned int vertexCount, | |
| unsigned int baseInstance, unsigned int instanceCount) { | |
| this->add<DrawInstanced>(type, baseVertex, vertexCount, baseInstance, instanceCount); | |
| } | |
| void drawIndexedInstanced(PrimitiveType type, | |
| unsigned int baseIndex, unsigned int indexCount, | |
| unsigned int baseVertex, unsigned int baseInstance, | |
| unsigned int instanceCount) { | |
| this->add<DrawIndexedInstanced>(type, | |
| baseIndex, | |
| indexCount, | |
| baseVertex, | |
| baseInstance, | |
| instanceCount); | |
| } | |
| void drawIndirect(PrimitiveType type) { | |
| this->add<DrawIndirect>(type); | |
| } | |
| void drawIndexedIndirect(PrimitiveType type) { | |
| this->add<DrawIndexedIndirect>(type); | |
| } | |
| void addBarrier(BarrierType type) { | |
| this->add<AddBarrier>(type); | |
| } | |
| using Command = std::pair<Type, void*>; | |
| using Iter = SkTBlockList<Command, 16>::CIter; | |
| Iter commands() const { return fCommands.items(); } | |
| private: | |
| template <typename T, typename... Args> | |
| void add(Args&&... args) { | |
| T* cmd = fAlloc.make<T>(T{std::forward<Args>(args)...}); | |
| fCommands.push_back(std::make_pair(T::kType, cmd)); | |
| } | |
| SkTBlockList<Command, 16> fCommands{SkBlockAllocator::GrowthPolicy::kFibonacci}; | |
| // fAlloc needs to be a data structure which can append variable length data in contiguous | |
| // chunks, returning a stable handle to that data for later retrieval. | |
| SkArenaAlloc fAlloc{256}; | |
| }; | |
| } // namespace DrawPassCommands | |
| } // namespace skgpu::graphite | |
| #endif // skgpu_graphite_DrawPassCommands_DEFINED |