| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrVkCommandBuffer_DEFINED |
| #define GrVkCommandBuffer_DEFINED |
| |
| #include "include/gpu/vk/GrVkTypes.h" |
| #include "src/gpu/GrManagedResource.h" |
| #include "src/gpu/vk/GrVkGpu.h" |
| #include "src/gpu/vk/GrVkSemaphore.h" |
| #include "src/gpu/vk/GrVkUtil.h" |
| |
| class GrVkBuffer; |
| class GrVkFramebuffer; |
| class GrVkImage; |
| class GrVkMeshBuffer; |
| class GrVkPipeline; |
| class GrVkPipelineState; |
| class GrVkRenderPass; |
| class GrVkRenderTarget; |
| class GrVkTransferBuffer; |
| |
| class GrVkCommandBuffer { |
| public: |
| virtual ~GrVkCommandBuffer() {} |
| |
| void invalidateState(); |
| |
| //////////////////////////////////////////////////////////////////////////// |
| // CommandBuffer commands |
| //////////////////////////////////////////////////////////////////////////// |
| enum BarrierType { |
| kBufferMemory_BarrierType, |
| kImageMemory_BarrierType |
| }; |
| |
| void pipelineBarrier(const GrVkGpu* gpu, |
| const GrManagedResource* resource, |
| VkPipelineStageFlags srcStageMask, |
| VkPipelineStageFlags dstStageMask, |
| bool byRegion, |
| BarrierType barrierType, |
| void* barrier); |
| |
| void bindInputBuffer(GrVkGpu* gpu, uint32_t binding, sk_sp<const GrBuffer> buffer); |
| |
| void bindIndexBuffer(GrVkGpu* gpu, sk_sp<const GrBuffer> buffer); |
| |
| void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline); |
| |
| void bindDescriptorSets(const GrVkGpu* gpu, |
| GrVkPipelineState*, |
| VkPipelineLayout layout, |
| uint32_t firstSet, |
| uint32_t setCount, |
| const VkDescriptorSet* descriptorSets, |
| uint32_t dynamicOffsetCount, |
| const uint32_t* dynamicOffsets); |
| |
| void setViewport(const GrVkGpu* gpu, |
| uint32_t firstViewport, |
| uint32_t viewportCount, |
| const VkViewport* viewports); |
| |
| void setScissor(const GrVkGpu* gpu, |
| uint32_t firstScissor, |
| uint32_t scissorCount, |
| const VkRect2D* scissors); |
| |
| void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]); |
| |
| // Commands that only work inside of a render pass |
| void clearAttachments(const GrVkGpu* gpu, |
| int numAttachments, |
| const VkClearAttachment* attachments, |
| int numRects, |
| const VkClearRect* clearRects); |
| |
| void drawIndexed(const GrVkGpu* gpu, |
| uint32_t indexCount, |
| uint32_t instanceCount, |
| uint32_t firstIndex, |
| int32_t vertexOffset, |
| uint32_t firstInstance); |
| |
| void draw(const GrVkGpu* gpu, |
| uint32_t vertexCount, |
| uint32_t instanceCount, |
| uint32_t firstVertex, |
| uint32_t firstInstance); |
| |
| void drawIndirect(const GrVkGpu* gpu, |
| const GrVkMeshBuffer* indirectBuffer, |
| VkDeviceSize offset, |
| uint32_t drawCount, |
| uint32_t stride); |
| |
| void drawIndexedIndirect(const GrVkGpu* gpu, |
| const GrVkMeshBuffer* indirectBuffer, |
| VkDeviceSize offset, |
| uint32_t drawCount, |
| uint32_t stride); |
| |
| // Add ref-counted resource that will be tracked and released when this command buffer finishes |
| // execution |
| void addResource(const GrManagedResource* resource) { |
| SkASSERT(resource); |
| resource->ref(); |
| resource->notifyQueuedForWorkOnGpu(); |
| fTrackedResources.append(1, &resource); |
| } |
| |
| // Add ref-counted resource that will be tracked and released when this command buffer finishes |
| // execution. When it is released, it will signal that the resource can be recycled for reuse. |
| void addRecycledResource(const GrRecycledResource* resource) { |
| resource->ref(); |
| resource->notifyQueuedForWorkOnGpu(); |
| fTrackedRecycledResources.append(1, &resource); |
| } |
| |
| void addGrBuffer(sk_sp<const GrBuffer> buffer) { |
| fTrackedGpuBuffers.push_back(std::move(buffer)); |
| } |
| |
| void releaseResources(); |
| |
| void freeGPUData(const GrGpu* gpu, VkCommandPool pool) const; |
| |
| bool hasWork() const { return fHasWork; } |
| |
| protected: |
| GrVkCommandBuffer(VkCommandBuffer cmdBuffer, bool isWrapped = false) |
| : fCmdBuffer(cmdBuffer) |
| , fIsWrapped(isWrapped) { |
| fTrackedResources.setReserve(kInitialTrackedResourcesCount); |
| fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount); |
| this->invalidateState(); |
| } |
| |
| bool isWrapped() const { return fIsWrapped; } |
| |
| void addingWork(const GrVkGpu* gpu); |
| |
| void submitPipelineBarriers(const GrVkGpu* gpu, bool forSelfDependency = false); |
| |
| SkTDArray<const GrManagedResource*> fTrackedResources; |
| SkTDArray<const GrRecycledResource*> fTrackedRecycledResources; |
| SkSTArray<16, sk_sp<const GrBuffer>> fTrackedGpuBuffers; |
| |
| // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add |
| // new commands to the buffer; |
| bool fIsActive = false; |
| bool fHasWork = false; |
| |
| // Stores a pointer to the current active render pass (i.e. begin has been called but not |
| // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own |
| // the render pass. |
| const GrVkRenderPass* fActiveRenderPass = nullptr; |
| |
| VkCommandBuffer fCmdBuffer; |
| |
| private: |
| static const int kInitialTrackedResourcesCount = 32; |
| |
| virtual void onReleaseResources() {} |
| virtual void onFreeGPUData(const GrVkGpu* gpu) const = 0; |
| |
| static constexpr uint32_t kMaxInputBuffers = 2; |
| |
| VkBuffer fBoundInputBuffers[kMaxInputBuffers]; |
| VkBuffer fBoundIndexBuffer; |
| |
| // When resetting the command buffer, we remove the tracked resources from their arrays, and |
| // we prefer to not free all the memory every time so usually we just rewind. However, to avoid |
| // all arrays growing to the max size, after so many resets we'll do a full reset of the tracked |
| // resource arrays. |
| static const int kNumRewindResetsBeforeFullReset = 8; |
| int fNumResets = 0; |
| |
| // Cached values used for dynamic state updates |
| VkViewport fCachedViewport; |
| VkRect2D fCachedScissor; |
| float fCachedBlendConstant[4]; |
| |
| // Tracking of memory barriers so that we can submit them all in a batch together. |
| SkSTArray<4, VkBufferMemoryBarrier> fBufferBarriers; |
| SkSTArray<1, VkImageMemoryBarrier> fImageBarriers; |
| bool fBarriersByRegion = false; |
| VkPipelineStageFlags fSrcStageMask = 0; |
| VkPipelineStageFlags fDstStageMask = 0; |
| |
| bool fIsWrapped; |
| }; |
| |
| class GrVkSecondaryCommandBuffer; |
| |
| class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer { |
| public: |
| ~GrVkPrimaryCommandBuffer() override; |
| |
| static GrVkPrimaryCommandBuffer* Create(GrVkGpu* gpu, VkCommandPool cmdPool); |
| |
| void begin(GrVkGpu* gpu); |
| void end(GrVkGpu* gpu); |
| |
| // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used |
| // in the render pass. |
| bool beginRenderPass(GrVkGpu* gpu, |
| const GrVkRenderPass* renderPass, |
| const VkClearValue clearValues[], |
| GrVkRenderTarget* target, |
| const SkIRect& bounds, |
| bool forSecondaryCB); |
| void endRenderPass(const GrVkGpu* gpu); |
| |
| // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are |
| // currently inside a render pass that is compatible with the one used to create the |
| // SecondaryCommandBuffer. |
| void executeCommands(const GrVkGpu* gpu, |
| std::unique_ptr<GrVkSecondaryCommandBuffer> secondaryBuffer); |
| |
| // Commands that only work outside of a render pass |
| void clearColorImage(const GrVkGpu* gpu, |
| GrVkImage* image, |
| const VkClearColorValue* color, |
| uint32_t subRangeCount, |
| const VkImageSubresourceRange* subRanges); |
| |
| void clearDepthStencilImage(const GrVkGpu* gpu, |
| GrVkImage* image, |
| const VkClearDepthStencilValue* color, |
| uint32_t subRangeCount, |
| const VkImageSubresourceRange* subRanges); |
| |
| void copyImage(const GrVkGpu* gpu, |
| GrVkImage* srcImage, |
| VkImageLayout srcLayout, |
| GrVkImage* dstImage, |
| VkImageLayout dstLayout, |
| uint32_t copyRegionCount, |
| const VkImageCopy* copyRegions); |
| |
| void blitImage(const GrVkGpu* gpu, |
| const GrManagedResource* srcResource, |
| VkImage srcImage, |
| VkImageLayout srcLayout, |
| const GrManagedResource* dstResource, |
| VkImage dstImage, |
| VkImageLayout dstLayout, |
| uint32_t blitRegionCount, |
| const VkImageBlit* blitRegions, |
| VkFilter filter); |
| |
| void blitImage(const GrVkGpu* gpu, |
| const GrVkImage& srcImage, |
| const GrVkImage& dstImage, |
| uint32_t blitRegionCount, |
| const VkImageBlit* blitRegions, |
| VkFilter filter); |
| |
| void copyImageToBuffer(const GrVkGpu* gpu, |
| GrVkImage* srcImage, |
| VkImageLayout srcLayout, |
| GrVkTransferBuffer* dstBuffer, |
| uint32_t copyRegionCount, |
| const VkBufferImageCopy* copyRegions); |
| |
| void copyBufferToImage(const GrVkGpu* gpu, |
| GrVkTransferBuffer* srcBuffer, |
| GrVkImage* dstImage, |
| VkImageLayout dstLayout, |
| uint32_t copyRegionCount, |
| const VkBufferImageCopy* copyRegions); |
| |
| void copyBuffer(GrVkGpu* gpu, |
| GrVkBuffer* srcBuffer, |
| GrVkBuffer* dstBuffer, |
| uint32_t regionCount, |
| const VkBufferCopy* regions); |
| |
| void updateBuffer(GrVkGpu* gpu, |
| GrVkBuffer* dstBuffer, |
| VkDeviceSize dstOffset, |
| VkDeviceSize dataSize, |
| const void* data); |
| |
| void resolveImage(GrVkGpu* gpu, |
| const GrVkImage& srcImage, |
| const GrVkImage& dstImage, |
| uint32_t regionCount, |
| const VkImageResolve* regions); |
| |
| bool submitToQueue(GrVkGpu* gpu, VkQueue queue, |
| SkTArray<GrVkSemaphore::Resource*>& signalSemaphores, |
| SkTArray<GrVkSemaphore::Resource*>& waitSemaphores); |
| |
| void forceSync(GrVkGpu* gpu); |
| |
| bool finished(GrVkGpu* gpu); |
| |
| void addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc); |
| |
| void callFinishedProcs() { |
| fFinishedProcs.reset(); |
| } |
| |
| void recycleSecondaryCommandBuffers(GrVkCommandPool* cmdPool); |
| |
| private: |
| explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer) |
| : INHERITED(cmdBuffer) |
| , fSubmitFence(VK_NULL_HANDLE) {} |
| |
| void onFreeGPUData(const GrVkGpu* gpu) const override; |
| |
| void onReleaseResources() override; |
| |
| SkTArray<std::unique_ptr<GrVkSecondaryCommandBuffer>, true> fSecondaryCommandBuffers; |
| VkFence fSubmitFence; |
| SkTArray<sk_sp<GrRefCntedCallback>> fFinishedProcs; |
| |
| using INHERITED = GrVkCommandBuffer; |
| }; |
| |
| class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer { |
| public: |
| static GrVkSecondaryCommandBuffer* Create(GrVkGpu* gpu, GrVkCommandPool* cmdPool); |
| // Used for wrapping an external secondary command buffer. |
| static GrVkSecondaryCommandBuffer* Create(VkCommandBuffer externalSecondaryCB); |
| |
| void begin(GrVkGpu* gpu, const GrVkFramebuffer* framebuffer, |
| const GrVkRenderPass* compatibleRenderPass); |
| void end(GrVkGpu* gpu); |
| |
| void recycle(GrVkCommandPool* cmdPool); |
| |
| VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; } |
| |
| private: |
| explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, bool isWrapped) |
| : INHERITED(cmdBuffer, isWrapped) {} |
| |
| void onFreeGPUData(const GrVkGpu* gpu) const override {} |
| |
| // Used for accessing fIsActive (on GrVkCommandBuffer) |
| friend class GrVkPrimaryCommandBuffer; |
| |
| using INHERITED = GrVkCommandBuffer; |
| }; |
| |
| #endif |