/* * Copyright 2021 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef skgpu_CommandBuffer_DEFINED #define skgpu_CommandBuffer_DEFINED #include "experimental/graphite/include/TextureInfo.h" #include "experimental/graphite/src/DrawTypes.h" #include "experimental/graphite/src/DrawWriter.h" #include "include/core/SkColor.h" #include "include/core/SkRect.h" #include "include/core/SkRefCnt.h" #include "include/private/SkTArray.h" struct SkIRect; namespace skgpu { class Buffer; class Gpu; class GraphicsPipeline; class Resource; class Sampler; class Texture; class TextureProxy; enum class UniformSlot { // TODO: Want this? // Meant for uniforms that change rarely to never over the course of a render pass // kStatic, // Meant for uniforms that are defined and used by the RenderStep portion of the pipeline shader kRenderStep, // Meant for uniforms that are defined and used by the paint parameters (ie SkPaint subset) kPaint, }; struct AttachmentDesc { TextureInfo fTextureInfo; LoadOp fLoadOp; StoreOp fStoreOp; }; struct RenderPassDesc { AttachmentDesc fColorAttachment; std::array fClearColor; AttachmentDesc fColorResolveAttachment; AttachmentDesc fDepthStencilAttachment; float fClearDepth; uint32_t fClearStencil; // TODO: // * bounds (TBD whether exact bounds vs. granular) // * input attachments }; // specifies a single region for copying, either from buffer to texture, or vice versa struct BufferTextureCopyData { size_t fBufferOffset; size_t fBufferRowBytes; SkIRect fRect; unsigned int fMipLevel; }; class CommandBuffer : public SkRefCnt, private DrawDispatcher { public: ~CommandBuffer() override; #ifdef SK_DEBUG bool hasWork() { return fHasWork; } #endif void trackResource(sk_sp resource); bool beginRenderPass(const RenderPassDesc&, sk_sp colorTexture, sk_sp resolveTexture, sk_sp depthStencilTexture); virtual void endRenderPass() = 0; //--------------------------------------------------------------- // Can only be used within renderpasses //--------------------------------------------------------------- void bindGraphicsPipeline(sk_sp graphicsPipeline); void bindUniformBuffer(UniformSlot, sk_sp, size_t bufferOffset); void bindDrawBuffers(BindBufferInfo vertices, BindBufferInfo instances, BindBufferInfo indices) final; struct TextureBindEntry { sk_sp fTexture; unsigned int fBindIndex; }; void bindTextures(const TextureBindEntry* entries, int count); struct SamplerBindEntry { sk_sp fSampler; unsigned int fBindIndex; }; void bindSamplers(const SamplerBindEntry* entries, int count); // TODO: do we want to handle multiple scissor rects and viewports? void setScissor(unsigned int left, unsigned int top, unsigned int width, unsigned int height) { this->onSetScissor(left, top, width, height); } void setViewport(float x, float y, float width, float height, float minDepth = 0, float maxDepth = 1) { this->onSetViewport(x, y, width, height, minDepth, maxDepth); } void setBlendConstants(std::array blendConstants) { this->onSetBlendConstants(blendConstants); } void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) final { this->onDraw(type, baseVertex, vertexCount); SkDEBUGCODE(fHasWork = true;) } void drawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount, unsigned int baseVertex) final { this->onDrawIndexed(type, baseIndex, indexCount, baseVertex); SkDEBUGCODE(fHasWork = true;) } void drawInstanced(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount, unsigned int baseInstance, unsigned int instanceCount) final { this->onDrawInstanced(type, baseVertex, vertexCount, baseInstance, instanceCount); SkDEBUGCODE(fHasWork = true;) } void drawIndexedInstanced(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount, unsigned int baseVertex, unsigned int baseInstance, unsigned int instanceCount) final { this->onDrawIndexedInstanced(type, baseIndex, indexCount, baseVertex, baseInstance, instanceCount); SkDEBUGCODE(fHasWork = true;) } // When using a DrawWriter dispatching directly to a CommandBuffer, binding of pipelines and // uniforms must be coordinated with forNewPipeline() and forDynamicStateChange(). The direct // draw calls and vertex buffer binding calls on CB should not be intermingled with the writer. DrawDispatcher* asDrawDispatcher() { return this; } //--------------------------------------------------------------- // Can only be used outside renderpasses //--------------------------------------------------------------- bool copyTextureToBuffer(sk_sp, SkIRect srcRect, sk_sp, size_t bufferOffset, size_t bufferRowBytes); bool copyBufferToTexture(sk_sp, sk_sp, const BufferTextureCopyData*, int count); protected: CommandBuffer(); private: void releaseResources(); // TODO: Once all buffer use goes through the DrawBufferManager, we likely do not need to track // refs every time a buffer is bound, since the DBM will transfer ownership for any used buffer // to the CommandBuffer. void bindVertexBuffers(sk_sp vertexBuffer, size_t vertexOffset, sk_sp instanceBuffer, size_t instanceOffset); void bindIndexBuffer(sk_sp indexBuffer, size_t bufferOffset); virtual bool onBeginRenderPass(const RenderPassDesc&, const Texture* colorTexture, const Texture* resolveTexture, const Texture* depthStencilTexture) = 0; virtual void onBindGraphicsPipeline(const GraphicsPipeline*) = 0; virtual void onBindUniformBuffer(UniformSlot, const Buffer*, size_t bufferOffset) = 0; virtual void onBindVertexBuffers(const Buffer* vertexBuffer, size_t vertexOffset, const Buffer* instanceBuffer, size_t instanceOffset) = 0; virtual void onBindIndexBuffer(const Buffer* indexBuffer, size_t bufferOffset) = 0; virtual void onBindTextures(const TextureBindEntry* entries, int count) = 0; virtual void onBindSamplers(const SamplerBindEntry* entries, int count) = 0; virtual void onSetScissor(unsigned int left, unsigned int top, unsigned int width, unsigned int height) = 0; virtual void onSetViewport(float x, float y, float width, float height, float minDepth, float maxDepth) = 0; virtual void onSetBlendConstants(std::array blendConstants) = 0; virtual void onDraw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) = 0; virtual void onDrawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount, unsigned int baseVertex) = 0; virtual void onDrawInstanced(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount, unsigned int baseInstance, unsigned int instanceCount) = 0; virtual void onDrawIndexedInstanced(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount, unsigned int baseVertex, unsigned int baseInstance, unsigned int instanceCount) = 0; virtual bool onCopyTextureToBuffer(const Texture*, SkIRect srcRect, const Buffer*, size_t bufferOffset, size_t bufferRowBytes) = 0; virtual bool onCopyBufferToTexture(const Buffer*, const Texture*, const BufferTextureCopyData*, int count) = 0; #ifdef SK_DEBUG bool fHasWork = false; #endif inline static constexpr int kInitialTrackedResourcesCount = 32; SkSTArray> fTrackedResources; }; } // namespace skgpu #endif // skgpu_CommandBuffer_DEFINED