/* * 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_VulkanCommandBuffer_DEFINED #define skgpu_graphite_VulkanCommandBuffer_DEFINED #include "src/gpu/graphite/CommandBuffer.h" #include "include/gpu/vk/VulkanTypes.h" #include "src/gpu/graphite/DrawPass.h" #include "src/gpu/graphite/vk/VulkanGraphicsPipeline.h" #include "src/gpu/graphite/vk/VulkanResourceProvider.h" namespace skgpu::graphite { class VulkanBuffer; class VulkanDescriptorSet; class VulkanSharedContext; class VulkanTexture; class Buffer; class VulkanCommandBuffer final : public CommandBuffer { public: static std::unique_ptr Make(const VulkanSharedContext*, VulkanResourceProvider*, Protected); ~VulkanCommandBuffer() override; bool setNewCommandBufferResources() override; bool submit(VkQueue); bool isFinished(); void waitUntilFinished(); void addBufferMemoryBarrier(const Resource* resource, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkBufferMemoryBarrier* barrier); void addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkBufferMemoryBarrier* barrier); void addImageMemoryBarrier(const Resource*, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, bool byRegion, VkImageMemoryBarrier* barrier); private: VulkanCommandBuffer(VkCommandPool pool, VkCommandBuffer primaryCommandBuffer, const VulkanSharedContext* sharedContext, VulkanResourceProvider* resourceProvider, Protected); ResourceProvider* resourceProvider() const override { return fResourceProvider; } void onResetCommandBuffer() override; void begin(); void end(); void addWaitSemaphores(size_t numWaitSemaphores, const BackendSemaphore* waitSemaphores) override; void addSignalSemaphores(size_t numWaitSemaphores, const BackendSemaphore* signalSemaphores) override; void prepareSurfaceForStateUpdate(SkSurface* targetSurface, const MutableTextureState* newState) override; bool onAddRenderPass(const RenderPassDesc&, SkIRect renderPassBounds, const Texture* colorTexture, const Texture* resolveTexture, const Texture* depthStencilTexture, SkIRect viewport, const DrawPassList&) override; bool beginRenderPass(const RenderPassDesc&, SkIRect renderPassBounds, const Texture* colorTexture, const Texture* resolveTexture, const Texture* depthStencilTexture); void endRenderPass(); void addDrawPass(const DrawPass*); // Track descriptor changes for binding prior to draw calls void recordBufferBindingInfo(const BindBufferInfo& info, UniformSlot); // Either both arguments are non-null, or both must be null (to reset or handle just the // dstCopy intrinsic w/o requiring a DrawPass command). void recordTextureAndSamplerDescSet( const DrawPass*, const DrawPassCommands::BindTexturesAndSamplers*); void bindTextureSamplers(); void bindUniformBuffers(); void syncDescriptorSets(); void bindGraphicsPipeline(const GraphicsPipeline*); void setBlendConstants(float* blendConstants); void bindDrawBuffers(const BindBufferInfo& vertices, const BindBufferInfo& instances, const BindBufferInfo& indices, const BindBufferInfo& indirect); void bindVertexBuffers(const Buffer* vertexBuffer, size_t vertexOffset, const Buffer* instanceBuffer, size_t instanceOffset); void bindInputBuffer(const Buffer* buffer, VkDeviceSize offset, uint32_t binding); void bindIndexBuffer(const Buffer* indexBuffer, size_t offset); void bindIndirectBuffer(const Buffer* indirectBuffer, size_t offset); void setScissor(const Scissor&); void setScissor(const SkIRect&); void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount); void drawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount, unsigned int baseVertex); void drawInstanced(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount, unsigned int baseInstance, unsigned int instanceCount); void drawIndexedInstanced(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount, unsigned int baseVertex, unsigned int baseInstance, unsigned int instanceCount); void drawIndirect(PrimitiveType type); void drawIndexedIndirect(PrimitiveType type); // TODO: The virtuals in this class have not yet been implemented as we still haven't // implemented the objects they use. bool onAddComputePass(DispatchGroupSpan) override; bool onCopyBufferToBuffer(const Buffer* srcBuffer, size_t srcOffset, const Buffer* dstBuffer, size_t dstOffset, size_t size) override; bool onCopyTextureToBuffer(const Texture*, SkIRect srcRect, const Buffer*, size_t bufferOffset, size_t bufferRowBytes) override; bool onCopyBufferToTexture(const Buffer*, const Texture*, const BufferTextureCopyData* copyData, int count) override; bool onCopyTextureToTexture(const Texture* src, SkIRect srcRect, const Texture* dst, SkIPoint dstPoint, int mipLevel) override; bool pushConstants(VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* values); bool onSynchronizeBufferToCpu(const Buffer*, bool* outDidResultInWork) override; bool onClearBuffer(const Buffer*, size_t offset, size_t size) override; enum BarrierType { kBufferMemory_BarrierType, kImageMemory_BarrierType }; void pipelineBarrier(const Resource* resource, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, bool byRegion, BarrierType barrierType, void* barrier); void submitPipelineBarriers(bool forSelfDependency = false); // Update the intrinsic constant uniform buffer and binding to reflect the updated viewport. // The resource provider is responsible for finding a suitable buffer and managing its lifetime. bool updateIntrinsicUniforms(SkIRect viewport); bool loadMSAAFromResolve(const RenderPassDesc&, VulkanTexture& resolveTexture, SkISize dstDimensions, SkIRect nativeBounds); bool updateAndBindLoadMSAAInputAttachment(const VulkanTexture& resolveTexture); void updateBuffer(const VulkanBuffer* buffer, const void* data, size_t dataSize, size_t dstOffset = 0); void nextSubpass(); void setViewport(SkIRect viewport); VkCommandPool fPool; VkCommandBuffer fPrimaryCommandBuffer; const VulkanSharedContext* fSharedContext; VulkanResourceProvider* fResourceProvider; // begin() has been called, but not end() bool fActive = false; // Track whether there is currently an active render pass (beginRenderPass has been called, but // not endRenderPass) bool fActiveRenderPass = false; const VulkanGraphicsPipeline* fActiveGraphicsPipeline = nullptr; VkFence fSubmitFence = VK_NULL_HANDLE; // Current semaphores skia_private::STArray<1, VkSemaphore> fWaitSemaphores; skia_private::STArray<1, VkSemaphore> fSignalSemaphores; // Tracking of memory barriers so that we can submit them all in a batch together. skia_private::STArray<1, VkBufferMemoryBarrier> fBufferBarriers; skia_private::STArray<2, VkImageMemoryBarrier> fImageBarriers; bool fBarriersByRegion = false; VkPipelineStageFlags fSrcStageMask = 0; VkPipelineStageFlags fDstStageMask = 0; // Track whether certain descriptor sets need to be bound bool fBindUniformBuffers = false; bool fBindTextureSamplers = false; std::array fUniformBuffersToBind; VkDescriptorSet fTextureSamplerDescSetToBind = VK_NULL_HANDLE; int fNumTextureSamplers = 0; VkBuffer fBoundInputBuffers[VulkanGraphicsPipeline::kNumInputBuffers]; size_t fBoundInputBufferOffsets[VulkanGraphicsPipeline::kNumInputBuffers]; VkBuffer fBoundIndexBuffer = VK_NULL_HANDLE; VkBuffer fBoundIndirectBuffer = VK_NULL_HANDLE; size_t fBoundIndexBufferOffset = 0; size_t fBoundIndirectBufferOffset = 0; float fCachedBlendConstant[4]; class IntrinsicConstantsManager; std::unique_ptr fIntrinsicConstants; }; } // namespace skgpu::graphite #endif // skgpu_graphite_VulkanCommandBuffer_DEFINED