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