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