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