blob: 23eb5922ec3b5f21d081f14f594f850c98437f83 [file] [log] [blame]
Greg Daniel164a9f02016-02-22 09:56:40 -05001/*
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"
Greg Daniel164a9f02016-02-22 09:56:40 -050012#include "GrVkResource.h"
Greg Daniel6be35232017-03-01 17:01:09 -050013#include "GrVkSemaphore.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050014#include "GrVkUtil.h"
Greg Daniel487132b2018-12-20 14:09:36 -050015#include "vk/GrVkTypes.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050016
Greg Daniel6ecc9112017-06-16 16:17:03 +000017class GrVkBuffer;
egdaniel9a6cf802016-06-08 08:22:05 -070018class GrVkFramebuffer;
Greg Daniel6ecc9112017-06-16 16:17:03 +000019class GrVkIndexBuffer;
20class GrVkImage;
egdaniel470d77a2016-03-18 12:50:27 -070021class GrVkPipeline;
Greg Daniel6ecc9112017-06-16 16:17:03 +000022class GrVkPipelineState;
Greg Daniel164a9f02016-02-22 09:56:40 -050023class GrVkRenderPass;
24class GrVkRenderTarget;
25class GrVkTransferBuffer;
Greg Daniel6ecc9112017-06-16 16:17:03 +000026class GrVkVertexBuffer;
Greg Daniel164a9f02016-02-22 09:56:40 -050027
28class GrVkCommandBuffer : public GrVkResource {
29public:
Greg Daniel164a9f02016-02-22 09:56:40 -050030 void invalidateState();
31
Greg Daniel164a9f02016-02-22 09:56:40 -050032 ////////////////////////////////////////////////////////////////////////////
Greg Daniel164a9f02016-02-22 09:56:40 -050033 // CommandBuffer commands
34 ////////////////////////////////////////////////////////////////////////////
35 enum BarrierType {
36 kMemory_BarrierType,
37 kBufferMemory_BarrierType,
38 kImageMemory_BarrierType
39 };
40
41 void pipelineBarrier(const GrVkGpu* gpu,
Greg Daniel59dc1482019-02-22 10:46:38 -050042 const GrVkResource* resource,
Greg Daniel164a9f02016-02-22 09:56:40 -050043 VkPipelineStageFlags srcStageMask,
44 VkPipelineStageFlags dstStageMask,
45 bool byRegion,
46 BarrierType barrierType,
Greg Daniel59dc1482019-02-22 10:46:38 -050047 void* barrier);
Greg Daniel164a9f02016-02-22 09:56:40 -050048
Greg Daniel6ecc9112017-06-16 16:17:03 +000049 void bindInputBuffer(GrVkGpu* gpu, uint32_t binding, const GrVkVertexBuffer* vbuffer);
Chris Dalton1d616352017-05-31 12:51:23 -060050
Greg Daniel6ecc9112017-06-16 16:17:03 +000051 void bindIndexBuffer(GrVkGpu* gpu, const GrVkIndexBuffer* ibuffer);
Greg Daniel164a9f02016-02-22 09:56:40 -050052
egdaniel58a8d922016-04-21 08:03:10 -070053 void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline);
54
Greg Daniel164a9f02016-02-22 09:56:40 -050055 void bindDescriptorSets(const GrVkGpu* gpu,
egdaniel22281c12016-03-23 13:49:40 -070056 GrVkPipelineState*,
Greg Daniel7d918fd2018-06-19 15:22:01 -040057 GrVkPipelineLayout* layout,
Greg Daniel164a9f02016-02-22 09:56:40 -050058 uint32_t firstSet,
59 uint32_t setCount,
60 const VkDescriptorSet* descriptorSets,
61 uint32_t dynamicOffsetCount,
62 const uint32_t* dynamicOffsets);
63
egdanielbc9b2962016-09-27 08:00:53 -070064 void bindDescriptorSets(const GrVkGpu* gpu,
65 const SkTArray<const GrVkRecycledResource*>&,
66 const SkTArray<const GrVkResource*>&,
Greg Daniel7d918fd2018-06-19 15:22:01 -040067 GrVkPipelineLayout* layout,
egdanielbc9b2962016-09-27 08:00:53 -070068 uint32_t firstSet,
69 uint32_t setCount,
70 const VkDescriptorSet* descriptorSets,
71 uint32_t dynamicOffsetCount,
72 const uint32_t* dynamicOffsets);
73
Ethan Nicholas8e265a72018-12-12 16:22:40 -050074 GrVkCommandPool* commandPool() { return fCmdPool; }
75
egdaniel470d77a2016-03-18 12:50:27 -070076 void setViewport(const GrVkGpu* gpu,
77 uint32_t firstViewport,
78 uint32_t viewportCount,
79 const VkViewport* viewports);
80
81 void setScissor(const GrVkGpu* gpu,
82 uint32_t firstScissor,
83 uint32_t scissorCount,
84 const VkRect2D* scissors);
85
86 void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]);
87
egdaniel9a6cf802016-06-08 08:22:05 -070088 // Commands that only work inside of a render pass
89 void clearAttachments(const GrVkGpu* gpu,
90 int numAttachments,
91 const VkClearAttachment* attachments,
92 int numRects,
93 const VkClearRect* clearRects) const;
94
95 void drawIndexed(const GrVkGpu* gpu,
96 uint32_t indexCount,
97 uint32_t instanceCount,
98 uint32_t firstIndex,
99 int32_t vertexOffset,
100 uint32_t firstInstance) const;
101
102 void draw(const GrVkGpu* gpu,
103 uint32_t vertexCount,
104 uint32_t instanceCount,
105 uint32_t firstVertex,
106 uint32_t firstInstance) const;
107
Greg Daniel7d918fd2018-06-19 15:22:01 -0400108 // Add ref-counted resource that will be tracked and released when this command buffer finishes
109 // execution
egdaniel9a6cf802016-06-08 08:22:05 -0700110 void addResource(const GrVkResource* resource) {
111 resource->ref();
Brian Salomon614c1a82018-12-19 15:42:06 -0500112 resource->notifyAddedToCommandBuffer();
egdaniel594739c2016-09-20 12:39:25 -0700113 fTrackedResources.append(1, &resource);
egdaniel9a6cf802016-06-08 08:22:05 -0700114 }
115
egdanielc1be9bc2016-07-20 08:33:00 -0700116 // Add ref-counted resource that will be tracked and released when this command buffer finishes
117 // execution. When it is released, it will signal that the resource can be recycled for reuse.
118 void addRecycledResource(const GrVkRecycledResource* resource) {
119 resource->ref();
Brian Salomon614c1a82018-12-19 15:42:06 -0500120 resource->notifyAddedToCommandBuffer();
egdaniel594739c2016-09-20 12:39:25 -0700121 fTrackedRecycledResources.append(1, &resource);
egdanielc1be9bc2016-07-20 08:33:00 -0700122 }
123
Greg Daniel7d918fd2018-06-19 15:22:01 -0400124 // Add ref-counted resource that will be tracked and released when this command buffer finishes
125 // recording.
126 void addRecordingResource(const GrVkResource* resource) {
127 resource->ref();
Brian Salomon614c1a82018-12-19 15:42:06 -0500128 resource->notifyAddedToCommandBuffer();
Greg Daniel7d918fd2018-06-19 15:22:01 -0400129 fTrackedRecordingResources.append(1, &resource);
130 }
131
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500132 void releaseResources(GrVkGpu* gpu);
jvanverth7ec92412016-07-06 09:24:57 -0700133
Robert Phillipsce0a2bf2019-04-02 13:37:34 -0400134 bool hasWork() const { return fHasWork; }
135
egdaniel9a6cf802016-06-08 08:22:05 -0700136protected:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500137 GrVkCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool,
Greg Daniel070cbaf2019-01-03 17:35:54 -0500138 const GrVkRenderPass* rp = nullptr)
egdaniel594739c2016-09-20 12:39:25 -0700139 : fIsActive(false)
egdaniel9a6cf802016-06-08 08:22:05 -0700140 , fActiveRenderPass(rp)
141 , fCmdBuffer(cmdBuffer)
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500142 , fCmdPool(cmdPool)
egdaniel594739c2016-09-20 12:39:25 -0700143 , fNumResets(0) {
144 fTrackedResources.setReserve(kInitialTrackedResourcesCount);
145 fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount);
Greg Daniel7d918fd2018-06-19 15:22:01 -0400146 fTrackedRecordingResources.setReserve(kInitialTrackedResourcesCount);
egdaniel9a6cf802016-06-08 08:22:05 -0700147 this->invalidateState();
148 }
egdaniel594739c2016-09-20 12:39:25 -0700149
Greg Daniel070cbaf2019-01-03 17:35:54 -0500150 bool isWrapped() const {
151 return fCmdPool == nullptr;
152 }
153
Robert Phillipsce0a2bf2019-04-02 13:37:34 -0400154 void addedWork() const { fHasWork = true; }
155
egdaniel594739c2016-09-20 12:39:25 -0700156 SkTDArray<const GrVkResource*> fTrackedResources;
157 SkTDArray<const GrVkRecycledResource*> fTrackedRecycledResources;
Greg Daniel7d918fd2018-06-19 15:22:01 -0400158 SkTDArray<const GrVkResource*> fTrackedRecordingResources;
egdaniel9a6cf802016-06-08 08:22:05 -0700159
160 // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add
161 // new commands to the buffer;
Robert Phillips04d2ce22019-04-03 13:20:43 -0400162 bool fIsActive;
163 mutable bool fHasWork = false;
egdaniel9a6cf802016-06-08 08:22:05 -0700164
165 // Stores a pointer to the current active render pass (i.e. begin has been called but not
166 // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own
167 // the render pass.
168 const GrVkRenderPass* fActiveRenderPass;
169
170 VkCommandBuffer fCmdBuffer;
egdaniel9a6cf802016-06-08 08:22:05 -0700171
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500172 // Raw pointer, not refcounted. The command pool controls the command buffer's lifespan, so
173 // it's guaranteed to outlive us.
174 GrVkCommandPool* fCmdPool;
175
egdaniel9a6cf802016-06-08 08:22:05 -0700176private:
177 static const int kInitialTrackedResourcesCount = 32;
178
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500179 void freeGPUData(GrVkGpu* gpu) const final override;
180 virtual void onFreeGPUData(GrVkGpu* gpu) const = 0;
181 void abandonGPUData() const final override;
182 virtual void onAbandonGPUData() const = 0;
egdaniel9a6cf802016-06-08 08:22:05 -0700183
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500184 virtual void onReleaseResources(GrVkGpu* gpu) {}
jvanverth7ec92412016-07-06 09:24:57 -0700185
Greg Daniel6ecc9112017-06-16 16:17:03 +0000186 static constexpr uint32_t kMaxInputBuffers = 2;
187
Chris Dalton1d616352017-05-31 12:51:23 -0600188 VkBuffer fBoundInputBuffers[kMaxInputBuffers];
189 VkBuffer fBoundIndexBuffer;
egdaniel9a6cf802016-06-08 08:22:05 -0700190
egdaniel594739c2016-09-20 12:39:25 -0700191 // When resetting the command buffer, we remove the tracked resources from their arrays, and
192 // we prefer to not free all the memory every time so usually we just rewind. However, to avoid
193 // all arrays growing to the max size, after so many resets we'll do a full reset of the tracked
194 // resource arrays.
195 static const int kNumRewindResetsBeforeFullReset = 8;
196 int fNumResets;
197
egdaniel9a6cf802016-06-08 08:22:05 -0700198 // Cached values used for dynamic state updates
199 VkViewport fCachedViewport;
200 VkRect2D fCachedScissor;
201 float fCachedBlendConstant[4];
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500202
203#ifdef SK_DEBUG
204 mutable bool fResourcesReleased = false;
205#endif
egdaniel9a6cf802016-06-08 08:22:05 -0700206};
207
208class GrVkSecondaryCommandBuffer;
209
210class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer {
211public:
egdaniel9cb63402016-06-23 08:37:05 -0700212 ~GrVkPrimaryCommandBuffer() override;
213
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500214 static GrVkPrimaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool);
egdaniel9a6cf802016-06-08 08:22:05 -0700215
216 void begin(const GrVkGpu* gpu);
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500217 void end(GrVkGpu* gpu);
egdaniel9a6cf802016-06-08 08:22:05 -0700218
219 // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used
220 // in the render pass.
221 void beginRenderPass(const GrVkGpu* gpu,
222 const GrVkRenderPass* renderPass,
Robert Phillips95214472017-08-08 18:00:03 -0400223 const VkClearValue clearValues[],
egdaniel9cb63402016-06-23 08:37:05 -0700224 const GrVkRenderTarget& target,
225 const SkIRect& bounds,
226 bool forSecondaryCB);
egdaniel9a6cf802016-06-08 08:22:05 -0700227 void endRenderPass(const GrVkGpu* gpu);
228
229 // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are
230 // currently inside a render pass that is compatible with the one used to create the
231 // SecondaryCommandBuffer.
232 void executeCommands(const GrVkGpu* gpu,
jvanverth7ec92412016-07-06 09:24:57 -0700233 GrVkSecondaryCommandBuffer* secondaryBuffer);
egdaniel9a6cf802016-06-08 08:22:05 -0700234
Greg Daniel164a9f02016-02-22 09:56:40 -0500235 // Commands that only work outside of a render pass
236 void clearColorImage(const GrVkGpu* gpu,
237 GrVkImage* image,
238 const VkClearColorValue* color,
239 uint32_t subRangeCount,
240 const VkImageSubresourceRange* subRanges);
241
egdaniel3d5d9ac2016-03-01 12:56:15 -0800242 void clearDepthStencilImage(const GrVkGpu* gpu,
243 GrVkImage* image,
244 const VkClearDepthStencilValue* color,
245 uint32_t subRangeCount,
246 const VkImageSubresourceRange* subRanges);
247
Greg Daniel164a9f02016-02-22 09:56:40 -0500248 void copyImage(const GrVkGpu* gpu,
249 GrVkImage* srcImage,
250 VkImageLayout srcLayout,
251 GrVkImage* dstImage,
252 VkImageLayout dstLayout,
253 uint32_t copyRegionCount,
254 const VkImageCopy* copyRegions);
255
egdaniel17b89252016-04-05 07:23:38 -0700256 void blitImage(const GrVkGpu* gpu,
egdanielb2df0c22016-05-13 11:30:37 -0700257 const GrVkResource* srcResource,
258 VkImage srcImage,
egdaniel17b89252016-04-05 07:23:38 -0700259 VkImageLayout srcLayout,
egdanielb2df0c22016-05-13 11:30:37 -0700260 const GrVkResource* dstResource,
261 VkImage dstImage,
egdaniel17b89252016-04-05 07:23:38 -0700262 VkImageLayout dstLayout,
263 uint32_t blitRegionCount,
264 const VkImageBlit* blitRegions,
265 VkFilter filter);
266
egdanielb2df0c22016-05-13 11:30:37 -0700267 void blitImage(const GrVkGpu* gpu,
268 const GrVkImage& srcImage,
269 const GrVkImage& dstImage,
270 uint32_t blitRegionCount,
271 const VkImageBlit* blitRegions,
Greg Daniel6ecc9112017-06-16 16:17:03 +0000272 VkFilter filter);
egdanielb2df0c22016-05-13 11:30:37 -0700273
Greg Daniel164a9f02016-02-22 09:56:40 -0500274 void copyImageToBuffer(const GrVkGpu* gpu,
275 GrVkImage* srcImage,
276 VkImageLayout srcLayout,
277 GrVkTransferBuffer* dstBuffer,
278 uint32_t copyRegionCount,
279 const VkBufferImageCopy* copyRegions);
280
281 void copyBufferToImage(const GrVkGpu* gpu,
282 GrVkTransferBuffer* srcBuffer,
283 GrVkImage* dstImage,
284 VkImageLayout dstLayout,
285 uint32_t copyRegionCount,
286 const VkBufferImageCopy* copyRegions);
287
Greg Daniel6888c0d2017-08-25 11:55:50 -0400288 void copyBuffer(GrVkGpu* gpu,
289 GrVkBuffer* srcBuffer,
290 GrVkBuffer* dstBuffer,
291 uint32_t regionCount,
292 const VkBufferCopy* regions);
293
jvanvertha584de92016-06-30 09:10:52 -0700294 void updateBuffer(GrVkGpu* gpu,
295 GrVkBuffer* dstBuffer,
296 VkDeviceSize dstOffset,
297 VkDeviceSize dataSize,
298 const void* data);
299
egdaniel52ad2512016-08-04 12:50:01 -0700300 void resolveImage(GrVkGpu* gpu,
301 const GrVkImage& srcImage,
302 const GrVkImage& dstImage,
303 uint32_t regionCount,
304 const VkImageResolve* regions);
305
Greg Daniel6be35232017-03-01 17:01:09 -0500306 void submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync,
Greg Daniel48661b82018-01-22 16:11:35 -0500307 SkTArray<GrVkSemaphore::Resource*>& signalSemaphores,
308 SkTArray<GrVkSemaphore::Resource*>& waitSemaphores);
egdaniel9a6cf802016-06-08 08:22:05 -0700309 bool finished(const GrVkGpu* gpu) const;
Greg Daniel164a9f02016-02-22 09:56:40 -0500310
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500311 void recycleSecondaryCommandBuffers();
312
jvanverth7ec92412016-07-06 09:24:57 -0700313#ifdef SK_TRACE_VK_RESOURCES
314 void dumpInfo() const override {
315 SkDebugf("GrVkPrimaryCommandBuffer: %d (%d refs)\n", fCmdBuffer, this->getRefCnt());
316 }
317#endif
318
Greg Daniel164a9f02016-02-22 09:56:40 -0500319private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500320 explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool)
321 : INHERITED(cmdBuffer, cmdPool)
egdaniel9cb63402016-06-23 08:37:05 -0700322 , fSubmitFence(VK_NULL_HANDLE) {}
323
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500324 void onFreeGPUData(GrVkGpu* gpu) const override;
egdaniel9cb63402016-06-23 08:37:05 -0700325
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500326 void onAbandonGPUData() const override;
327
328 void onReleaseResources(GrVkGpu* gpu) override;
jvanverth7ec92412016-07-06 09:24:57 -0700329
330 SkTArray<GrVkSecondaryCommandBuffer*, true> fSecondaryCommandBuffers;
331 VkFence fSubmitFence;
Greg Daniel164a9f02016-02-22 09:56:40 -0500332
egdaniel9a6cf802016-06-08 08:22:05 -0700333 typedef GrVkCommandBuffer INHERITED;
Greg Daniel164a9f02016-02-22 09:56:40 -0500334};
335
egdaniel9a6cf802016-06-08 08:22:05 -0700336class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer {
337public:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500338 static GrVkSecondaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool);
Greg Daniel070cbaf2019-01-03 17:35:54 -0500339 // Used for wrapping an external secondary command buffer.
340 static GrVkSecondaryCommandBuffer* Create(VkCommandBuffer externalSecondaryCB);
egdaniel9a6cf802016-06-08 08:22:05 -0700341
jvanverth7ec92412016-07-06 09:24:57 -0700342 void begin(const GrVkGpu* gpu, const GrVkFramebuffer* framebuffer,
343 const GrVkRenderPass* compatibleRenderPass);
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500344 void end(GrVkGpu* gpu);
egdaniel9a6cf802016-06-08 08:22:05 -0700345
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400346 VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; }
347
jvanverth7ec92412016-07-06 09:24:57 -0700348#ifdef SK_TRACE_VK_RESOURCES
349 void dumpInfo() const override {
350 SkDebugf("GrVkSecondaryCommandBuffer: %d (%d refs)\n", fCmdBuffer, this->getRefCnt());
351 }
352#endif
353
egdaniel9a6cf802016-06-08 08:22:05 -0700354private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500355 explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool)
356 : INHERITED(cmdBuffer, cmdPool) {}
egdaniel9a6cf802016-06-08 08:22:05 -0700357
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500358 void onFreeGPUData(GrVkGpu* gpu) const override {}
359
360 void onAbandonGPUData() const override {}
egdaniel9cb63402016-06-23 08:37:05 -0700361
egdaniel9a6cf802016-06-08 08:22:05 -0700362 friend class GrVkPrimaryCommandBuffer;
363
364 typedef GrVkCommandBuffer INHERITED;
365};
Greg Daniel164a9f02016-02-22 09:56:40 -0500366
367#endif