blob: c1c8015d6e8a6f00718943ba1bb774b711735c2a [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 {
Greg Daniel164a9f02016-02-22 09:56:40 -050036 kBufferMemory_BarrierType,
37 kImageMemory_BarrierType
38 };
39
40 void pipelineBarrier(const GrVkGpu* gpu,
Greg Daniel59dc1482019-02-22 10:46:38 -050041 const GrVkResource* resource,
Greg Daniel164a9f02016-02-22 09:56:40 -050042 VkPipelineStageFlags srcStageMask,
43 VkPipelineStageFlags dstStageMask,
44 bool byRegion,
45 BarrierType barrierType,
Greg Daniel59dc1482019-02-22 10:46:38 -050046 void* barrier);
Greg Daniel164a9f02016-02-22 09:56:40 -050047
Greg Daniel6ecc9112017-06-16 16:17:03 +000048 void bindInputBuffer(GrVkGpu* gpu, uint32_t binding, const GrVkVertexBuffer* vbuffer);
Chris Dalton1d616352017-05-31 12:51:23 -060049
Greg Daniel6ecc9112017-06-16 16:17:03 +000050 void bindIndexBuffer(GrVkGpu* gpu, const GrVkIndexBuffer* ibuffer);
Greg Daniel164a9f02016-02-22 09:56:40 -050051
egdaniel58a8d922016-04-21 08:03:10 -070052 void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline);
53
Greg Daniel164a9f02016-02-22 09:56:40 -050054 void bindDescriptorSets(const GrVkGpu* gpu,
egdaniel22281c12016-03-23 13:49:40 -070055 GrVkPipelineState*,
Greg Daniel7d918fd2018-06-19 15:22:01 -040056 GrVkPipelineLayout* layout,
Greg Daniel164a9f02016-02-22 09:56:40 -050057 uint32_t firstSet,
58 uint32_t setCount,
59 const VkDescriptorSet* descriptorSets,
60 uint32_t dynamicOffsetCount,
61 const uint32_t* dynamicOffsets);
62
egdanielbc9b2962016-09-27 08:00:53 -070063 void bindDescriptorSets(const GrVkGpu* gpu,
64 const SkTArray<const GrVkRecycledResource*>&,
65 const SkTArray<const GrVkResource*>&,
Greg Daniel7d918fd2018-06-19 15:22:01 -040066 GrVkPipelineLayout* layout,
egdanielbc9b2962016-09-27 08:00:53 -070067 uint32_t firstSet,
68 uint32_t setCount,
69 const VkDescriptorSet* descriptorSets,
70 uint32_t dynamicOffsetCount,
71 const uint32_t* dynamicOffsets);
72
Ethan Nicholas8e265a72018-12-12 16:22:40 -050073 GrVkCommandPool* commandPool() { return fCmdPool; }
74
egdaniel470d77a2016-03-18 12:50:27 -070075 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
egdaniel9a6cf802016-06-08 08:22:05 -070087 // 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,
Greg Danielf346df32019-04-03 14:52:13 -040092 const VkClearRect* clearRects);
egdaniel9a6cf802016-06-08 08:22:05 -070093
94 void drawIndexed(const GrVkGpu* gpu,
95 uint32_t indexCount,
96 uint32_t instanceCount,
97 uint32_t firstIndex,
98 int32_t vertexOffset,
Greg Danielf346df32019-04-03 14:52:13 -040099 uint32_t firstInstance);
egdaniel9a6cf802016-06-08 08:22:05 -0700100
101 void draw(const GrVkGpu* gpu,
102 uint32_t vertexCount,
103 uint32_t instanceCount,
104 uint32_t firstVertex,
Greg Danielf346df32019-04-03 14:52:13 -0400105 uint32_t firstInstance);
egdaniel9a6cf802016-06-08 08:22:05 -0700106
Greg Daniel7d918fd2018-06-19 15:22:01 -0400107 // Add ref-counted resource that will be tracked and released when this command buffer finishes
108 // execution
egdaniel9a6cf802016-06-08 08:22:05 -0700109 void addResource(const GrVkResource* resource) {
110 resource->ref();
Brian Salomon614c1a82018-12-19 15:42:06 -0500111 resource->notifyAddedToCommandBuffer();
egdaniel594739c2016-09-20 12:39:25 -0700112 fTrackedResources.append(1, &resource);
egdaniel9a6cf802016-06-08 08:22:05 -0700113 }
114
egdanielc1be9bc2016-07-20 08:33:00 -0700115 // 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.
117 void addRecycledResource(const GrVkRecycledResource* resource) {
118 resource->ref();
Brian Salomon614c1a82018-12-19 15:42:06 -0500119 resource->notifyAddedToCommandBuffer();
egdaniel594739c2016-09-20 12:39:25 -0700120 fTrackedRecycledResources.append(1, &resource);
egdanielc1be9bc2016-07-20 08:33:00 -0700121 }
122
Greg Daniel7d918fd2018-06-19 15:22:01 -0400123 // Add ref-counted resource that will be tracked and released when this command buffer finishes
124 // recording.
125 void addRecordingResource(const GrVkResource* resource) {
126 resource->ref();
Brian Salomon614c1a82018-12-19 15:42:06 -0500127 resource->notifyAddedToCommandBuffer();
Greg Daniel7d918fd2018-06-19 15:22:01 -0400128 fTrackedRecordingResources.append(1, &resource);
129 }
130
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500131 void releaseResources(GrVkGpu* gpu);
jvanverth7ec92412016-07-06 09:24:57 -0700132
Robert Phillipsce0a2bf2019-04-02 13:37:34 -0400133 bool hasWork() const { return fHasWork; }
134
egdaniel9a6cf802016-06-08 08:22:05 -0700135protected:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500136 GrVkCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool,
Greg Daniel070cbaf2019-01-03 17:35:54 -0500137 const GrVkRenderPass* rp = nullptr)
egdaniel594739c2016-09-20 12:39:25 -0700138 : fIsActive(false)
egdaniel9a6cf802016-06-08 08:22:05 -0700139 , fActiveRenderPass(rp)
140 , fCmdBuffer(cmdBuffer)
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500141 , fCmdPool(cmdPool)
egdaniel594739c2016-09-20 12:39:25 -0700142 , fNumResets(0) {
143 fTrackedResources.setReserve(kInitialTrackedResourcesCount);
144 fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount);
Greg Daniel7d918fd2018-06-19 15:22:01 -0400145 fTrackedRecordingResources.setReserve(kInitialTrackedResourcesCount);
egdaniel9a6cf802016-06-08 08:22:05 -0700146 this->invalidateState();
147 }
egdaniel594739c2016-09-20 12:39:25 -0700148
Greg Daniel070cbaf2019-01-03 17:35:54 -0500149 bool isWrapped() const {
150 return fCmdPool == nullptr;
151 }
152
Greg Danielee54f232019-04-03 14:58:40 -0400153 void addingWork(const GrVkGpu* gpu);
154
155 void submitPipelineBarriers(const GrVkGpu* gpu);
Robert Phillipsce0a2bf2019-04-02 13:37:34 -0400156
egdaniel594739c2016-09-20 12:39:25 -0700157 SkTDArray<const GrVkResource*> fTrackedResources;
158 SkTDArray<const GrVkRecycledResource*> fTrackedRecycledResources;
Greg Daniel7d918fd2018-06-19 15:22:01 -0400159 SkTDArray<const GrVkResource*> fTrackedRecordingResources;
egdaniel9a6cf802016-06-08 08:22:05 -0700160
161 // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add
162 // new commands to the buffer;
Robert Phillips04d2ce22019-04-03 13:20:43 -0400163 bool fIsActive;
Greg Danielf346df32019-04-03 14:52:13 -0400164 bool fHasWork = false;
egdaniel9a6cf802016-06-08 08:22:05 -0700165
166 // Stores a pointer to the current active render pass (i.e. begin has been called but not
167 // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own
168 // the render pass.
169 const GrVkRenderPass* fActiveRenderPass;
170
171 VkCommandBuffer fCmdBuffer;
egdaniel9a6cf802016-06-08 08:22:05 -0700172
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500173 // Raw pointer, not refcounted. The command pool controls the command buffer's lifespan, so
174 // it's guaranteed to outlive us.
175 GrVkCommandPool* fCmdPool;
176
egdaniel9a6cf802016-06-08 08:22:05 -0700177private:
178 static const int kInitialTrackedResourcesCount = 32;
179
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500180 void freeGPUData(GrVkGpu* gpu) const final override;
181 virtual void onFreeGPUData(GrVkGpu* gpu) const = 0;
182 void abandonGPUData() const final override;
183 virtual void onAbandonGPUData() const = 0;
egdaniel9a6cf802016-06-08 08:22:05 -0700184
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500185 virtual void onReleaseResources(GrVkGpu* gpu) {}
jvanverth7ec92412016-07-06 09:24:57 -0700186
Greg Daniel6ecc9112017-06-16 16:17:03 +0000187 static constexpr uint32_t kMaxInputBuffers = 2;
188
Chris Dalton1d616352017-05-31 12:51:23 -0600189 VkBuffer fBoundInputBuffers[kMaxInputBuffers];
190 VkBuffer fBoundIndexBuffer;
egdaniel9a6cf802016-06-08 08:22:05 -0700191
egdaniel594739c2016-09-20 12:39:25 -0700192 // When resetting the command buffer, we remove the tracked resources from their arrays, and
193 // we prefer to not free all the memory every time so usually we just rewind. However, to avoid
194 // all arrays growing to the max size, after so many resets we'll do a full reset of the tracked
195 // resource arrays.
196 static const int kNumRewindResetsBeforeFullReset = 8;
197 int fNumResets;
198
egdaniel9a6cf802016-06-08 08:22:05 -0700199 // Cached values used for dynamic state updates
200 VkViewport fCachedViewport;
201 VkRect2D fCachedScissor;
202 float fCachedBlendConstant[4];
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500203
204#ifdef SK_DEBUG
205 mutable bool fResourcesReleased = false;
206#endif
Greg Danielee54f232019-04-03 14:58:40 -0400207 // Tracking of memory barriers so that we can submit them all in a batch together.
208 SkSTArray<4, VkBufferMemoryBarrier> fBufferBarriers;
209 SkSTArray<1, VkImageMemoryBarrier> fImageBarriers;
210 bool fBarriersByRegion = false;
211 VkPipelineStageFlags fSrcStageMask = 0;
212 VkPipelineStageFlags fDstStageMask = 0;
egdaniel9a6cf802016-06-08 08:22:05 -0700213};
214
215class GrVkSecondaryCommandBuffer;
216
217class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer {
218public:
egdaniel9cb63402016-06-23 08:37:05 -0700219 ~GrVkPrimaryCommandBuffer() override;
220
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500221 static GrVkPrimaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool);
egdaniel9a6cf802016-06-08 08:22:05 -0700222
223 void begin(const GrVkGpu* gpu);
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500224 void end(GrVkGpu* gpu);
egdaniel9a6cf802016-06-08 08:22:05 -0700225
226 // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used
227 // in the render pass.
228 void beginRenderPass(const GrVkGpu* gpu,
229 const GrVkRenderPass* renderPass,
Robert Phillips95214472017-08-08 18:00:03 -0400230 const VkClearValue clearValues[],
egdaniel9cb63402016-06-23 08:37:05 -0700231 const GrVkRenderTarget& target,
232 const SkIRect& bounds,
233 bool forSecondaryCB);
egdaniel9a6cf802016-06-08 08:22:05 -0700234 void endRenderPass(const GrVkGpu* gpu);
235
236 // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are
237 // currently inside a render pass that is compatible with the one used to create the
238 // SecondaryCommandBuffer.
239 void executeCommands(const GrVkGpu* gpu,
jvanverth7ec92412016-07-06 09:24:57 -0700240 GrVkSecondaryCommandBuffer* secondaryBuffer);
egdaniel9a6cf802016-06-08 08:22:05 -0700241
Greg Daniel164a9f02016-02-22 09:56:40 -0500242 // Commands that only work outside of a render pass
243 void clearColorImage(const GrVkGpu* gpu,
244 GrVkImage* image,
245 const VkClearColorValue* color,
246 uint32_t subRangeCount,
247 const VkImageSubresourceRange* subRanges);
248
egdaniel3d5d9ac2016-03-01 12:56:15 -0800249 void clearDepthStencilImage(const GrVkGpu* gpu,
250 GrVkImage* image,
251 const VkClearDepthStencilValue* color,
252 uint32_t subRangeCount,
253 const VkImageSubresourceRange* subRanges);
254
Greg Daniel164a9f02016-02-22 09:56:40 -0500255 void copyImage(const GrVkGpu* gpu,
256 GrVkImage* srcImage,
257 VkImageLayout srcLayout,
258 GrVkImage* dstImage,
259 VkImageLayout dstLayout,
260 uint32_t copyRegionCount,
261 const VkImageCopy* copyRegions);
262
egdaniel17b89252016-04-05 07:23:38 -0700263 void blitImage(const GrVkGpu* gpu,
egdanielb2df0c22016-05-13 11:30:37 -0700264 const GrVkResource* srcResource,
265 VkImage srcImage,
egdaniel17b89252016-04-05 07:23:38 -0700266 VkImageLayout srcLayout,
egdanielb2df0c22016-05-13 11:30:37 -0700267 const GrVkResource* dstResource,
268 VkImage dstImage,
egdaniel17b89252016-04-05 07:23:38 -0700269 VkImageLayout dstLayout,
270 uint32_t blitRegionCount,
271 const VkImageBlit* blitRegions,
272 VkFilter filter);
273
egdanielb2df0c22016-05-13 11:30:37 -0700274 void blitImage(const GrVkGpu* gpu,
275 const GrVkImage& srcImage,
276 const GrVkImage& dstImage,
277 uint32_t blitRegionCount,
278 const VkImageBlit* blitRegions,
Greg Daniel6ecc9112017-06-16 16:17:03 +0000279 VkFilter filter);
egdanielb2df0c22016-05-13 11:30:37 -0700280
Greg Daniel164a9f02016-02-22 09:56:40 -0500281 void copyImageToBuffer(const GrVkGpu* gpu,
282 GrVkImage* srcImage,
283 VkImageLayout srcLayout,
284 GrVkTransferBuffer* dstBuffer,
285 uint32_t copyRegionCount,
286 const VkBufferImageCopy* copyRegions);
287
288 void copyBufferToImage(const GrVkGpu* gpu,
289 GrVkTransferBuffer* srcBuffer,
290 GrVkImage* dstImage,
291 VkImageLayout dstLayout,
292 uint32_t copyRegionCount,
293 const VkBufferImageCopy* copyRegions);
294
Greg Daniel6888c0d2017-08-25 11:55:50 -0400295 void copyBuffer(GrVkGpu* gpu,
296 GrVkBuffer* srcBuffer,
297 GrVkBuffer* dstBuffer,
298 uint32_t regionCount,
299 const VkBufferCopy* regions);
300
jvanvertha584de92016-06-30 09:10:52 -0700301 void updateBuffer(GrVkGpu* gpu,
302 GrVkBuffer* dstBuffer,
303 VkDeviceSize dstOffset,
304 VkDeviceSize dataSize,
305 const void* data);
306
egdaniel52ad2512016-08-04 12:50:01 -0700307 void resolveImage(GrVkGpu* gpu,
308 const GrVkImage& srcImage,
309 const GrVkImage& dstImage,
310 uint32_t regionCount,
311 const VkImageResolve* regions);
312
Greg Daniel6be35232017-03-01 17:01:09 -0500313 void submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync,
Greg Daniel48661b82018-01-22 16:11:35 -0500314 SkTArray<GrVkSemaphore::Resource*>& signalSemaphores,
315 SkTArray<GrVkSemaphore::Resource*>& waitSemaphores);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400316 bool finished(const GrVkGpu* gpu);
317
318 void addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc);
Greg Daniel164a9f02016-02-22 09:56:40 -0500319
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500320 void recycleSecondaryCommandBuffers();
321
jvanverth7ec92412016-07-06 09:24:57 -0700322#ifdef SK_TRACE_VK_RESOURCES
323 void dumpInfo() const override {
324 SkDebugf("GrVkPrimaryCommandBuffer: %d (%d refs)\n", fCmdBuffer, this->getRefCnt());
325 }
326#endif
327
Greg Daniel164a9f02016-02-22 09:56:40 -0500328private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500329 explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool)
330 : INHERITED(cmdBuffer, cmdPool)
egdaniel9cb63402016-06-23 08:37:05 -0700331 , fSubmitFence(VK_NULL_HANDLE) {}
332
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500333 void onFreeGPUData(GrVkGpu* gpu) const override;
egdaniel9cb63402016-06-23 08:37:05 -0700334
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500335 void onAbandonGPUData() const override;
336
337 void onReleaseResources(GrVkGpu* gpu) override;
jvanverth7ec92412016-07-06 09:24:57 -0700338
339 SkTArray<GrVkSecondaryCommandBuffer*, true> fSecondaryCommandBuffers;
340 VkFence fSubmitFence;
Greg Daniela3aa75a2019-04-12 14:24:55 -0400341 SkTArray<sk_sp<GrRefCntedCallback>> fFinishedProcs;
Greg Daniel164a9f02016-02-22 09:56:40 -0500342
egdaniel9a6cf802016-06-08 08:22:05 -0700343 typedef GrVkCommandBuffer INHERITED;
Greg Daniel164a9f02016-02-22 09:56:40 -0500344};
345
egdaniel9a6cf802016-06-08 08:22:05 -0700346class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer {
347public:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500348 static GrVkSecondaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool);
Greg Daniel070cbaf2019-01-03 17:35:54 -0500349 // Used for wrapping an external secondary command buffer.
350 static GrVkSecondaryCommandBuffer* Create(VkCommandBuffer externalSecondaryCB);
egdaniel9a6cf802016-06-08 08:22:05 -0700351
jvanverth7ec92412016-07-06 09:24:57 -0700352 void begin(const GrVkGpu* gpu, const GrVkFramebuffer* framebuffer,
353 const GrVkRenderPass* compatibleRenderPass);
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500354 void end(GrVkGpu* gpu);
egdaniel9a6cf802016-06-08 08:22:05 -0700355
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400356 VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; }
357
jvanverth7ec92412016-07-06 09:24:57 -0700358#ifdef SK_TRACE_VK_RESOURCES
359 void dumpInfo() const override {
360 SkDebugf("GrVkSecondaryCommandBuffer: %d (%d refs)\n", fCmdBuffer, this->getRefCnt());
361 }
362#endif
363
egdaniel9a6cf802016-06-08 08:22:05 -0700364private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500365 explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool)
366 : INHERITED(cmdBuffer, cmdPool) {}
egdaniel9a6cf802016-06-08 08:22:05 -0700367
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500368 void onFreeGPUData(GrVkGpu* gpu) const override {}
369
370 void onAbandonGPUData() const override {}
egdaniel9cb63402016-06-23 08:37:05 -0700371
egdaniel9a6cf802016-06-08 08:22:05 -0700372 friend class GrVkPrimaryCommandBuffer;
373
374 typedef GrVkCommandBuffer INHERITED;
375};
Greg Daniel164a9f02016-02-22 09:56:40 -0500376
377#endif