• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "src/gpu/vk/GrVkCommandBuffer.h"
9 
10 #include "include/core/SkRect.h"
11 #include "src/core/SkTraceEvent.h"
12 #include "src/gpu/vk/GrVkBuffer.h"
13 #include "src/gpu/vk/GrVkCommandPool.h"
14 #include "src/gpu/vk/GrVkFramebuffer.h"
15 #include "src/gpu/vk/GrVkGpu.h"
16 #include "src/gpu/vk/GrVkImage.h"
17 #include "src/gpu/vk/GrVkImageView.h"
18 #include "src/gpu/vk/GrVkPipeline.h"
19 #include "src/gpu/vk/GrVkPipelineState.h"
20 #include "src/gpu/vk/GrVkPipelineState.h"
21 #include "src/gpu/vk/GrVkRenderPass.h"
22 #include "src/gpu/vk/GrVkRenderTarget.h"
23 #include "src/gpu/vk/GrVkUtil.h"
24 #ifdef SK_VK_PARTIALRENDER
25 #include "src/gpu/vk/GrVkDrawAreaManager.h"
26 #include "src/gpu/vk/vulkan_header_ext_huawei.h"
27 #endif
28 
invalidateState()29 void GrVkCommandBuffer::invalidateState() {
30     for (auto& boundInputBuffer : fBoundInputBuffers) {
31         boundInputBuffer = VK_NULL_HANDLE;
32     }
33     fBoundIndexBuffer = VK_NULL_HANDLE;
34 
35     memset(&fCachedViewport, 0, sizeof(VkViewport));
36     fCachedViewport.width = - 1.0f; // Viewport must have a width greater than 0
37 
38     memset(&fCachedScissor, 0, sizeof(VkRect2D));
39     fCachedScissor.offset.x = -1; // Scissor offset must be greater that 0 to be valid
40 
41     for (int i = 0; i < 4; ++i) {
42         fCachedBlendConstant[i] = -1.0;
43     }
44 }
45 
freeGPUData(const GrGpu * gpu,VkCommandPool cmdPool) const46 void GrVkCommandBuffer::freeGPUData(const GrGpu* gpu, VkCommandPool cmdPool) const {
47     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
48     SkASSERT(!fIsActive);
49     SkASSERT(!fTrackedResources.count());
50     SkASSERT(!fTrackedRecycledResources.count());
51     SkASSERT(!fTrackedGpuBuffers.count());
52     SkASSERT(!fTrackedGpuSurfaces.count());
53     SkASSERT(cmdPool != VK_NULL_HANDLE);
54     SkASSERT(!this->isWrapped());
55 
56     GrVkGpu* vkGpu = (GrVkGpu*)gpu;
57     GR_VK_CALL(vkGpu->vkInterface(), FreeCommandBuffers(vkGpu->device(), cmdPool, 1, &fCmdBuffer));
58 
59     this->onFreeGPUData(vkGpu);
60 }
61 
releaseResources()62 void GrVkCommandBuffer::releaseResources() {
63     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
64     SkASSERT(!fIsActive || this->isWrapped());
65     fTrackedResources.reset();
66     fTrackedRecycledResources.reset();
67 
68     fTrackedGpuBuffers.reset();
69     fTrackedGpuSurfaces.reset();
70 
71     this->invalidateState();
72 
73     this->onReleaseResources();
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 // CommandBuffer commands
78 ////////////////////////////////////////////////////////////////////////////////
79 
pipelineBarrier(const GrVkGpu * gpu,const GrManagedResource * resource,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,bool byRegion,BarrierType barrierType,void * barrier)80 void GrVkCommandBuffer::pipelineBarrier(const GrVkGpu* gpu,
81                                         const GrManagedResource* resource,
82                                         VkPipelineStageFlags srcStageMask,
83                                         VkPipelineStageFlags dstStageMask,
84                                         bool byRegion,
85                                         BarrierType barrierType,
86                                         void* barrier) {
87     SkASSERT(!this->isWrapped());
88     SkASSERT(fIsActive);
89 #ifdef SK_DEBUG
90     // For images we can have barriers inside of render passes but they require us to add more
91     // support in subpasses which need self dependencies to have barriers inside them. Also, we can
92     // never have buffer barriers inside of a render pass. For now we will just assert that we are
93     // not in a render pass.
94     bool isValidSubpassBarrier = false;
95     if (barrierType == kImageMemory_BarrierType) {
96         VkImageMemoryBarrier* imgBarrier = static_cast<VkImageMemoryBarrier*>(barrier);
97         isValidSubpassBarrier = (imgBarrier->newLayout == imgBarrier->oldLayout) &&
98                                 (imgBarrier->srcQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) &&
99                                 (imgBarrier->dstQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) &&
100                                 byRegion;
101     }
102     SkASSERT(!fActiveRenderPass || isValidSubpassBarrier);
103 #endif
104 
105     if (barrierType == kBufferMemory_BarrierType) {
106         const VkBufferMemoryBarrier* barrierPtr = static_cast<VkBufferMemoryBarrier*>(barrier);
107         fBufferBarriers.push_back(*barrierPtr);
108     } else {
109         SkASSERT(barrierType == kImageMemory_BarrierType);
110         const VkImageMemoryBarrier* barrierPtr = static_cast<VkImageMemoryBarrier*>(barrier);
111         // We need to check if we are adding a pipeline barrier that covers part of the same
112         // subresource range as a barrier that is already in current batch. If it does, then we must
113         // submit the first batch because the vulkan spec does not define a specific ordering for
114         // barriers submitted in the same batch.
115         // TODO: Look if we can gain anything by merging barriers together instead of submitting
116         // the old ones.
117         for (int i = 0; i < fImageBarriers.count(); ++i) {
118             VkImageMemoryBarrier& currentBarrier = fImageBarriers[i];
119             if (barrierPtr->image == currentBarrier.image) {
120                 const VkImageSubresourceRange newRange = barrierPtr->subresourceRange;
121                 const VkImageSubresourceRange oldRange = currentBarrier.subresourceRange;
122                 SkASSERT(newRange.aspectMask == oldRange.aspectMask);
123                 SkASSERT(newRange.baseArrayLayer == oldRange.baseArrayLayer);
124                 SkASSERT(newRange.layerCount == oldRange.layerCount);
125                 uint32_t newStart = newRange.baseMipLevel;
126                 uint32_t newEnd = newRange.baseMipLevel + newRange.levelCount - 1;
127                 uint32_t oldStart = oldRange.baseMipLevel;
128                 uint32_t oldEnd = oldRange.baseMipLevel + oldRange.levelCount - 1;
129                 if (std::max(newStart, oldStart) <= std::min(newEnd, oldEnd)) {
130                     this->submitPipelineBarriers(gpu);
131                     break;
132                 }
133             }
134         }
135         fImageBarriers.push_back(*barrierPtr);
136     }
137     fBarriersByRegion |= byRegion;
138     fSrcStageMask = fSrcStageMask | srcStageMask;
139     fDstStageMask = fDstStageMask | dstStageMask;
140 
141     fHasWork = true;
142     if (resource) {
143         this->addResource(resource);
144     }
145     if (fActiveRenderPass) {
146         this->submitPipelineBarriers(gpu, true);
147     }
148 }
149 
submitPipelineBarriers(const GrVkGpu * gpu,bool forSelfDependency)150 void GrVkCommandBuffer::submitPipelineBarriers(const GrVkGpu* gpu, bool forSelfDependency) {
151     SkASSERT(fIsActive);
152 
153     // Currently we never submit a pipeline barrier without at least one memory barrier.
154     if (fBufferBarriers.count() || fImageBarriers.count()) {
155         // For images we can have barriers inside of render passes but they require us to add more
156         // support in subpasses which need self dependencies to have barriers inside them. Also, we
157         // can never have buffer barriers inside of a render pass. For now we will just assert that
158         // we are not in a render pass.
159         SkASSERT(!fActiveRenderPass || forSelfDependency);
160         SkASSERT(!this->isWrapped());
161         SkASSERT(fSrcStageMask && fDstStageMask);
162 
163         VkDependencyFlags dependencyFlags = fBarriersByRegion ? VK_DEPENDENCY_BY_REGION_BIT : 0;
164         GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(
165                 fCmdBuffer, fSrcStageMask, fDstStageMask, dependencyFlags, 0, nullptr,
166                 fBufferBarriers.count(), fBufferBarriers.begin(),
167                 fImageBarriers.count(), fImageBarriers.begin()));
168         fBufferBarriers.reset();
169         fImageBarriers.reset();
170         fBarriersByRegion = false;
171         fSrcStageMask = 0;
172         fDstStageMask = 0;
173     }
174     SkASSERT(!fBufferBarriers.count());
175     SkASSERT(!fImageBarriers.count());
176     SkASSERT(!fBarriersByRegion);
177     SkASSERT(!fSrcStageMask);
178     SkASSERT(!fDstStageMask);
179 }
180 
bindInputBuffer(GrVkGpu * gpu,uint32_t binding,sk_sp<const GrBuffer> buffer)181 void GrVkCommandBuffer::bindInputBuffer(GrVkGpu* gpu, uint32_t binding,
182                                         sk_sp<const GrBuffer> buffer) {
183     VkBuffer vkBuffer = static_cast<const GrVkBuffer*>(buffer.get())->vkBuffer();
184     SkASSERT(VK_NULL_HANDLE != vkBuffer);
185     SkASSERT(binding < kMaxInputBuffers);
186     // TODO: once vbuffer->offset() no longer always returns 0, we will need to track the offset
187     // to know if we can skip binding or not.
188     if (vkBuffer != fBoundInputBuffers[binding]) {
189         VkDeviceSize offset = 0;
190         GR_VK_CALL(gpu->vkInterface(), CmdBindVertexBuffers(fCmdBuffer,
191                                                             binding,
192                                                             1,
193                                                             &vkBuffer,
194                                                             &offset));
195         fBoundInputBuffers[binding] = vkBuffer;
196         this->addGrBuffer(std::move(buffer));
197     }
198 }
199 
bindIndexBuffer(GrVkGpu * gpu,sk_sp<const GrBuffer> buffer)200 void GrVkCommandBuffer::bindIndexBuffer(GrVkGpu* gpu, sk_sp<const GrBuffer> buffer) {
201     VkBuffer vkBuffer = static_cast<const GrVkBuffer*>(buffer.get())->vkBuffer();
202     SkASSERT(VK_NULL_HANDLE != vkBuffer);
203     // TODO: once ibuffer->offset() no longer always returns 0, we will need to track the offset
204     // to know if we can skip binding or not.
205     if (vkBuffer != fBoundIndexBuffer) {
206         GR_VK_CALL(gpu->vkInterface(), CmdBindIndexBuffer(fCmdBuffer,
207                                                           vkBuffer, /*offset=*/0,
208                                                           VK_INDEX_TYPE_UINT16));
209         fBoundIndexBuffer = vkBuffer;
210         this->addGrBuffer(std::move(buffer));
211     }
212 }
213 
clearAttachments(const GrVkGpu * gpu,int numAttachments,const VkClearAttachment * attachments,int numRects,const VkClearRect * clearRects)214 void GrVkCommandBuffer::clearAttachments(const GrVkGpu* gpu,
215                                          int numAttachments,
216                                          const VkClearAttachment* attachments,
217                                          int numRects,
218                                          const VkClearRect* clearRects) {
219     SkASSERT(fIsActive);
220     SkASSERT(fActiveRenderPass);
221     SkASSERT(numAttachments > 0);
222     SkASSERT(numRects > 0);
223 
224     this->addingWork(gpu);
225 
226 #ifdef SK_DEBUG
227     for (int i = 0; i < numAttachments; ++i) {
228         if (attachments[i].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
229             uint32_t testIndex;
230             SkAssertResult(fActiveRenderPass->colorAttachmentIndex(&testIndex));
231             SkASSERT(testIndex == attachments[i].colorAttachment);
232         }
233     }
234 #endif
235     GR_VK_CALL(gpu->vkInterface(), CmdClearAttachments(fCmdBuffer,
236                                                        numAttachments,
237                                                        attachments,
238                                                        numRects,
239                                                        clearRects));
240     if (gpu->vkCaps().mustInvalidatePrimaryCmdBufferStateAfterClearAttachments()) {
241         this->invalidateState();
242     }
243 }
244 
bindDescriptorSets(const GrVkGpu * gpu,VkPipelineLayout layout,uint32_t firstSet,uint32_t setCount,const VkDescriptorSet * descriptorSets,uint32_t dynamicOffsetCount,const uint32_t * dynamicOffsets)245 void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
246                                            VkPipelineLayout layout,
247                                            uint32_t firstSet,
248                                            uint32_t setCount,
249                                            const VkDescriptorSet* descriptorSets,
250                                            uint32_t dynamicOffsetCount,
251                                            const uint32_t* dynamicOffsets) {
252     SkASSERT(fIsActive);
253     GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer,
254                                                          VK_PIPELINE_BIND_POINT_GRAPHICS,
255                                                          layout,
256                                                          firstSet,
257                                                          setCount,
258                                                          descriptorSets,
259                                                          dynamicOffsetCount,
260                                                          dynamicOffsets));
261 }
262 
bindPipeline(const GrVkGpu * gpu,sk_sp<const GrVkPipeline> pipeline)263 void GrVkCommandBuffer::bindPipeline(const GrVkGpu* gpu, sk_sp<const GrVkPipeline> pipeline) {
264     SkASSERT(fIsActive);
265     GR_VK_CALL(gpu->vkInterface(), CmdBindPipeline(fCmdBuffer,
266                                                    VK_PIPELINE_BIND_POINT_GRAPHICS,
267                                                    pipeline->pipeline()));
268     this->addResource(std::move(pipeline));
269 }
270 
pushConstants(const GrVkGpu * gpu,VkPipelineLayout layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * values)271 void GrVkCommandBuffer::pushConstants(const GrVkGpu* gpu, VkPipelineLayout layout,
272                                       VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size,
273                                       const void* values) {
274     SkASSERT(fIsActive);
275     // offset and size must be a multiple of 4
276     SkASSERT(!SkToBool(offset & 0x3));
277     SkASSERT(!SkToBool(size & 0x3));
278     GR_VK_CALL(gpu->vkInterface(), CmdPushConstants(fCmdBuffer,
279                                                     layout,
280                                                     stageFlags,
281                                                     offset,
282                                                     size,
283                                                     values));
284 }
285 
drawIndexed(const GrVkGpu * gpu,uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)286 void GrVkCommandBuffer::drawIndexed(const GrVkGpu* gpu,
287                                     uint32_t indexCount,
288                                     uint32_t instanceCount,
289                                     uint32_t firstIndex,
290                                     int32_t vertexOffset,
291                                     uint32_t firstInstance) {
292     SkASSERT(fIsActive);
293     SkASSERT(fActiveRenderPass);
294     this->addingWork(gpu);
295     GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexed(fCmdBuffer,
296                                                   indexCount,
297                                                   instanceCount,
298                                                   firstIndex,
299                                                   vertexOffset,
300                                                   firstInstance));
301 }
302 
draw(const GrVkGpu * gpu,uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)303 void GrVkCommandBuffer::draw(const GrVkGpu* gpu,
304                              uint32_t vertexCount,
305                              uint32_t instanceCount,
306                              uint32_t firstVertex,
307                              uint32_t firstInstance) {
308     SkASSERT(fIsActive);
309     SkASSERT(fActiveRenderPass);
310     this->addingWork(gpu);
311     GR_VK_CALL(gpu->vkInterface(), CmdDraw(fCmdBuffer,
312                                            vertexCount,
313                                            instanceCount,
314                                            firstVertex,
315                                            firstInstance));
316 }
317 
drawIndirect(const GrVkGpu * gpu,sk_sp<const GrBuffer> indirectBuffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)318 void GrVkCommandBuffer::drawIndirect(const GrVkGpu* gpu,
319                                      sk_sp<const GrBuffer> indirectBuffer,
320                                      VkDeviceSize offset,
321                                      uint32_t drawCount,
322                                      uint32_t stride) {
323     SkASSERT(fIsActive);
324     SkASSERT(fActiveRenderPass);
325     SkASSERT(!indirectBuffer->isCpuBuffer());
326     this->addingWork(gpu);
327     VkBuffer vkBuffer = static_cast<const GrVkBuffer*>(indirectBuffer.get())->vkBuffer();
328     GR_VK_CALL(gpu->vkInterface(), CmdDrawIndirect(fCmdBuffer,
329                                                    vkBuffer,
330                                                    offset,
331                                                    drawCount,
332                                                    stride));
333     this->addGrBuffer(std::move(indirectBuffer));
334 }
335 
drawIndexedIndirect(const GrVkGpu * gpu,sk_sp<const GrBuffer> indirectBuffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)336 void GrVkCommandBuffer::drawIndexedIndirect(const GrVkGpu* gpu,
337                                             sk_sp<const GrBuffer> indirectBuffer,
338                                             VkDeviceSize offset,
339                                             uint32_t drawCount,
340                                             uint32_t stride) {
341     SkASSERT(fIsActive);
342     SkASSERT(fActiveRenderPass);
343     SkASSERT(!indirectBuffer->isCpuBuffer());
344     this->addingWork(gpu);
345     VkBuffer vkBuffer = static_cast<const GrVkBuffer*>(indirectBuffer.get())->vkBuffer();
346     GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexedIndirect(fCmdBuffer,
347                                                           vkBuffer,
348                                                           offset,
349                                                           drawCount,
350                                                           stride));
351     this->addGrBuffer(std::move(indirectBuffer));
352 }
353 
setViewport(const GrVkGpu * gpu,uint32_t firstViewport,uint32_t viewportCount,const VkViewport * viewports)354 void GrVkCommandBuffer::setViewport(const GrVkGpu* gpu,
355                                     uint32_t firstViewport,
356                                     uint32_t viewportCount,
357                                     const VkViewport* viewports) {
358     SkASSERT(fIsActive);
359     SkASSERT(1 == viewportCount);
360     if (0 != memcmp(viewports, &fCachedViewport, sizeof(VkViewport))) {
361         GR_VK_CALL(gpu->vkInterface(), CmdSetViewport(fCmdBuffer,
362                                                       firstViewport,
363                                                       viewportCount,
364                                                       viewports));
365         fCachedViewport = viewports[0];
366     }
367 }
368 
setScissor(const GrVkGpu * gpu,uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * scissors)369 void GrVkCommandBuffer::setScissor(const GrVkGpu* gpu,
370                                    uint32_t firstScissor,
371                                    uint32_t scissorCount,
372                                    const VkRect2D* scissors) {
373     SkASSERT(fIsActive);
374     SkASSERT(1 == scissorCount);
375     if (0 != memcmp(scissors, &fCachedScissor, sizeof(VkRect2D))) {
376         GR_VK_CALL(gpu->vkInterface(), CmdSetScissor(fCmdBuffer,
377                                                      firstScissor,
378                                                      scissorCount,
379                                                      scissors));
380         fCachedScissor = scissors[0];
381     }
382 }
383 
setBlendConstants(const GrVkGpu * gpu,const float blendConstants[4])384 void GrVkCommandBuffer::setBlendConstants(const GrVkGpu* gpu,
385                                           const float blendConstants[4]) {
386     SkASSERT(fIsActive);
387     if (0 != memcmp(blendConstants, fCachedBlendConstant, 4 * sizeof(float))) {
388         GR_VK_CALL(gpu->vkInterface(), CmdSetBlendConstants(fCmdBuffer, blendConstants));
389         memcpy(fCachedBlendConstant, blendConstants, 4 * sizeof(float));
390     }
391 }
392 
addingWork(const GrVkGpu * gpu)393 void GrVkCommandBuffer::addingWork(const GrVkGpu* gpu) {
394     this->submitPipelineBarriers(gpu);
395     fHasWork = true;
396 }
397 
398 ///////////////////////////////////////////////////////////////////////////////
399 // PrimaryCommandBuffer
400 ////////////////////////////////////////////////////////////////////////////////
~GrVkPrimaryCommandBuffer()401 GrVkPrimaryCommandBuffer::~GrVkPrimaryCommandBuffer() {
402     // Should have ended any render pass we're in the middle of
403     SkASSERT(!fActiveRenderPass);
404 }
405 
Create(GrVkGpu * gpu,VkCommandPool cmdPool)406 GrVkPrimaryCommandBuffer* GrVkPrimaryCommandBuffer::Create(GrVkGpu* gpu,
407                                                            VkCommandPool cmdPool) {
408     const VkCommandBufferAllocateInfo cmdInfo = {
409         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
410         nullptr,                                          // pNext
411         cmdPool,                                          // commandPool
412         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                  // level
413         1                                                 // bufferCount
414     };
415 
416     VkCommandBuffer cmdBuffer;
417     VkResult err;
418     GR_VK_CALL_RESULT(gpu, err, AllocateCommandBuffers(gpu->device(), &cmdInfo, &cmdBuffer));
419     if (err) {
420         return nullptr;
421     }
422     return new GrVkPrimaryCommandBuffer(cmdBuffer);
423 }
424 
begin(GrVkGpu * gpu)425 void GrVkPrimaryCommandBuffer::begin(GrVkGpu* gpu) {
426     SkASSERT(!fIsActive);
427     VkCommandBufferBeginInfo cmdBufferBeginInfo;
428     memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
429     cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
430     cmdBufferBeginInfo.pNext = nullptr;
431     cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
432     cmdBufferBeginInfo.pInheritanceInfo = nullptr;
433 
434     GR_VK_CALL_ERRCHECK(gpu, BeginCommandBuffer(fCmdBuffer, &cmdBufferBeginInfo));
435     fIsActive = true;
436 }
437 
end(GrVkGpu * gpu,bool abandoningBuffer)438 void GrVkPrimaryCommandBuffer::end(GrVkGpu* gpu, bool abandoningBuffer) {
439     SkASSERT(fIsActive);
440     SkASSERT(!fActiveRenderPass);
441 
442     // If we are in the process of abandoning the context then the GrResourceCache will have freed
443     // all resources before destroying the GrVkGpu. When we destroy the GrVkGpu we call end on the
444     // command buffer to keep all our state tracking consistent. However, the vulkan validation
445     // layers complain about calling end on a command buffer that contains resources that have
446     // already been deleted. From the vulkan API it isn't required to end the command buffer to
447     // delete it, so we just skip the vulkan API calls and update our own state tracking.
448     if (!abandoningBuffer) {
449         this->submitPipelineBarriers(gpu);
450 
451         GR_VK_CALL_ERRCHECK(gpu, EndCommandBuffer(fCmdBuffer));
452     }
453     this->invalidateState();
454     fIsActive = false;
455     fHasWork = false;
456 }
457 
beginRenderPass(GrVkGpu * gpu,const GrVkRenderPass * renderPass,sk_sp<const GrVkFramebuffer> framebuffer,const VkClearValue clearValues[],const GrSurface * target,const SkIRect & bounds,bool forSecondaryCB)458 bool GrVkPrimaryCommandBuffer::beginRenderPass(GrVkGpu* gpu,
459                                                const GrVkRenderPass* renderPass,
460                                                sk_sp<const GrVkFramebuffer> framebuffer,
461                                                const VkClearValue clearValues[],
462                                                const GrSurface* target,
463                                                const SkIRect& bounds,
464                                                bool forSecondaryCB) {
465     SkASSERT(fIsActive);
466     SkASSERT(!fActiveRenderPass);
467 
468     SkASSERT(framebuffer);
469 
470     this->addingWork(gpu);
471 
472     VkRenderPassBeginInfo beginInfo;
473     VkRect2D renderArea;
474     renderArea.offset = { bounds.fLeft , bounds.fTop };
475     renderArea.extent = { (uint32_t)bounds.width(), (uint32_t)bounds.height() };
476 
477     memset(&beginInfo, 0, sizeof(VkRenderPassBeginInfo));
478     beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
479     beginInfo.pNext = nullptr;
480     beginInfo.renderPass = renderPass->vkRenderPass();
481     beginInfo.framebuffer = framebuffer->framebuffer();
482     beginInfo.renderArea = renderArea;
483     beginInfo.clearValueCount = renderPass->clearValueCount();
484     beginInfo.pClearValues = clearValues;
485 
486     VkSubpassContents contents = forSecondaryCB ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
487                                                 : VK_SUBPASS_CONTENTS_INLINE;
488 
489 #ifdef SK_VK_PARTIALRENDER
490     VkRenderPassDamageRegionBeginInfo renderPassDamageRegionBeginInfo {};
491     std::vector<VkRect2D> regions;
492 
493     if (target) {
494         GrRenderTarget* renderTarget = const_cast<GrRenderTarget*>(target->asRenderTarget());
495         std::vector<SkIRect>& renderAreas = GrVkDrawAreaManager::getInstance().getDrawingArea(renderTarget);
496         if (!renderAreas.empty()) {
497             renderPassDamageRegionBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_DAMAGE_REGION_BEGIN_INFO_TYPE;
498             renderPassDamageRegionBeginInfo.pNext = nullptr;
499 
500             for (auto &rect : renderAreas) {
501                 VkRect2D vkRect = {{rect.fLeft, rect.fTop}, {rect.width(), rect.height()}};
502                 regions.push_back(vkRect);
503             }
504 
505             renderPassDamageRegionBeginInfo.regionCount = static_cast<uint32_t>(regions.size());
506             renderPassDamageRegionBeginInfo.regions = regions.data();
507             beginInfo.pNext = &renderPassDamageRegionBeginInfo;
508         }
509     }
510 #endif
511 
512     GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents));
513     fActiveRenderPass = renderPass;
514     this->addResource(renderPass);
515     this->addResource(std::move(framebuffer));
516     this->addGrSurface(sk_ref_sp(target));
517     return true;
518 }
519 
endRenderPass(const GrVkGpu * gpu)520 void GrVkPrimaryCommandBuffer::endRenderPass(const GrVkGpu* gpu) {
521     SkASSERT(fIsActive);
522     SkASSERT(fActiveRenderPass);
523     this->addingWork(gpu);
524     GR_VK_CALL(gpu->vkInterface(), CmdEndRenderPass(fCmdBuffer));
525     fActiveRenderPass = nullptr;
526 }
527 
528 
nexSubpass(GrVkGpu * gpu,bool forSecondaryCB)529 void GrVkPrimaryCommandBuffer::nexSubpass(GrVkGpu* gpu, bool forSecondaryCB) {
530     SkASSERT(fIsActive);
531     SkASSERT(fActiveRenderPass);
532     VkSubpassContents contents = forSecondaryCB ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
533                                                 : VK_SUBPASS_CONTENTS_INLINE;
534     GR_VK_CALL(gpu->vkInterface(), CmdNextSubpass(fCmdBuffer, contents));
535 }
536 
executeCommands(const GrVkGpu * gpu,std::unique_ptr<GrVkSecondaryCommandBuffer> buffer)537 void GrVkPrimaryCommandBuffer::executeCommands(const GrVkGpu* gpu,
538                                                std::unique_ptr<GrVkSecondaryCommandBuffer> buffer) {
539     // The Vulkan spec allows secondary command buffers to be executed on a primary command buffer
540     // if the command pools both were created from were created with the same queue family. However,
541     // we currently always create them from the same pool.
542     SkASSERT(fIsActive);
543     SkASSERT(!buffer->fIsActive);
544     SkASSERT(fActiveRenderPass);
545     SkASSERT(fActiveRenderPass->isCompatible(*buffer->fActiveRenderPass));
546 
547     this->addingWork(gpu);
548 
549     GR_VK_CALL(gpu->vkInterface(), CmdExecuteCommands(fCmdBuffer, 1, &buffer->fCmdBuffer));
550     fSecondaryCommandBuffers.push_back(std::move(buffer));
551     // When executing a secondary command buffer all state (besides render pass state) becomes
552     // invalidated and must be reset. This includes bound buffers, pipelines, dynamic state, etc.
553     this->invalidateState();
554 }
555 
submit_to_queue(GrVkGpu * gpu,VkQueue queue,VkFence fence,uint32_t waitCount,const VkSemaphore * waitSemaphores,const VkPipelineStageFlags * waitStages,uint32_t commandBufferCount,const VkCommandBuffer * commandBuffers,uint32_t signalCount,const VkSemaphore * signalSemaphores,GrProtected protectedContext)556 static bool submit_to_queue(GrVkGpu* gpu,
557                             VkQueue queue,
558                             VkFence fence,
559                             uint32_t waitCount,
560                             const VkSemaphore* waitSemaphores,
561                             const VkPipelineStageFlags* waitStages,
562                             uint32_t commandBufferCount,
563                             const VkCommandBuffer* commandBuffers,
564                             uint32_t signalCount,
565                             const VkSemaphore* signalSemaphores,
566                             GrProtected protectedContext) {
567     VkProtectedSubmitInfo protectedSubmitInfo;
568     if (protectedContext == GrProtected::kYes) {
569         memset(&protectedSubmitInfo, 0, sizeof(VkProtectedSubmitInfo));
570         protectedSubmitInfo.sType = VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO;
571         protectedSubmitInfo.pNext = nullptr;
572         protectedSubmitInfo.protectedSubmit = VK_TRUE;
573     }
574 
575     VkSubmitInfo submitInfo;
576     memset(&submitInfo, 0, sizeof(VkSubmitInfo));
577     submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
578     submitInfo.pNext = protectedContext == GrProtected::kYes ? &protectedSubmitInfo : nullptr;
579     submitInfo.waitSemaphoreCount = waitCount;
580     submitInfo.pWaitSemaphores = waitSemaphores;
581     submitInfo.pWaitDstStageMask = waitStages;
582     submitInfo.commandBufferCount = commandBufferCount;
583     submitInfo.pCommandBuffers = commandBuffers;
584     submitInfo.signalSemaphoreCount = signalCount;
585     submitInfo.pSignalSemaphores = signalSemaphores;
586     VkResult result;
587     GR_VK_CALL_RESULT(gpu, result, QueueSubmit(queue, 1, &submitInfo, fence));
588     return result == VK_SUCCESS;
589 }
590 
submitToQueue(GrVkGpu * gpu,VkQueue queue,SkTArray<GrVkSemaphore::Resource * > & signalSemaphores,SkTArray<GrVkSemaphore::Resource * > & waitSemaphores)591 bool GrVkPrimaryCommandBuffer::submitToQueue(
592         GrVkGpu* gpu,
593         VkQueue queue,
594         SkTArray<GrVkSemaphore::Resource*>& signalSemaphores,
595         SkTArray<GrVkSemaphore::Resource*>& waitSemaphores) {
596     SkASSERT(!fIsActive);
597 
598     VkResult err;
599     if (VK_NULL_HANDLE == fSubmitFence) {
600         VkFenceCreateInfo fenceInfo;
601         memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
602         fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
603         GR_VK_CALL_RESULT(gpu, err, CreateFence(gpu->device(), &fenceInfo, nullptr,
604                                                 &fSubmitFence));
605         if (err) {
606             fSubmitFence = VK_NULL_HANDLE;
607             return false;
608         }
609     } else {
610         // This cannot return DEVICE_LOST so we assert we succeeded.
611         GR_VK_CALL_RESULT(gpu, err, ResetFences(gpu->device(), 1, &fSubmitFence));
612         SkASSERT(err == VK_SUCCESS);
613     }
614 
615     int signalCount = signalSemaphores.count();
616     int waitCount = waitSemaphores.count();
617 
618     bool submitted = false;
619 
620     if (0 == signalCount && 0 == waitCount) {
621         // This command buffer has no dependent semaphores so we can simply just submit it to the
622         // queue with no worries.
623         submitted = submit_to_queue(
624                 gpu, queue, fSubmitFence, 0, nullptr, nullptr, 1, &fCmdBuffer, 0, nullptr,
625                 gpu->protectedContext() ? GrProtected::kYes : GrProtected::kNo);
626     } else {
627         SkTArray<VkSemaphore> vkSignalSems(signalCount);
628         for (int i = 0; i < signalCount; ++i) {
629             if (signalSemaphores[i]->shouldSignal()) {
630                 this->addResource(signalSemaphores[i]);
631                 vkSignalSems.push_back(signalSemaphores[i]->semaphore());
632             }
633         }
634 
635         SkTArray<VkSemaphore> vkWaitSems(waitCount);
636         SkTArray<VkPipelineStageFlags> vkWaitStages(waitCount);
637         for (int i = 0; i < waitCount; ++i) {
638             if (waitSemaphores[i]->shouldWait()) {
639                 this->addResource(waitSemaphores[i]);
640                 vkWaitSems.push_back(waitSemaphores[i]->semaphore());
641                 vkWaitStages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
642             }
643         }
644         submitted = submit_to_queue(gpu, queue, fSubmitFence, vkWaitSems.count(),
645                                     vkWaitSems.begin(), vkWaitStages.begin(), 1, &fCmdBuffer,
646                                     vkSignalSems.count(), vkSignalSems.begin(),
647                                     gpu->protectedContext() ? GrProtected::kYes : GrProtected::kNo);
648         if (submitted) {
649             for (int i = 0; i < signalCount; ++i) {
650                 signalSemaphores[i]->markAsSignaled();
651             }
652             for (int i = 0; i < waitCount; ++i) {
653                 waitSemaphores[i]->markAsWaited();
654             }
655         }
656     }
657 
658     if (!submitted) {
659         // Destroy the fence or else we will try to wait forever for it to finish.
660         GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr));
661         fSubmitFence = VK_NULL_HANDLE;
662         return false;
663     }
664     return true;
665 }
666 
forceSync(GrVkGpu * gpu)667 void GrVkPrimaryCommandBuffer::forceSync(GrVkGpu* gpu) {
668     if (fSubmitFence == VK_NULL_HANDLE) {
669         return;
670     }
671     GR_VK_CALL_ERRCHECK(gpu, WaitForFences(gpu->device(), 1, &fSubmitFence, true, UINT64_MAX));
672 }
673 
finished(GrVkGpu * gpu)674 bool GrVkPrimaryCommandBuffer::finished(GrVkGpu* gpu) {
675     SkASSERT(!fIsActive);
676     if (VK_NULL_HANDLE == fSubmitFence) {
677         return true;
678     }
679 
680     VkResult err;
681     GR_VK_CALL_RESULT_NOCHECK(gpu, err, GetFenceStatus(gpu->device(), fSubmitFence));
682     switch (err) {
683         case VK_SUCCESS:
684         case VK_ERROR_DEVICE_LOST:
685             return true;
686 
687         case VK_NOT_READY:
688             return false;
689 
690         default:
691             SkDebugf("Error getting fence status: %d\n", err);
692             SK_ABORT("Got an invalid fence status");
693             return false;
694     }
695 }
696 
addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc)697 void GrVkPrimaryCommandBuffer::addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc) {
698     fFinishedProcs.push_back(std::move(finishedProc));
699 }
700 
onReleaseResources()701 void GrVkPrimaryCommandBuffer::onReleaseResources() {
702     for (int i = 0; i < fSecondaryCommandBuffers.count(); ++i) {
703         fSecondaryCommandBuffers[i]->releaseResources();
704     }
705     this->callFinishedProcs();
706 }
707 
recycleSecondaryCommandBuffers(GrVkCommandPool * cmdPool)708 void GrVkPrimaryCommandBuffer::recycleSecondaryCommandBuffers(GrVkCommandPool* cmdPool) {
709     for (int i = 0; i < fSecondaryCommandBuffers.count(); ++i) {
710         fSecondaryCommandBuffers[i].release()->recycle(cmdPool);
711     }
712     fSecondaryCommandBuffers.reset();
713 }
714 
copyImage(const GrVkGpu * gpu,GrVkImage * srcImage,VkImageLayout srcLayout,GrVkImage * dstImage,VkImageLayout dstLayout,uint32_t copyRegionCount,const VkImageCopy * copyRegions)715 void GrVkPrimaryCommandBuffer::copyImage(const GrVkGpu* gpu,
716                                          GrVkImage* srcImage,
717                                          VkImageLayout srcLayout,
718                                          GrVkImage* dstImage,
719                                          VkImageLayout dstLayout,
720                                          uint32_t copyRegionCount,
721                                          const VkImageCopy* copyRegions) {
722     SkASSERT(fIsActive);
723     SkASSERT(!fActiveRenderPass);
724     this->addingWork(gpu);
725     this->addResource(srcImage->resource());
726     this->addResource(dstImage->resource());
727     GR_VK_CALL(gpu->vkInterface(), CmdCopyImage(fCmdBuffer,
728                                                 srcImage->image(),
729                                                 srcLayout,
730                                                 dstImage->image(),
731                                                 dstLayout,
732                                                 copyRegionCount,
733                                                 copyRegions));
734 }
735 
blitImage(const GrVkGpu * gpu,const GrManagedResource * srcResource,VkImage srcImage,VkImageLayout srcLayout,const GrManagedResource * dstResource,VkImage dstImage,VkImageLayout dstLayout,uint32_t blitRegionCount,const VkImageBlit * blitRegions,VkFilter filter)736 void GrVkPrimaryCommandBuffer::blitImage(const GrVkGpu* gpu,
737                                          const GrManagedResource* srcResource,
738                                          VkImage srcImage,
739                                          VkImageLayout srcLayout,
740                                          const GrManagedResource* dstResource,
741                                          VkImage dstImage,
742                                          VkImageLayout dstLayout,
743                                          uint32_t blitRegionCount,
744                                          const VkImageBlit* blitRegions,
745                                          VkFilter filter) {
746     SkASSERT(fIsActive);
747     SkASSERT(!fActiveRenderPass);
748     this->addingWork(gpu);
749     this->addResource(srcResource);
750     this->addResource(dstResource);
751     GR_VK_CALL(gpu->vkInterface(), CmdBlitImage(fCmdBuffer,
752                                                 srcImage,
753                                                 srcLayout,
754                                                 dstImage,
755                                                 dstLayout,
756                                                 blitRegionCount,
757                                                 blitRegions,
758                                                 filter));
759 }
760 
blitImage(const GrVkGpu * gpu,const GrVkImage & srcImage,const GrVkImage & dstImage,uint32_t blitRegionCount,const VkImageBlit * blitRegions,VkFilter filter)761 void GrVkPrimaryCommandBuffer::blitImage(const GrVkGpu* gpu,
762                                          const GrVkImage& srcImage,
763                                          const GrVkImage& dstImage,
764                                          uint32_t blitRegionCount,
765                                          const VkImageBlit* blitRegions,
766                                          VkFilter filter) {
767     this->blitImage(gpu,
768                     srcImage.resource(),
769                     srcImage.image(),
770                     srcImage.currentLayout(),
771                     dstImage.resource(),
772                     dstImage.image(),
773                     dstImage.currentLayout(),
774                     blitRegionCount,
775                     blitRegions,
776                     filter);
777 }
778 
779 
copyImageToBuffer(const GrVkGpu * gpu,GrVkImage * srcImage,VkImageLayout srcLayout,sk_sp<GrGpuBuffer> dstBuffer,uint32_t copyRegionCount,const VkBufferImageCopy * copyRegions)780 void GrVkPrimaryCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu,
781                                                  GrVkImage* srcImage,
782                                                  VkImageLayout srcLayout,
783                                                  sk_sp<GrGpuBuffer> dstBuffer,
784                                                  uint32_t copyRegionCount,
785                                                  const VkBufferImageCopy* copyRegions) {
786     SkASSERT(fIsActive);
787     SkASSERT(!fActiveRenderPass);
788     this->addingWork(gpu);
789     GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(dstBuffer.get());
790     GR_VK_CALL(gpu->vkInterface(), CmdCopyImageToBuffer(fCmdBuffer,
791                                                         srcImage->image(),
792                                                         srcLayout,
793                                                         vkBuffer->vkBuffer(),
794                                                         copyRegionCount,
795                                                         copyRegions));
796     this->addResource(srcImage->resource());
797     this->addGrBuffer(std::move(dstBuffer));
798 }
799 
copyBufferToImage(const GrVkGpu * gpu,VkBuffer srcBuffer,GrVkImage * dstImage,VkImageLayout dstLayout,uint32_t copyRegionCount,const VkBufferImageCopy * copyRegions)800 void GrVkPrimaryCommandBuffer::copyBufferToImage(const GrVkGpu* gpu,
801                                                  VkBuffer srcBuffer,
802                                                  GrVkImage* dstImage,
803                                                  VkImageLayout dstLayout,
804                                                  uint32_t copyRegionCount,
805                                                  const VkBufferImageCopy* copyRegions) {
806     SkASSERT(fIsActive);
807     SkASSERT(!fActiveRenderPass);
808     this->addingWork(gpu);
809 
810     GR_VK_CALL(gpu->vkInterface(), CmdCopyBufferToImage(fCmdBuffer,
811                                                         srcBuffer,
812                                                         dstImage->image(),
813                                                         dstLayout,
814                                                         copyRegionCount,
815                                                         copyRegions));
816     this->addResource(dstImage->resource());
817 }
818 
copyBuffer(GrVkGpu * gpu,sk_sp<GrGpuBuffer> srcBuffer,sk_sp<GrGpuBuffer> dstBuffer,uint32_t regionCount,const VkBufferCopy * regions)819 void GrVkPrimaryCommandBuffer::copyBuffer(GrVkGpu* gpu,
820                                           sk_sp<GrGpuBuffer> srcBuffer,
821                                           sk_sp<GrGpuBuffer> dstBuffer,
822                                           uint32_t regionCount,
823                                           const VkBufferCopy* regions) {
824     SkASSERT(fIsActive);
825     SkASSERT(!fActiveRenderPass);
826     this->addingWork(gpu);
827 #ifdef SK_DEBUG
828     for (uint32_t i = 0; i < regionCount; ++i) {
829         const VkBufferCopy& region = regions[i];
830         SkASSERT(region.size > 0);
831         SkASSERT(region.srcOffset < srcBuffer->size());
832         SkASSERT(region.dstOffset < dstBuffer->size());
833         SkASSERT(region.srcOffset + region.size <= srcBuffer->size());
834         SkASSERT(region.dstOffset + region.size <= dstBuffer->size());
835     }
836 #endif
837 
838     const GrVkBuffer* srcVk = static_cast<GrVkBuffer*>(srcBuffer.get());
839     const GrVkBuffer* dstVk = static_cast<GrVkBuffer*>(dstBuffer.get());
840 
841     GR_VK_CALL(gpu->vkInterface(), CmdCopyBuffer(fCmdBuffer,
842                                                  srcVk->vkBuffer(),
843                                                  dstVk->vkBuffer(),
844                                                  regionCount,
845                                                  regions));
846     this->addGrBuffer(std::move(srcBuffer));
847     this->addGrBuffer(std::move(dstBuffer));
848 }
849 
updateBuffer(GrVkGpu * gpu,sk_sp<GrVkBuffer> dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const void * data)850 void GrVkPrimaryCommandBuffer::updateBuffer(GrVkGpu* gpu,
851                                             sk_sp<GrVkBuffer> dstBuffer,
852                                             VkDeviceSize dstOffset,
853                                             VkDeviceSize dataSize,
854                                             const void* data) {
855     SkASSERT(fIsActive);
856     SkASSERT(!fActiveRenderPass);
857     SkASSERT(0 == (dstOffset & 0x03));  // four byte aligned
858     // TODO: handle larger transfer sizes
859     SkASSERT(dataSize <= 65536);
860     SkASSERT(0 == (dataSize & 0x03));  // four byte aligned
861     this->addingWork(gpu);
862     GR_VK_CALL(
863             gpu->vkInterface(),
864             CmdUpdateBuffer(
865                     fCmdBuffer, dstBuffer->vkBuffer(), dstOffset, dataSize, (const uint32_t*)data));
866     this->addGrBuffer(std::move(dstBuffer));
867 }
868 
clearColorImage(const GrVkGpu * gpu,GrVkImage * image,const VkClearColorValue * color,uint32_t subRangeCount,const VkImageSubresourceRange * subRanges)869 void GrVkPrimaryCommandBuffer::clearColorImage(const GrVkGpu* gpu,
870                                                GrVkImage* image,
871                                                const VkClearColorValue* color,
872                                                uint32_t subRangeCount,
873                                                const VkImageSubresourceRange* subRanges) {
874     SkASSERT(fIsActive);
875     SkASSERT(!fActiveRenderPass);
876     this->addingWork(gpu);
877     this->addResource(image->resource());
878     GR_VK_CALL(gpu->vkInterface(), CmdClearColorImage(fCmdBuffer,
879                                                       image->image(),
880                                                       image->currentLayout(),
881                                                       color,
882                                                       subRangeCount,
883                                                       subRanges));
884 }
885 
clearDepthStencilImage(const GrVkGpu * gpu,GrVkImage * image,const VkClearDepthStencilValue * color,uint32_t subRangeCount,const VkImageSubresourceRange * subRanges)886 void GrVkPrimaryCommandBuffer::clearDepthStencilImage(const GrVkGpu* gpu,
887                                                       GrVkImage* image,
888                                                       const VkClearDepthStencilValue* color,
889                                                       uint32_t subRangeCount,
890                                                       const VkImageSubresourceRange* subRanges) {
891     SkASSERT(fIsActive);
892     SkASSERT(!fActiveRenderPass);
893     this->addingWork(gpu);
894     this->addResource(image->resource());
895     GR_VK_CALL(gpu->vkInterface(), CmdClearDepthStencilImage(fCmdBuffer,
896                                                              image->image(),
897                                                              image->currentLayout(),
898                                                              color,
899                                                              subRangeCount,
900                                                              subRanges));
901 }
902 
resolveImage(GrVkGpu * gpu,const GrVkImage & srcImage,const GrVkImage & dstImage,uint32_t regionCount,const VkImageResolve * regions)903 void GrVkPrimaryCommandBuffer::resolveImage(GrVkGpu* gpu,
904                                             const GrVkImage& srcImage,
905                                             const GrVkImage& dstImage,
906                                             uint32_t regionCount,
907                                             const VkImageResolve* regions) {
908     SkASSERT(fIsActive);
909     SkASSERT(!fActiveRenderPass);
910 
911     this->addingWork(gpu);
912     this->addResource(srcImage.resource());
913     this->addResource(dstImage.resource());
914 
915     GR_VK_CALL(gpu->vkInterface(), CmdResolveImage(fCmdBuffer,
916                                                    srcImage.image(),
917                                                    srcImage.currentLayout(),
918                                                    dstImage.image(),
919                                                    dstImage.currentLayout(),
920                                                    regionCount,
921                                                    regions));
922 }
923 
onFreeGPUData(const GrVkGpu * gpu) const924 void GrVkPrimaryCommandBuffer::onFreeGPUData(const GrVkGpu* gpu) const {
925     SkASSERT(!fActiveRenderPass);
926     // Destroy the fence, if any
927     if (VK_NULL_HANDLE != fSubmitFence) {
928         GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr));
929     }
930     SkASSERT(!fSecondaryCommandBuffers.count());
931 }
932 
933 ///////////////////////////////////////////////////////////////////////////////
934 // SecondaryCommandBuffer
935 ////////////////////////////////////////////////////////////////////////////////
936 
Create(GrVkGpu * gpu,GrVkCommandPool * cmdPool)937 GrVkSecondaryCommandBuffer* GrVkSecondaryCommandBuffer::Create(GrVkGpu* gpu,
938                                                                GrVkCommandPool* cmdPool) {
939     SkASSERT(cmdPool);
940     const VkCommandBufferAllocateInfo cmdInfo = {
941         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
942         nullptr,                                          // pNext
943         cmdPool->vkCommandPool(),                         // commandPool
944         VK_COMMAND_BUFFER_LEVEL_SECONDARY,                // level
945         1                                                 // bufferCount
946     };
947 
948     VkCommandBuffer cmdBuffer;
949     VkResult err;
950     GR_VK_CALL_RESULT(gpu, err, AllocateCommandBuffers(gpu->device(), &cmdInfo, &cmdBuffer));
951     if (err) {
952         return nullptr;
953     }
954     return new GrVkSecondaryCommandBuffer(cmdBuffer, /*externalRenderPass=*/nullptr);
955 }
956 
Create(VkCommandBuffer cmdBuffer,const GrVkRenderPass * externalRenderPass)957 GrVkSecondaryCommandBuffer* GrVkSecondaryCommandBuffer::Create(
958         VkCommandBuffer cmdBuffer, const GrVkRenderPass* externalRenderPass) {
959     return new GrVkSecondaryCommandBuffer(cmdBuffer, externalRenderPass);
960 }
961 
begin(GrVkGpu * gpu,const GrVkFramebuffer * framebuffer,const GrVkRenderPass * compatibleRenderPass)962 void GrVkSecondaryCommandBuffer::begin(GrVkGpu* gpu, const GrVkFramebuffer* framebuffer,
963                                        const GrVkRenderPass* compatibleRenderPass) {
964     SkASSERT(!fIsActive);
965     SkASSERT(!this->isWrapped());
966     SkASSERT(compatibleRenderPass);
967     fActiveRenderPass = compatibleRenderPass;
968 
969     VkCommandBufferInheritanceInfo inheritanceInfo;
970     memset(&inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo));
971     inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
972     inheritanceInfo.pNext = nullptr;
973     inheritanceInfo.renderPass = fActiveRenderPass->vkRenderPass();
974     inheritanceInfo.subpass = 0; // Currently only using 1 subpass for each render pass
975     inheritanceInfo.framebuffer = framebuffer ? framebuffer->framebuffer() : VK_NULL_HANDLE;
976     inheritanceInfo.occlusionQueryEnable = false;
977     inheritanceInfo.queryFlags = 0;
978     inheritanceInfo.pipelineStatistics = 0;
979 
980     VkCommandBufferBeginInfo cmdBufferBeginInfo;
981     memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
982     cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
983     cmdBufferBeginInfo.pNext = nullptr;
984     cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT |
985             VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
986     cmdBufferBeginInfo.pInheritanceInfo = &inheritanceInfo;
987 
988     GR_VK_CALL_ERRCHECK(gpu, BeginCommandBuffer(fCmdBuffer, &cmdBufferBeginInfo));
989 
990     fIsActive = true;
991 }
992 
end(GrVkGpu * gpu)993 void GrVkSecondaryCommandBuffer::end(GrVkGpu* gpu) {
994     SkASSERT(fIsActive);
995     SkASSERT(!this->isWrapped());
996     GR_VK_CALL_ERRCHECK(gpu, EndCommandBuffer(fCmdBuffer));
997     this->invalidateState();
998     fHasWork = false;
999     fIsActive = false;
1000 }
1001 
recycle(GrVkCommandPool * cmdPool)1002 void GrVkSecondaryCommandBuffer::recycle(GrVkCommandPool* cmdPool) {
1003     if (this->isWrapped()) {
1004         delete this;
1005     } else {
1006         cmdPool->recycleSecondaryCommandBuffer(this);
1007     }
1008 }
1009 
1010