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/GrManagedResource.h" 13 #include "src/gpu/GrRefCnt.h" 14 #include "src/gpu/vk/GrVkGpu.h" 15 #include "src/gpu/vk/GrVkSemaphore.h" 16 #include "src/gpu/vk/GrVkUtil.h" 17 18 class GrVkFramebuffer; 19 class GrVkImage; 20 class GrVkPipeline; 21 class GrVkPipelineState; 22 class GrVkRenderPass; 23 class GrVkRenderTarget; 24 25 class GrVkCommandBuffer { 26 public: ~GrVkCommandBuffer()27 virtual ~GrVkCommandBuffer() {} 28 29 void invalidateState(); 30 31 //////////////////////////////////////////////////////////////////////////// 32 // CommandBuffer commands 33 //////////////////////////////////////////////////////////////////////////// 34 enum BarrierType { 35 kBufferMemory_BarrierType, 36 kImageMemory_BarrierType 37 }; 38 39 void pipelineBarrier(const GrVkGpu* gpu, 40 const GrManagedResource* resource, 41 VkPipelineStageFlags srcStageMask, 42 VkPipelineStageFlags dstStageMask, 43 bool byRegion, 44 BarrierType barrierType, 45 void* barrier); 46 47 void bindInputBuffer(GrVkGpu* gpu, uint32_t binding, sk_sp<const GrBuffer> buffer); 48 49 void bindIndexBuffer(GrVkGpu* gpu, sk_sp<const GrBuffer> buffer); 50 51 void bindPipeline(const GrVkGpu* gpu, sk_sp<const GrVkPipeline> pipeline); 52 53 void bindDescriptorSets(const GrVkGpu* gpu, 54 VkPipelineLayout layout, 55 uint32_t firstSet, 56 uint32_t setCount, 57 const VkDescriptorSet* descriptorSets, 58 uint32_t dynamicOffsetCount, 59 const uint32_t* dynamicOffsets); 60 61 void pushConstants(const GrVkGpu* gpu, VkPipelineLayout layout, 62 VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, 63 const void* values); 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 void drawIndirect(const GrVkGpu* gpu, 98 sk_sp<const GrBuffer> indirectBuffer, 99 VkDeviceSize offset, 100 uint32_t drawCount, 101 uint32_t stride); 102 103 void drawIndexedIndirect(const GrVkGpu* gpu, 104 sk_sp<const GrBuffer> indirectBuffer, 105 VkDeviceSize offset, 106 uint32_t drawCount, 107 uint32_t stride); 108 109 // Add ref-counted resource that will be tracked and released when this command buffer finishes 110 // execution addResource(sk_sp<const GrManagedResource> resource)111 void addResource(sk_sp<const GrManagedResource> resource) { 112 SkASSERT(resource); 113 fTrackedResources.push_back(std::move(resource)); 114 } addResource(const GrManagedResource * resource)115 void addResource(const GrManagedResource* resource) { 116 this->addResource(sk_ref_sp(resource)); 117 } 118 119 // Add ref-counted resource that will be tracked and released when this command buffer finishes 120 // execution. When it is released, it will signal that the resource can be recycled for reuse. addRecycledResource(gr_rp<const GrRecycledResource> resource)121 void addRecycledResource(gr_rp<const GrRecycledResource> resource) { 122 SkASSERT(resource); 123 fTrackedRecycledResources.push_back(std::move(resource)); 124 } 125 addRecycledResource(const GrRecycledResource * resource)126 void addRecycledResource(const GrRecycledResource* resource) { 127 this->addRecycledResource(gr_ref_rp<const GrRecycledResource>(resource)); 128 } 129 addGrBuffer(sk_sp<const GrBuffer> buffer)130 void addGrBuffer(sk_sp<const GrBuffer> buffer) { 131 fTrackedGpuBuffers.push_back(std::move(buffer)); 132 } 133 addGrSurface(sk_sp<const GrSurface> surface)134 void addGrSurface(sk_sp<const GrSurface> surface) { 135 fTrackedGpuSurfaces.push_back(std::move(surface)); 136 } 137 138 void releaseResources(); 139 140 void freeGPUData(const GrGpu* gpu, VkCommandPool pool) const; 141 hasWork()142 bool hasWork() const { return fHasWork; } 143 144 protected: 145 GrVkCommandBuffer(VkCommandBuffer cmdBuffer, bool isWrapped = false) fIsActive(isWrapped)146 : fIsActive(isWrapped) // All wrapped command buffers start as active 147 , fCmdBuffer(cmdBuffer) 148 , fIsWrapped(isWrapped) { 149 this->invalidateState(); 150 } 151 isWrapped()152 bool isWrapped() const { return fIsWrapped; } 153 154 void addingWork(const GrVkGpu* gpu); 155 156 void submitPipelineBarriers(const GrVkGpu* gpu, bool forSelfDependency = false); 157 158 private: 159 static constexpr int kInitialTrackedResourcesCount = 32; 160 161 protected: 162 template <typename T> using TrackedResourceArray = SkSTArray<kInitialTrackedResourcesCount, T>; 163 TrackedResourceArray<sk_sp<const GrManagedResource>> fTrackedResources; 164 TrackedResourceArray<gr_rp<const GrRecycledResource>> fTrackedRecycledResources; 165 SkSTArray<16, sk_sp<const GrBuffer>> fTrackedGpuBuffers; 166 SkSTArray<16, gr_cb<const GrSurface>> fTrackedGpuSurfaces; 167 168 // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add 169 // new commands to the buffer; 170 bool fIsActive; 171 bool fHasWork = false; 172 173 // Stores a pointer to the current active render pass (i.e. begin has been called but not 174 // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own 175 // the render pass. 176 const GrVkRenderPass* fActiveRenderPass = nullptr; 177 178 VkCommandBuffer fCmdBuffer; 179 onReleaseResources()180 virtual void onReleaseResources() {} 181 virtual void onFreeGPUData(const GrVkGpu* gpu) const = 0; 182 183 static constexpr uint32_t kMaxInputBuffers = 2; 184 185 VkBuffer fBoundInputBuffers[kMaxInputBuffers]; 186 VkBuffer fBoundIndexBuffer; 187 188 // Cached values used for dynamic state updates 189 VkViewport fCachedViewport; 190 VkRect2D fCachedScissor; 191 float fCachedBlendConstant[4]; 192 193 // Tracking of memory barriers so that we can submit them all in a batch together. 194 SkSTArray<1, VkBufferMemoryBarrier> fBufferBarriers; 195 SkSTArray<2, VkImageMemoryBarrier> fImageBarriers; 196 bool fBarriersByRegion = false; 197 VkPipelineStageFlags fSrcStageMask = 0; 198 VkPipelineStageFlags fDstStageMask = 0; 199 200 bool fIsWrapped; 201 }; 202 203 class GrVkSecondaryCommandBuffer; 204 205 class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer { 206 public: 207 ~GrVkPrimaryCommandBuffer() override; 208 209 static GrVkPrimaryCommandBuffer* Create(GrVkGpu* gpu, VkCommandPool cmdPool); 210 211 void begin(GrVkGpu* gpu); 212 void end(GrVkGpu* gpu, bool abandoningBuffer = false); 213 214 // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used 215 // in the render pass. 216 bool beginRenderPass(GrVkGpu* gpu, 217 const GrVkRenderPass*, 218 sk_sp<const GrVkFramebuffer>, 219 const VkClearValue clearValues[], 220 const GrSurface* target, 221 const SkIRect& bounds, 222 bool forSecondaryCB); 223 void endRenderPass(const GrVkGpu* gpu); 224 225 void nexSubpass(GrVkGpu* gpu, bool forSecondaryCB); 226 227 // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are 228 // currently inside a render pass that is compatible with the one used to create the 229 // SecondaryCommandBuffer. 230 void executeCommands(const GrVkGpu* gpu, 231 std::unique_ptr<GrVkSecondaryCommandBuffer> secondaryBuffer); 232 233 // Commands that only work outside of a render pass 234 void clearColorImage(const GrVkGpu* gpu, 235 GrVkImage* image, 236 const VkClearColorValue* color, 237 uint32_t subRangeCount, 238 const VkImageSubresourceRange* subRanges); 239 240 void clearDepthStencilImage(const GrVkGpu* gpu, 241 GrVkImage* image, 242 const VkClearDepthStencilValue* color, 243 uint32_t subRangeCount, 244 const VkImageSubresourceRange* subRanges); 245 246 void copyImage(const GrVkGpu* gpu, 247 GrVkImage* srcImage, 248 VkImageLayout srcLayout, 249 GrVkImage* dstImage, 250 VkImageLayout dstLayout, 251 uint32_t copyRegionCount, 252 const VkImageCopy* copyRegions); 253 254 void blitImage(const GrVkGpu* gpu, 255 const GrManagedResource* srcResource, 256 VkImage srcImage, 257 VkImageLayout srcLayout, 258 const GrManagedResource* dstResource, 259 VkImage dstImage, 260 VkImageLayout dstLayout, 261 uint32_t blitRegionCount, 262 const VkImageBlit* blitRegions, 263 VkFilter filter); 264 265 void blitImage(const GrVkGpu* gpu, 266 const GrVkImage& srcImage, 267 const GrVkImage& dstImage, 268 uint32_t blitRegionCount, 269 const VkImageBlit* blitRegions, 270 VkFilter filter); 271 272 void copyImageToBuffer(const GrVkGpu* gpu, 273 GrVkImage* srcImage, 274 VkImageLayout srcLayout, 275 sk_sp<GrGpuBuffer> dstBuffer, 276 uint32_t copyRegionCount, 277 const VkBufferImageCopy* copyRegions); 278 279 // All uses of copyBufferToImage are done with buffers from our staging manager. The staging 280 // manager will handle making sure the command buffer refs the buffer. Thus we just pass in the 281 // raw VkBuffer here and don't worry about refs. 282 void copyBufferToImage(const GrVkGpu* gpu, 283 VkBuffer srcBuffer, 284 GrVkImage* dstImage, 285 VkImageLayout dstLayout, 286 uint32_t copyRegionCount, 287 const VkBufferImageCopy* copyRegions); 288 289 void copyBuffer(GrVkGpu* gpu, 290 sk_sp<GrGpuBuffer> srcBuffer, 291 sk_sp<GrGpuBuffer> dstBuffer, 292 uint32_t regionCount, 293 const VkBufferCopy* regions); 294 295 void updateBuffer(GrVkGpu* gpu, 296 sk_sp<GrVkBuffer> dstBuffer, 297 VkDeviceSize dstOffset, 298 VkDeviceSize dataSize, 299 const void* data); 300 301 void resolveImage(GrVkGpu* gpu, 302 const GrVkImage& srcImage, 303 const GrVkImage& dstImage, 304 uint32_t regionCount, 305 const VkImageResolve* regions); 306 307 bool submitToQueue(GrVkGpu* gpu, VkQueue queue, 308 SkTArray<GrVkSemaphore::Resource*>& signalSemaphores, 309 SkTArray<GrVkSemaphore::Resource*>& waitSemaphores); 310 311 void forceSync(GrVkGpu* gpu); 312 313 bool finished(GrVkGpu* gpu); 314 315 void addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc); 316 callFinishedProcs()317 void callFinishedProcs() { 318 fFinishedProcs.reset(); 319 } 320 321 void recycleSecondaryCommandBuffers(GrVkCommandPool* cmdPool); 322 323 private: GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer)324 explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer) 325 : INHERITED(cmdBuffer) 326 , fSubmitFence(VK_NULL_HANDLE) {} 327 328 void onFreeGPUData(const GrVkGpu* gpu) const override; 329 330 void onReleaseResources() override; 331 332 SkTArray<std::unique_ptr<GrVkSecondaryCommandBuffer>, true> fSecondaryCommandBuffers; 333 VkFence fSubmitFence; 334 SkTArray<sk_sp<GrRefCntedCallback>> fFinishedProcs; 335 336 using INHERITED = GrVkCommandBuffer; 337 }; 338 339 class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer { 340 public: 341 static GrVkSecondaryCommandBuffer* Create(GrVkGpu* gpu, GrVkCommandPool* cmdPool); 342 // Used for wrapping an external secondary command buffer. 343 static GrVkSecondaryCommandBuffer* Create(VkCommandBuffer externalSecondaryCB, 344 const GrVkRenderPass* externalRenderPass); 345 346 void begin(GrVkGpu* gpu, const GrVkFramebuffer* framebuffer, 347 const GrVkRenderPass* compatibleRenderPass); 348 void end(GrVkGpu* gpu); 349 350 void recycle(GrVkCommandPool* cmdPool); 351 vkCommandBuffer()352 VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; } 353 354 private: GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer,const GrVkRenderPass * externalRenderPass)355 explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, 356 const GrVkRenderPass* externalRenderPass) 357 : INHERITED(cmdBuffer, SkToBool(externalRenderPass)) { 358 fActiveRenderPass = externalRenderPass; 359 } 360 onFreeGPUData(const GrVkGpu * gpu)361 void onFreeGPUData(const GrVkGpu* gpu) const override {} 362 363 // Used for accessing fIsActive (on GrVkCommandBuffer) 364 friend class GrVkPrimaryCommandBuffer; 365 366 using INHERITED = GrVkCommandBuffer; 367 }; 368 369 #endif 370