1 /* 2 * Copyright 2015 Google Inc. 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 GrVkCommandBuffer_DEFINED 9 #define GrVkCommandBuffer_DEFINED 10 11 #include "include/gpu/vk/GrVkTypes.h" 12 #include "src/gpu/vk/GrVkGpu.h" 13 #include "src/gpu/vk/GrVkResource.h" 14 #include "src/gpu/vk/GrVkSemaphore.h" 15 #include "src/gpu/vk/GrVkUtil.h" 16 17 class GrVkBuffer; 18 class GrVkFramebuffer; 19 class GrVkIndexBuffer; 20 class GrVkImage; 21 class GrVkPipeline; 22 class GrVkPipelineState; 23 class GrVkRenderPass; 24 class GrVkRenderTarget; 25 class GrVkTransferBuffer; 26 class GrVkVertexBuffer; 27 28 class GrVkCommandBuffer { 29 public: ~GrVkCommandBuffer()30 virtual ~GrVkCommandBuffer() {} 31 32 void invalidateState(); 33 34 //////////////////////////////////////////////////////////////////////////// 35 // CommandBuffer commands 36 //////////////////////////////////////////////////////////////////////////// 37 enum BarrierType { 38 kBufferMemory_BarrierType, 39 kImageMemory_BarrierType 40 }; 41 42 void pipelineBarrier(const GrVkGpu* gpu, 43 const GrVkResource* resource, 44 VkPipelineStageFlags srcStageMask, 45 VkPipelineStageFlags dstStageMask, 46 bool byRegion, 47 BarrierType barrierType, 48 void* barrier); 49 50 void bindInputBuffer(GrVkGpu* gpu, uint32_t binding, const GrVkVertexBuffer* vbuffer); 51 52 void bindIndexBuffer(GrVkGpu* gpu, const GrVkIndexBuffer* ibuffer); 53 54 void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline); 55 56 void bindDescriptorSets(const GrVkGpu* gpu, 57 GrVkPipelineState*, 58 VkPipelineLayout layout, 59 uint32_t firstSet, 60 uint32_t setCount, 61 const VkDescriptorSet* descriptorSets, 62 uint32_t dynamicOffsetCount, 63 const uint32_t* dynamicOffsets); 64 commandPool()65 GrVkCommandPool* commandPool() { return fCmdPool; } 66 67 void setViewport(const GrVkGpu* gpu, 68 uint32_t firstViewport, 69 uint32_t viewportCount, 70 const VkViewport* viewports); 71 72 void setScissor(const GrVkGpu* gpu, 73 uint32_t firstScissor, 74 uint32_t scissorCount, 75 const VkRect2D* scissors); 76 77 void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]); 78 79 // Commands that only work inside of a render pass 80 void clearAttachments(const GrVkGpu* gpu, 81 int numAttachments, 82 const VkClearAttachment* attachments, 83 int numRects, 84 const VkClearRect* clearRects); 85 86 void drawIndexed(const GrVkGpu* gpu, 87 uint32_t indexCount, 88 uint32_t instanceCount, 89 uint32_t firstIndex, 90 int32_t vertexOffset, 91 uint32_t firstInstance); 92 93 void draw(const GrVkGpu* gpu, 94 uint32_t vertexCount, 95 uint32_t instanceCount, 96 uint32_t firstVertex, 97 uint32_t firstInstance); 98 99 // Add ref-counted resource that will be tracked and released when this command buffer finishes 100 // execution addResource(const GrVkResource * resource)101 void addResource(const GrVkResource* resource) { 102 resource->ref(); 103 resource->notifyAddedToCommandBuffer(); 104 fTrackedResources.append(1, &resource); 105 } 106 107 // Add ref-counted resource that will be tracked and released when this command buffer finishes 108 // execution. When it is released, it will signal that the resource can be recycled for reuse. addRecycledResource(const GrVkRecycledResource * resource)109 void addRecycledResource(const GrVkRecycledResource* resource) { 110 resource->ref(); 111 resource->notifyAddedToCommandBuffer(); 112 fTrackedRecycledResources.append(1, &resource); 113 } 114 115 void releaseResources(GrVkGpu* gpu); 116 117 void freeGPUData(GrVkGpu* gpu) const; 118 void abandonGPUData() const; 119 hasWork()120 bool hasWork() const { return fHasWork; } 121 122 protected: 123 GrVkCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool, 124 const GrVkRenderPass* rp = nullptr) fIsActive(false)125 : fIsActive(false) 126 , fActiveRenderPass(rp) 127 , fCmdBuffer(cmdBuffer) 128 , fCmdPool(cmdPool) 129 , fNumResets(0) { 130 fTrackedResources.setReserve(kInitialTrackedResourcesCount); 131 fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount); 132 this->invalidateState(); 133 } 134 isWrapped()135 bool isWrapped() const { return fCmdPool == nullptr; } 136 137 void addingWork(const GrVkGpu* gpu); 138 139 void submitPipelineBarriers(const GrVkGpu* gpu); 140 141 SkTDArray<const GrVkResource*> fTrackedResources; 142 SkTDArray<const GrVkRecycledResource*> fTrackedRecycledResources; 143 144 // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add 145 // new commands to the buffer; 146 bool fIsActive; 147 bool fHasWork = false; 148 149 // Stores a pointer to the current active render pass (i.e. begin has been called but not 150 // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own 151 // the render pass. 152 const GrVkRenderPass* fActiveRenderPass; 153 154 VkCommandBuffer fCmdBuffer; 155 156 // Raw pointer, not refcounted. The command pool controls the command buffer's lifespan, so 157 // it's guaranteed to outlive us. 158 GrVkCommandPool* fCmdPool; 159 160 private: 161 static const int kInitialTrackedResourcesCount = 32; 162 onReleaseResources(GrVkGpu * gpu)163 virtual void onReleaseResources(GrVkGpu* gpu) {} 164 virtual void onFreeGPUData(GrVkGpu* gpu) const = 0; 165 virtual void onAbandonGPUData() const = 0; 166 167 static constexpr uint32_t kMaxInputBuffers = 2; 168 169 VkBuffer fBoundInputBuffers[kMaxInputBuffers]; 170 VkBuffer fBoundIndexBuffer; 171 172 // When resetting the command buffer, we remove the tracked resources from their arrays, and 173 // we prefer to not free all the memory every time so usually we just rewind. However, to avoid 174 // all arrays growing to the max size, after so many resets we'll do a full reset of the tracked 175 // resource arrays. 176 static const int kNumRewindResetsBeforeFullReset = 8; 177 int fNumResets; 178 179 // Cached values used for dynamic state updates 180 VkViewport fCachedViewport; 181 VkRect2D fCachedScissor; 182 float fCachedBlendConstant[4]; 183 184 #ifdef SK_DEBUG 185 mutable bool fResourcesReleased = false; 186 #endif 187 // Tracking of memory barriers so that we can submit them all in a batch together. 188 SkSTArray<4, VkBufferMemoryBarrier> fBufferBarriers; 189 SkSTArray<1, VkImageMemoryBarrier> fImageBarriers; 190 bool fBarriersByRegion = false; 191 VkPipelineStageFlags fSrcStageMask = 0; 192 VkPipelineStageFlags fDstStageMask = 0; 193 }; 194 195 class GrVkSecondaryCommandBuffer; 196 197 class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer { 198 public: 199 ~GrVkPrimaryCommandBuffer() override; 200 201 static GrVkPrimaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool); 202 203 void begin(const GrVkGpu* gpu); 204 void end(GrVkGpu* gpu); 205 206 // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used 207 // in the render pass. 208 void beginRenderPass(const GrVkGpu* gpu, 209 const GrVkRenderPass* renderPass, 210 const VkClearValue clearValues[], 211 const GrVkRenderTarget& target, 212 const SkIRect& bounds, 213 bool forSecondaryCB); 214 void endRenderPass(const GrVkGpu* gpu); 215 216 // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are 217 // currently inside a render pass that is compatible with the one used to create the 218 // SecondaryCommandBuffer. 219 void executeCommands(const GrVkGpu* gpu, 220 std::unique_ptr<GrVkSecondaryCommandBuffer> secondaryBuffer); 221 222 // Commands that only work outside of a render pass 223 void clearColorImage(const GrVkGpu* gpu, 224 GrVkImage* image, 225 const VkClearColorValue* color, 226 uint32_t subRangeCount, 227 const VkImageSubresourceRange* subRanges); 228 229 void clearDepthStencilImage(const GrVkGpu* gpu, 230 GrVkImage* image, 231 const VkClearDepthStencilValue* color, 232 uint32_t subRangeCount, 233 const VkImageSubresourceRange* subRanges); 234 235 void copyImage(const GrVkGpu* gpu, 236 GrVkImage* srcImage, 237 VkImageLayout srcLayout, 238 GrVkImage* dstImage, 239 VkImageLayout dstLayout, 240 uint32_t copyRegionCount, 241 const VkImageCopy* copyRegions); 242 243 void blitImage(const GrVkGpu* gpu, 244 const GrVkResource* srcResource, 245 VkImage srcImage, 246 VkImageLayout srcLayout, 247 const GrVkResource* dstResource, 248 VkImage dstImage, 249 VkImageLayout dstLayout, 250 uint32_t blitRegionCount, 251 const VkImageBlit* blitRegions, 252 VkFilter filter); 253 254 void blitImage(const GrVkGpu* gpu, 255 const GrVkImage& srcImage, 256 const GrVkImage& dstImage, 257 uint32_t blitRegionCount, 258 const VkImageBlit* blitRegions, 259 VkFilter filter); 260 261 void copyImageToBuffer(const GrVkGpu* gpu, 262 GrVkImage* srcImage, 263 VkImageLayout srcLayout, 264 GrVkTransferBuffer* dstBuffer, 265 uint32_t copyRegionCount, 266 const VkBufferImageCopy* copyRegions); 267 268 void copyBufferToImage(const GrVkGpu* gpu, 269 GrVkTransferBuffer* srcBuffer, 270 GrVkImage* dstImage, 271 VkImageLayout dstLayout, 272 uint32_t copyRegionCount, 273 const VkBufferImageCopy* copyRegions); 274 275 void copyBuffer(GrVkGpu* gpu, 276 GrVkBuffer* srcBuffer, 277 GrVkBuffer* dstBuffer, 278 uint32_t regionCount, 279 const VkBufferCopy* regions); 280 281 void updateBuffer(GrVkGpu* gpu, 282 GrVkBuffer* dstBuffer, 283 VkDeviceSize dstOffset, 284 VkDeviceSize dataSize, 285 const void* data); 286 287 void resolveImage(GrVkGpu* gpu, 288 const GrVkImage& srcImage, 289 const GrVkImage& dstImage, 290 uint32_t regionCount, 291 const VkImageResolve* regions); 292 293 void submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync, 294 SkTArray<GrVkSemaphore::Resource*>& signalSemaphores, 295 SkTArray<GrVkSemaphore::Resource*>& waitSemaphores); 296 bool finished(const GrVkGpu* gpu); 297 298 void addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc); 299 300 void recycleSecondaryCommandBuffers(GrVkGpu* gpu); 301 302 private: GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer,GrVkCommandPool * cmdPool)303 explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool) 304 : INHERITED(cmdBuffer, cmdPool) 305 , fSubmitFence(VK_NULL_HANDLE) {} 306 307 void onFreeGPUData(GrVkGpu* gpu) const override; 308 309 void onAbandonGPUData() const override; 310 311 void onReleaseResources(GrVkGpu* gpu) override; 312 313 SkTArray<std::unique_ptr<GrVkSecondaryCommandBuffer>, true> fSecondaryCommandBuffers; 314 VkFence fSubmitFence; 315 SkTArray<sk_sp<GrRefCntedCallback>> fFinishedProcs; 316 317 typedef GrVkCommandBuffer INHERITED; 318 }; 319 320 class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer { 321 public: 322 static GrVkSecondaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool); 323 // Used for wrapping an external secondary command buffer. 324 static GrVkSecondaryCommandBuffer* Create(VkCommandBuffer externalSecondaryCB); 325 326 void begin(const GrVkGpu* gpu, const GrVkFramebuffer* framebuffer, 327 const GrVkRenderPass* compatibleRenderPass); 328 void end(GrVkGpu* gpu); 329 330 void recycle(GrVkGpu* gpu); 331 vkCommandBuffer()332 VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; } 333 334 private: GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer,GrVkCommandPool * cmdPool)335 explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool) 336 : INHERITED(cmdBuffer, cmdPool) {} 337 onFreeGPUData(GrVkGpu * gpu)338 void onFreeGPUData(GrVkGpu* gpu) const override {} 339 onAbandonGPUData()340 void onAbandonGPUData() const override {} 341 342 friend class GrVkPrimaryCommandBuffer; 343 344 typedef GrVkCommandBuffer INHERITED; 345 }; 346 347 #endif 348