blob: cb603f69f8567d232dae318f740d313c88b1bf1a [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#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"
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
Greg Daniel8daf3b72019-07-30 09:57:26 -040028class GrVkCommandBuffer {
Greg Daniel164a9f02016-02-22 09:56:40 -050029public:
Greg Daniel8daf3b72019-07-30 09:57:26 -040030 virtual ~GrVkCommandBuffer() {}
31
Greg Daniel164a9f02016-02-22 09:56:40 -050032 void invalidateState();
33
Greg Daniel164a9f02016-02-22 09:56:40 -050034 ////////////////////////////////////////////////////////////////////////////
Greg Daniel164a9f02016-02-22 09:56:40 -050035 // CommandBuffer commands
36 ////////////////////////////////////////////////////////////////////////////
37 enum BarrierType {
Greg Daniel164a9f02016-02-22 09:56:40 -050038 kBufferMemory_BarrierType,
39 kImageMemory_BarrierType
40 };
41
42 void pipelineBarrier(const GrVkGpu* gpu,
Greg Daniel59dc1482019-02-22 10:46:38 -050043 const GrVkResource* resource,
Greg Daniel164a9f02016-02-22 09:56:40 -050044 VkPipelineStageFlags srcStageMask,
45 VkPipelineStageFlags dstStageMask,
46 bool byRegion,
47 BarrierType barrierType,
Greg Daniel59dc1482019-02-22 10:46:38 -050048 void* barrier);
Greg Daniel164a9f02016-02-22 09:56:40 -050049
Greg Daniel6ecc9112017-06-16 16:17:03 +000050 void bindInputBuffer(GrVkGpu* gpu, uint32_t binding, const GrVkVertexBuffer* vbuffer);
Chris Dalton1d616352017-05-31 12:51:23 -060051
Greg Daniel6ecc9112017-06-16 16:17:03 +000052 void bindIndexBuffer(GrVkGpu* gpu, const GrVkIndexBuffer* ibuffer);
Greg Daniel164a9f02016-02-22 09:56:40 -050053
egdaniel58a8d922016-04-21 08:03:10 -070054 void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline);
55
Greg Daniel164a9f02016-02-22 09:56:40 -050056 void bindDescriptorSets(const GrVkGpu* gpu,
egdaniel22281c12016-03-23 13:49:40 -070057 GrVkPipelineState*,
Greg Danieleecc6872019-07-29 13:21:37 -040058 VkPipelineLayout layout,
egdanielbc9b2962016-09-27 08:00:53 -070059 uint32_t firstSet,
60 uint32_t setCount,
61 const VkDescriptorSet* descriptorSets,
62 uint32_t dynamicOffsetCount,
63 const uint32_t* dynamicOffsets);
64
Ethan Nicholas8e265a72018-12-12 16:22:40 -050065 GrVkCommandPool* commandPool() { return fCmdPool; }
66
egdaniel470d77a2016-03-18 12:50:27 -070067 void setViewport(const GrVkGpu* gpu,
68 uint32_t firstViewport,
69 uint32_t viewportCount,
70 const VkViewport* viewports);
71
72 void setScissor(const GrVkGpu* gpu,
73 uint32_t firstScissor,
74 uint32_t scissorCount,
75 const VkRect2D* scissors);
76
77 void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]);
78
egdaniel9a6cf802016-06-08 08:22:05 -070079 // Commands that only work inside of a render pass
80 void clearAttachments(const GrVkGpu* gpu,
81 int numAttachments,
82 const VkClearAttachment* attachments,
83 int numRects,
Greg Danielf346df32019-04-03 14:52:13 -040084 const VkClearRect* clearRects);
egdaniel9a6cf802016-06-08 08:22:05 -070085
86 void drawIndexed(const GrVkGpu* gpu,
87 uint32_t indexCount,
88 uint32_t instanceCount,
89 uint32_t firstIndex,
90 int32_t vertexOffset,
Greg Danielf346df32019-04-03 14:52:13 -040091 uint32_t firstInstance);
egdaniel9a6cf802016-06-08 08:22:05 -070092
93 void draw(const GrVkGpu* gpu,
94 uint32_t vertexCount,
95 uint32_t instanceCount,
96 uint32_t firstVertex,
Greg Danielf346df32019-04-03 14:52:13 -040097 uint32_t firstInstance);
egdaniel9a6cf802016-06-08 08:22:05 -070098
Greg Daniel7d918fd2018-06-19 15:22:01 -040099 // Add ref-counted resource that will be tracked and released when this command buffer finishes
100 // execution
egdaniel9a6cf802016-06-08 08:22:05 -0700101 void addResource(const GrVkResource* resource) {
Greg Danielfa3adf72019-11-07 09:53:41 -0500102 SkASSERT(resource);
egdaniel9a6cf802016-06-08 08:22:05 -0700103 resource->ref();
Brian Salomon614c1a82018-12-19 15:42:06 -0500104 resource->notifyAddedToCommandBuffer();
egdaniel594739c2016-09-20 12:39:25 -0700105 fTrackedResources.append(1, &resource);
egdaniel9a6cf802016-06-08 08:22:05 -0700106 }
107
egdanielc1be9bc2016-07-20 08:33:00 -0700108 // Add ref-counted resource that will be tracked and released when this command buffer finishes
109 // execution. When it is released, it will signal that the resource can be recycled for reuse.
110 void addRecycledResource(const GrVkRecycledResource* resource) {
111 resource->ref();
Brian Salomon614c1a82018-12-19 15:42:06 -0500112 resource->notifyAddedToCommandBuffer();
egdaniel594739c2016-09-20 12:39:25 -0700113 fTrackedRecycledResources.append(1, &resource);
egdanielc1be9bc2016-07-20 08:33:00 -0700114 }
115
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500116 void releaseResources(GrVkGpu* gpu);
jvanverth7ec92412016-07-06 09:24:57 -0700117
Greg Daniel8daf3b72019-07-30 09:57:26 -0400118 void freeGPUData(GrVkGpu* gpu) const;
119 void abandonGPUData() const;
120
Robert Phillipsce0a2bf2019-04-02 13:37:34 -0400121 bool hasWork() const { return fHasWork; }
122
egdaniel9a6cf802016-06-08 08:22:05 -0700123protected:
Greg Daniel8daf3b72019-07-30 09:57:26 -0400124 GrVkCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool,
125 const GrVkRenderPass* rp = nullptr)
egdaniel594739c2016-09-20 12:39:25 -0700126 : fIsActive(false)
egdaniel9a6cf802016-06-08 08:22:05 -0700127 , fActiveRenderPass(rp)
128 , fCmdBuffer(cmdBuffer)
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500129 , fCmdPool(cmdPool)
egdaniel594739c2016-09-20 12:39:25 -0700130 , fNumResets(0) {
Greg Daniel8daf3b72019-07-30 09:57:26 -0400131 fTrackedResources.setReserve(kInitialTrackedResourcesCount);
132 fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount);
133 this->invalidateState();
134 }
egdaniel594739c2016-09-20 12:39:25 -0700135
Greg Daniel8daf3b72019-07-30 09:57:26 -0400136 bool isWrapped() const { return fCmdPool == nullptr; }
Greg Daniel070cbaf2019-01-03 17:35:54 -0500137
Greg Daniel8daf3b72019-07-30 09:57:26 -0400138 void addingWork(const GrVkGpu* gpu);
Greg Danielee54f232019-04-03 14:58:40 -0400139
Greg Daniel8daf3b72019-07-30 09:57:26 -0400140 void submitPipelineBarriers(const GrVkGpu* gpu);
Robert Phillipsce0a2bf2019-04-02 13:37:34 -0400141
Greg Daniel8daf3b72019-07-30 09:57:26 -0400142 SkTDArray<const GrVkResource*> fTrackedResources;
143 SkTDArray<const GrVkRecycledResource*> fTrackedRecycledResources;
egdaniel9a6cf802016-06-08 08:22:05 -0700144
Greg Daniel8daf3b72019-07-30 09:57:26 -0400145 // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add
146 // new commands to the buffer;
147 bool fIsActive;
148 bool fHasWork = false;
egdaniel9a6cf802016-06-08 08:22:05 -0700149
Greg Daniel8daf3b72019-07-30 09:57:26 -0400150 // Stores a pointer to the current active render pass (i.e. begin has been called but not
151 // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own
152 // the render pass.
153 const GrVkRenderPass* fActiveRenderPass;
egdaniel9a6cf802016-06-08 08:22:05 -0700154
Greg Daniel8daf3b72019-07-30 09:57:26 -0400155 VkCommandBuffer fCmdBuffer;
egdaniel9a6cf802016-06-08 08:22:05 -0700156
Greg Daniel8daf3b72019-07-30 09:57:26 -0400157 // Raw pointer, not refcounted. The command pool controls the command buffer's lifespan, so
158 // it's guaranteed to outlive us.
159 GrVkCommandPool* fCmdPool;
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500160
egdaniel9a6cf802016-06-08 08:22:05 -0700161private:
162 static const int kInitialTrackedResourcesCount = 32;
163
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500164 virtual void onReleaseResources(GrVkGpu* gpu) {}
Greg Daniel8daf3b72019-07-30 09:57:26 -0400165 virtual void onFreeGPUData(GrVkGpu* gpu) const = 0;
166 virtual void onAbandonGPUData() const = 0;
jvanverth7ec92412016-07-06 09:24:57 -0700167
Greg Daniel6ecc9112017-06-16 16:17:03 +0000168 static constexpr uint32_t kMaxInputBuffers = 2;
169
Chris Dalton1d616352017-05-31 12:51:23 -0600170 VkBuffer fBoundInputBuffers[kMaxInputBuffers];
171 VkBuffer fBoundIndexBuffer;
egdaniel9a6cf802016-06-08 08:22:05 -0700172
egdaniel594739c2016-09-20 12:39:25 -0700173 // When resetting the command buffer, we remove the tracked resources from their arrays, and
174 // we prefer to not free all the memory every time so usually we just rewind. However, to avoid
175 // all arrays growing to the max size, after so many resets we'll do a full reset of the tracked
176 // resource arrays.
177 static const int kNumRewindResetsBeforeFullReset = 8;
178 int fNumResets;
179
egdaniel9a6cf802016-06-08 08:22:05 -0700180 // Cached values used for dynamic state updates
181 VkViewport fCachedViewport;
182 VkRect2D fCachedScissor;
183 float fCachedBlendConstant[4];
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500184
185#ifdef SK_DEBUG
186 mutable bool fResourcesReleased = false;
187#endif
Greg Danielee54f232019-04-03 14:58:40 -0400188 // Tracking of memory barriers so that we can submit them all in a batch together.
189 SkSTArray<4, VkBufferMemoryBarrier> fBufferBarriers;
190 SkSTArray<1, VkImageMemoryBarrier> fImageBarriers;
191 bool fBarriersByRegion = false;
192 VkPipelineStageFlags fSrcStageMask = 0;
193 VkPipelineStageFlags fDstStageMask = 0;
egdaniel9a6cf802016-06-08 08:22:05 -0700194};
195
196class GrVkSecondaryCommandBuffer;
197
198class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer {
199public:
egdaniel9cb63402016-06-23 08:37:05 -0700200 ~GrVkPrimaryCommandBuffer() override;
201
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500202 static GrVkPrimaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool);
egdaniel9a6cf802016-06-08 08:22:05 -0700203
Greg Daniele643da62019-11-05 12:36:42 -0500204 void begin(GrVkGpu* gpu);
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500205 void end(GrVkGpu* gpu);
egdaniel9a6cf802016-06-08 08:22:05 -0700206
207 // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used
208 // in the render pass.
Greg Danielfa3adf72019-11-07 09:53:41 -0500209 bool beginRenderPass(GrVkGpu* gpu,
egdaniel9a6cf802016-06-08 08:22:05 -0700210 const GrVkRenderPass* renderPass,
Robert Phillips95214472017-08-08 18:00:03 -0400211 const VkClearValue clearValues[],
Greg Danielfa3adf72019-11-07 09:53:41 -0500212 GrVkRenderTarget* target,
egdaniel9cb63402016-06-23 08:37:05 -0700213 const SkIRect& bounds,
214 bool forSecondaryCB);
egdaniel9a6cf802016-06-08 08:22:05 -0700215 void endRenderPass(const GrVkGpu* gpu);
216
217 // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are
218 // currently inside a render pass that is compatible with the one used to create the
219 // SecondaryCommandBuffer.
220 void executeCommands(const GrVkGpu* gpu,
Greg Daniel8daf3b72019-07-30 09:57:26 -0400221 std::unique_ptr<GrVkSecondaryCommandBuffer> secondaryBuffer);
egdaniel9a6cf802016-06-08 08:22:05 -0700222
Greg Daniel164a9f02016-02-22 09:56:40 -0500223 // Commands that only work outside of a render pass
224 void clearColorImage(const GrVkGpu* gpu,
225 GrVkImage* image,
226 const VkClearColorValue* color,
227 uint32_t subRangeCount,
228 const VkImageSubresourceRange* subRanges);
229
egdaniel3d5d9ac2016-03-01 12:56:15 -0800230 void clearDepthStencilImage(const GrVkGpu* gpu,
231 GrVkImage* image,
232 const VkClearDepthStencilValue* color,
233 uint32_t subRangeCount,
234 const VkImageSubresourceRange* subRanges);
235
Greg Daniel164a9f02016-02-22 09:56:40 -0500236 void copyImage(const GrVkGpu* gpu,
237 GrVkImage* srcImage,
238 VkImageLayout srcLayout,
239 GrVkImage* dstImage,
240 VkImageLayout dstLayout,
241 uint32_t copyRegionCount,
242 const VkImageCopy* copyRegions);
243
egdaniel17b89252016-04-05 07:23:38 -0700244 void blitImage(const GrVkGpu* gpu,
egdanielb2df0c22016-05-13 11:30:37 -0700245 const GrVkResource* srcResource,
246 VkImage srcImage,
egdaniel17b89252016-04-05 07:23:38 -0700247 VkImageLayout srcLayout,
egdanielb2df0c22016-05-13 11:30:37 -0700248 const GrVkResource* dstResource,
249 VkImage dstImage,
egdaniel17b89252016-04-05 07:23:38 -0700250 VkImageLayout dstLayout,
251 uint32_t blitRegionCount,
252 const VkImageBlit* blitRegions,
253 VkFilter filter);
254
egdanielb2df0c22016-05-13 11:30:37 -0700255 void blitImage(const GrVkGpu* gpu,
256 const GrVkImage& srcImage,
257 const GrVkImage& dstImage,
258 uint32_t blitRegionCount,
259 const VkImageBlit* blitRegions,
Greg Daniel6ecc9112017-06-16 16:17:03 +0000260 VkFilter filter);
egdanielb2df0c22016-05-13 11:30:37 -0700261
Greg Daniel164a9f02016-02-22 09:56:40 -0500262 void copyImageToBuffer(const GrVkGpu* gpu,
263 GrVkImage* srcImage,
264 VkImageLayout srcLayout,
265 GrVkTransferBuffer* dstBuffer,
266 uint32_t copyRegionCount,
267 const VkBufferImageCopy* copyRegions);
268
269 void copyBufferToImage(const GrVkGpu* gpu,
270 GrVkTransferBuffer* srcBuffer,
271 GrVkImage* dstImage,
272 VkImageLayout dstLayout,
273 uint32_t copyRegionCount,
274 const VkBufferImageCopy* copyRegions);
275
Greg Daniel6888c0d2017-08-25 11:55:50 -0400276 void copyBuffer(GrVkGpu* gpu,
277 GrVkBuffer* srcBuffer,
278 GrVkBuffer* dstBuffer,
279 uint32_t regionCount,
280 const VkBufferCopy* regions);
281
jvanvertha584de92016-06-30 09:10:52 -0700282 void updateBuffer(GrVkGpu* gpu,
283 GrVkBuffer* dstBuffer,
284 VkDeviceSize dstOffset,
285 VkDeviceSize dataSize,
286 const void* data);
287
egdaniel52ad2512016-08-04 12:50:01 -0700288 void resolveImage(GrVkGpu* gpu,
289 const GrVkImage& srcImage,
290 const GrVkImage& dstImage,
291 uint32_t regionCount,
292 const VkImageResolve* regions);
293
Greg Daniele643da62019-11-05 12:36:42 -0500294 void submitToQueue(GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync,
Greg Daniel48661b82018-01-22 16:11:35 -0500295 SkTArray<GrVkSemaphore::Resource*>& signalSemaphores,
296 SkTArray<GrVkSemaphore::Resource*>& waitSemaphores);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400297 bool finished(const GrVkGpu* gpu);
298
299 void addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc);
Greg Daniel164a9f02016-02-22 09:56:40 -0500300
Greg Daniel8daf3b72019-07-30 09:57:26 -0400301 void recycleSecondaryCommandBuffers(GrVkGpu* gpu);
jvanverth7ec92412016-07-06 09:24:57 -0700302
Greg Daniel164a9f02016-02-22 09:56:40 -0500303private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500304 explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool)
305 : INHERITED(cmdBuffer, cmdPool)
egdaniel9cb63402016-06-23 08:37:05 -0700306 , fSubmitFence(VK_NULL_HANDLE) {}
307
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500308 void onFreeGPUData(GrVkGpu* gpu) const override;
egdaniel9cb63402016-06-23 08:37:05 -0700309
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500310 void onAbandonGPUData() const override;
311
312 void onReleaseResources(GrVkGpu* gpu) override;
jvanverth7ec92412016-07-06 09:24:57 -0700313
Greg Daniel8daf3b72019-07-30 09:57:26 -0400314 SkTArray<std::unique_ptr<GrVkSecondaryCommandBuffer>, true> fSecondaryCommandBuffers;
315 VkFence fSubmitFence;
316 SkTArray<sk_sp<GrRefCntedCallback>> fFinishedProcs;
Greg Daniel164a9f02016-02-22 09:56:40 -0500317
egdaniel9a6cf802016-06-08 08:22:05 -0700318 typedef GrVkCommandBuffer INHERITED;
Greg Daniel164a9f02016-02-22 09:56:40 -0500319};
320
egdaniel9a6cf802016-06-08 08:22:05 -0700321class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer {
322public:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500323 static GrVkSecondaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool);
Greg Daniel070cbaf2019-01-03 17:35:54 -0500324 // Used for wrapping an external secondary command buffer.
325 static GrVkSecondaryCommandBuffer* Create(VkCommandBuffer externalSecondaryCB);
egdaniel9a6cf802016-06-08 08:22:05 -0700326
Greg Daniele643da62019-11-05 12:36:42 -0500327 void begin(GrVkGpu* gpu, const GrVkFramebuffer* framebuffer,
jvanverth7ec92412016-07-06 09:24:57 -0700328 const GrVkRenderPass* compatibleRenderPass);
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500329 void end(GrVkGpu* gpu);
egdaniel9a6cf802016-06-08 08:22:05 -0700330
Greg Daniel8daf3b72019-07-30 09:57:26 -0400331 void recycle(GrVkGpu* gpu);
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400332
Greg Daniel8daf3b72019-07-30 09:57:26 -0400333 VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; }
jvanverth7ec92412016-07-06 09:24:57 -0700334
egdaniel9a6cf802016-06-08 08:22:05 -0700335private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500336 explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool)
337 : INHERITED(cmdBuffer, cmdPool) {}
egdaniel9a6cf802016-06-08 08:22:05 -0700338
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500339 void onFreeGPUData(GrVkGpu* gpu) const override {}
340
341 void onAbandonGPUData() const override {}
egdaniel9cb63402016-06-23 08:37:05 -0700342
egdaniel9a6cf802016-06-08 08:22:05 -0700343 friend class GrVkPrimaryCommandBuffer;
344
345 typedef GrVkCommandBuffer INHERITED;
346};
Greg Daniel164a9f02016-02-22 09:56:40 -0500347
348#endif