• 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 "GrVkCommandBuffer.h"
9 
10 #include "GrVkFramebuffer.h"
11 #include "GrVkImageView.h"
12 #include "GrVkPipeline.h"
13 #include "GrVkRenderPass.h"
14 #include "GrVkRenderTarget.h"
15 #include "GrVkPipelineState.h"
16 #include "GrVkTransferBuffer.h"
17 #include "GrVkUtil.h"
18 #include "SkRect.h"
19 
invalidateState()20 void GrVkCommandBuffer::invalidateState() {
21     fBoundVertexBuffer = VK_NULL_HANDLE;
22     fBoundVertexBufferIsValid = false;
23     fBoundIndexBuffer = VK_NULL_HANDLE;
24     fBoundIndexBufferIsValid = false;
25 
26     memset(&fCachedViewport, 0, sizeof(VkViewport));
27     fCachedViewport.width = - 1.0f; // Viewport must have a width greater than 0
28 
29     memset(&fCachedScissor, 0, sizeof(VkRect2D));
30     fCachedScissor.offset.x = -1; // Scissor offset must be greater that 0 to be valid
31 
32     for (int i = 0; i < 4; ++i) {
33         fCachedBlendConstant[i] = -1.0;
34     }
35 }
36 
freeGPUData(const GrVkGpu * gpu) const37 void GrVkCommandBuffer::freeGPUData(const GrVkGpu* gpu) const {
38     SkASSERT(!fIsActive);
39     for (int i = 0; i < fTrackedResources.count(); ++i) {
40         fTrackedResources[i]->unref(gpu);
41     }
42 
43     for (int i = 0; i < fTrackedRecycledResources.count(); ++i) {
44         fTrackedRecycledResources[i]->recycle(const_cast<GrVkGpu*>(gpu));
45     }
46 
47     GR_VK_CALL(gpu->vkInterface(), FreeCommandBuffers(gpu->device(), gpu->cmdPool(),
48                                                       1, &fCmdBuffer));
49 
50     this->onFreeGPUData(gpu);
51 }
52 
abandonSubResources() const53 void GrVkCommandBuffer::abandonSubResources() const {
54     for (int i = 0; i < fTrackedResources.count(); ++i) {
55         fTrackedResources[i]->unrefAndAbandon();
56     }
57 
58     for (int i = 0; i < fTrackedRecycledResources.count(); ++i) {
59         // We don't recycle resources when abandoning them.
60         fTrackedRecycledResources[i]->unrefAndAbandon();
61     }
62 }
63 
reset(GrVkGpu * gpu)64 void GrVkCommandBuffer::reset(GrVkGpu* gpu) {
65     SkASSERT(!fIsActive);
66     for (int i = 0; i < fTrackedResources.count(); ++i) {
67         fTrackedResources[i]->unref(gpu);
68     }
69     for (int i = 0; i < fTrackedRecycledResources.count(); ++i) {
70         fTrackedRecycledResources[i]->recycle(const_cast<GrVkGpu*>(gpu));
71     }
72 
73     if (++fNumResets > kNumRewindResetsBeforeFullReset) {
74         fTrackedResources.reset();
75         fTrackedRecycledResources.reset();
76         fTrackedResources.setReserve(kInitialTrackedResourcesCount);
77         fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount);
78         fNumResets = 0;
79     } else {
80         fTrackedResources.rewind();
81         fTrackedRecycledResources.rewind();
82     }
83 
84 
85     this->invalidateState();
86 
87     // we will retain resources for later use
88     VkCommandBufferResetFlags flags = 0;
89     GR_VK_CALL(gpu->vkInterface(), ResetCommandBuffer(fCmdBuffer, flags));
90 
91     this->onReset(gpu);
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 // CommandBuffer commands
96 ////////////////////////////////////////////////////////////////////////////////
97 
pipelineBarrier(const GrVkGpu * gpu,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,bool byRegion,BarrierType barrierType,void * barrier) const98 void GrVkCommandBuffer::pipelineBarrier(const GrVkGpu* gpu,
99                                         VkPipelineStageFlags srcStageMask,
100                                         VkPipelineStageFlags dstStageMask,
101                                         bool byRegion,
102                                         BarrierType barrierType,
103                                         void* barrier) const {
104     SkASSERT(fIsActive);
105     // For images we can have barriers inside of render passes but they require us to add more
106     // support in subpasses which need self dependencies to have barriers inside them. Also, we can
107     // never have buffer barriers inside of a render pass. For now we will just assert that we are
108     // not in a render pass.
109     SkASSERT(!fActiveRenderPass);
110     VkDependencyFlags dependencyFlags = byRegion ? VK_DEPENDENCY_BY_REGION_BIT : 0;
111 
112     switch (barrierType) {
113         case kMemory_BarrierType: {
114             const VkMemoryBarrier* barrierPtr = reinterpret_cast<VkMemoryBarrier*>(barrier);
115             GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask,
116                                                               dstStageMask, dependencyFlags,
117                                                               1, barrierPtr,
118                                                               0, nullptr,
119                                                               0, nullptr));
120             break;
121         }
122 
123         case kBufferMemory_BarrierType: {
124             const VkBufferMemoryBarrier* barrierPtr =
125                                                  reinterpret_cast<VkBufferMemoryBarrier*>(barrier);
126             GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask,
127                                                               dstStageMask, dependencyFlags,
128                                                               0, nullptr,
129                                                               1, barrierPtr,
130                                                               0, nullptr));
131             break;
132         }
133 
134         case kImageMemory_BarrierType: {
135             const VkImageMemoryBarrier* barrierPtr =
136                                                   reinterpret_cast<VkImageMemoryBarrier*>(barrier);
137             GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask,
138                                                               dstStageMask, dependencyFlags,
139                                                               0, nullptr,
140                                                               0, nullptr,
141                                                               1, barrierPtr));
142             break;
143         }
144     }
145 
146 }
147 
clearAttachments(const GrVkGpu * gpu,int numAttachments,const VkClearAttachment * attachments,int numRects,const VkClearRect * clearRects) const148 void GrVkCommandBuffer::clearAttachments(const GrVkGpu* gpu,
149                                          int numAttachments,
150                                          const VkClearAttachment* attachments,
151                                          int numRects,
152                                          const VkClearRect* clearRects) const {
153     SkASSERT(fIsActive);
154     SkASSERT(fActiveRenderPass);
155     SkASSERT(numAttachments > 0);
156     SkASSERT(numRects > 0);
157 #ifdef SK_DEBUG
158     for (int i = 0; i < numAttachments; ++i) {
159         if (attachments[i].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
160             uint32_t testIndex;
161             SkAssertResult(fActiveRenderPass->colorAttachmentIndex(&testIndex));
162             SkASSERT(testIndex == attachments[i].colorAttachment);
163         }
164     }
165 #endif
166     GR_VK_CALL(gpu->vkInterface(), CmdClearAttachments(fCmdBuffer,
167                                                        numAttachments,
168                                                        attachments,
169                                                        numRects,
170                                                        clearRects));
171 }
172 
bindDescriptorSets(const GrVkGpu * gpu,GrVkPipelineState * pipelineState,VkPipelineLayout layout,uint32_t firstSet,uint32_t setCount,const VkDescriptorSet * descriptorSets,uint32_t dynamicOffsetCount,const uint32_t * dynamicOffsets)173 void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
174                                            GrVkPipelineState* pipelineState,
175                                            VkPipelineLayout layout,
176                                            uint32_t firstSet,
177                                            uint32_t setCount,
178                                            const VkDescriptorSet* descriptorSets,
179                                            uint32_t dynamicOffsetCount,
180                                            const uint32_t* dynamicOffsets) {
181     SkASSERT(fIsActive);
182     GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer,
183                                                          VK_PIPELINE_BIND_POINT_GRAPHICS,
184                                                          layout,
185                                                          firstSet,
186                                                          setCount,
187                                                          descriptorSets,
188                                                          dynamicOffsetCount,
189                                                          dynamicOffsets));
190     pipelineState->addUniformResources(*this);
191 }
192 
bindDescriptorSets(const GrVkGpu * gpu,const SkTArray<const GrVkRecycledResource * > & recycled,const SkTArray<const GrVkResource * > & resources,VkPipelineLayout layout,uint32_t firstSet,uint32_t setCount,const VkDescriptorSet * descriptorSets,uint32_t dynamicOffsetCount,const uint32_t * dynamicOffsets)193 void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
194                                            const SkTArray<const GrVkRecycledResource*>& recycled,
195                                            const SkTArray<const GrVkResource*>& resources,
196                                            VkPipelineLayout layout,
197                                            uint32_t firstSet,
198                                            uint32_t setCount,
199                                            const VkDescriptorSet* descriptorSets,
200                                            uint32_t dynamicOffsetCount,
201                                            const uint32_t* dynamicOffsets) {
202     SkASSERT(fIsActive);
203     GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer,
204                                                          VK_PIPELINE_BIND_POINT_GRAPHICS,
205                                                          layout,
206                                                          firstSet,
207                                                          setCount,
208                                                          descriptorSets,
209                                                          dynamicOffsetCount,
210                                                          dynamicOffsets));
211     for (int i = 0; i < recycled.count(); ++i) {
212         this->addRecycledResource(recycled[i]);
213     }
214     for (int i = 0; i < resources.count(); ++i) {
215         this->addResource(resources[i]);
216     }
217 }
218 
bindPipeline(const GrVkGpu * gpu,const GrVkPipeline * pipeline)219 void GrVkCommandBuffer::bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline) {
220     SkASSERT(fIsActive);
221     GR_VK_CALL(gpu->vkInterface(), CmdBindPipeline(fCmdBuffer,
222                                                    VK_PIPELINE_BIND_POINT_GRAPHICS,
223                                                    pipeline->pipeline()));
224     this->addResource(pipeline);
225 }
226 
drawIndexed(const GrVkGpu * gpu,uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance) const227 void GrVkCommandBuffer::drawIndexed(const GrVkGpu* gpu,
228                                     uint32_t indexCount,
229                                     uint32_t instanceCount,
230                                     uint32_t firstIndex,
231                                     int32_t vertexOffset,
232                                     uint32_t firstInstance) const {
233     SkASSERT(fIsActive);
234     SkASSERT(fActiveRenderPass);
235     GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexed(fCmdBuffer,
236                                                   indexCount,
237                                                   instanceCount,
238                                                   firstIndex,
239                                                   vertexOffset,
240                                                   firstInstance));
241 }
242 
draw(const GrVkGpu * gpu,uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance) const243 void GrVkCommandBuffer::draw(const GrVkGpu* gpu,
244                              uint32_t vertexCount,
245                              uint32_t instanceCount,
246                              uint32_t firstVertex,
247                              uint32_t firstInstance) const {
248     SkASSERT(fIsActive);
249     SkASSERT(fActiveRenderPass);
250     GR_VK_CALL(gpu->vkInterface(), CmdDraw(fCmdBuffer,
251                                            vertexCount,
252                                            instanceCount,
253                                            firstVertex,
254                                            firstInstance));
255 }
256 
setViewport(const GrVkGpu * gpu,uint32_t firstViewport,uint32_t viewportCount,const VkViewport * viewports)257 void GrVkCommandBuffer::setViewport(const GrVkGpu* gpu,
258                                     uint32_t firstViewport,
259                                     uint32_t viewportCount,
260                                     const VkViewport* viewports) {
261     SkASSERT(fIsActive);
262     SkASSERT(1 == viewportCount);
263     if (memcmp(viewports, &fCachedViewport, sizeof(VkViewport))) {
264         GR_VK_CALL(gpu->vkInterface(), CmdSetViewport(fCmdBuffer,
265                                                       firstViewport,
266                                                       viewportCount,
267                                                       viewports));
268         fCachedViewport = viewports[0];
269     }
270 }
271 
setScissor(const GrVkGpu * gpu,uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * scissors)272 void GrVkCommandBuffer::setScissor(const GrVkGpu* gpu,
273                                    uint32_t firstScissor,
274                                    uint32_t scissorCount,
275                                    const VkRect2D* scissors) {
276     SkASSERT(fIsActive);
277     SkASSERT(1 == scissorCount);
278     if (memcmp(scissors, &fCachedScissor, sizeof(VkRect2D))) {
279         GR_VK_CALL(gpu->vkInterface(), CmdSetScissor(fCmdBuffer,
280                                                      firstScissor,
281                                                      scissorCount,
282                                                      scissors));
283         fCachedScissor = scissors[0];
284     }
285 }
286 
setBlendConstants(const GrVkGpu * gpu,const float blendConstants[4])287 void GrVkCommandBuffer::setBlendConstants(const GrVkGpu* gpu,
288                                           const float blendConstants[4]) {
289     SkASSERT(fIsActive);
290     if (memcmp(blendConstants, fCachedBlendConstant, 4 * sizeof(float))) {
291         GR_VK_CALL(gpu->vkInterface(), CmdSetBlendConstants(fCmdBuffer, blendConstants));
292         memcpy(fCachedBlendConstant, blendConstants, 4 * sizeof(float));
293     }
294 }
295 
296 ///////////////////////////////////////////////////////////////////////////////
297 // PrimaryCommandBuffer
298 ////////////////////////////////////////////////////////////////////////////////
~GrVkPrimaryCommandBuffer()299 GrVkPrimaryCommandBuffer::~GrVkPrimaryCommandBuffer() {
300     // Should have ended any render pass we're in the middle of
301     SkASSERT(!fActiveRenderPass);
302 }
303 
Create(const GrVkGpu * gpu,VkCommandPool cmdPool)304 GrVkPrimaryCommandBuffer* GrVkPrimaryCommandBuffer::Create(const GrVkGpu* gpu,
305                                                            VkCommandPool cmdPool) {
306     const VkCommandBufferAllocateInfo cmdInfo = {
307         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
308         NULL,                                             // pNext
309         cmdPool,                                          // commandPool
310         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                  // level
311         1                                                 // bufferCount
312     };
313 
314     VkCommandBuffer cmdBuffer;
315     VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateCommandBuffers(gpu->device(),
316                                                                          &cmdInfo,
317                                                                          &cmdBuffer));
318     if (err) {
319         return nullptr;
320     }
321     return new GrVkPrimaryCommandBuffer(cmdBuffer);
322 }
323 
begin(const GrVkGpu * gpu)324 void GrVkPrimaryCommandBuffer::begin(const GrVkGpu* gpu) {
325     SkASSERT(!fIsActive);
326     VkCommandBufferBeginInfo cmdBufferBeginInfo;
327     memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
328     cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
329     cmdBufferBeginInfo.pNext = nullptr;
330     cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
331     cmdBufferBeginInfo.pInheritanceInfo = nullptr;
332 
333     GR_VK_CALL_ERRCHECK(gpu->vkInterface(), BeginCommandBuffer(fCmdBuffer,
334                                                                &cmdBufferBeginInfo));
335     fIsActive = true;
336 }
337 
end(const GrVkGpu * gpu)338 void GrVkPrimaryCommandBuffer::end(const GrVkGpu* gpu) {
339     SkASSERT(fIsActive);
340     SkASSERT(!fActiveRenderPass);
341     GR_VK_CALL_ERRCHECK(gpu->vkInterface(), EndCommandBuffer(fCmdBuffer));
342     this->invalidateState();
343     fIsActive = false;
344 }
345 
beginRenderPass(const GrVkGpu * gpu,const GrVkRenderPass * renderPass,const VkClearValue * clearValues,const GrVkRenderTarget & target,const SkIRect & bounds,bool forSecondaryCB)346 void GrVkPrimaryCommandBuffer::beginRenderPass(const GrVkGpu* gpu,
347                                                const GrVkRenderPass* renderPass,
348                                                const VkClearValue* clearValues,
349                                                const GrVkRenderTarget& target,
350                                                const SkIRect& bounds,
351                                                bool forSecondaryCB) {
352     SkASSERT(fIsActive);
353     SkASSERT(!fActiveRenderPass);
354     SkASSERT(renderPass->isCompatible(target));
355 
356     VkRenderPassBeginInfo beginInfo;
357     VkRect2D renderArea;
358     renderArea.offset = { bounds.fLeft , bounds.fTop };
359     renderArea.extent = { (uint32_t)bounds.width(), (uint32_t)bounds.height() };
360 
361     memset(&beginInfo, 0, sizeof(VkRenderPassBeginInfo));
362     beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
363     beginInfo.pNext = nullptr;
364     beginInfo.renderPass = renderPass->vkRenderPass();
365     beginInfo.framebuffer = target.framebuffer()->framebuffer();
366     beginInfo.renderArea = renderArea;
367     beginInfo.clearValueCount = renderPass->clearValueCount();
368     beginInfo.pClearValues = clearValues;
369 
370     VkSubpassContents contents = forSecondaryCB ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
371                                                 : VK_SUBPASS_CONTENTS_INLINE;
372 
373     GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents));
374     fActiveRenderPass = renderPass;
375     this->addResource(renderPass);
376     target.addResources(*this);
377 }
378 
endRenderPass(const GrVkGpu * gpu)379 void GrVkPrimaryCommandBuffer::endRenderPass(const GrVkGpu* gpu) {
380     SkASSERT(fIsActive);
381     SkASSERT(fActiveRenderPass);
382     GR_VK_CALL(gpu->vkInterface(), CmdEndRenderPass(fCmdBuffer));
383     fActiveRenderPass = nullptr;
384 }
385 
executeCommands(const GrVkGpu * gpu,GrVkSecondaryCommandBuffer * buffer)386 void GrVkPrimaryCommandBuffer::executeCommands(const GrVkGpu* gpu,
387                                                GrVkSecondaryCommandBuffer* buffer) {
388     SkASSERT(fIsActive);
389     SkASSERT(!buffer->fIsActive);
390     SkASSERT(fActiveRenderPass);
391     SkASSERT(fActiveRenderPass->isCompatible(*buffer->fActiveRenderPass));
392 
393     GR_VK_CALL(gpu->vkInterface(), CmdExecuteCommands(fCmdBuffer, 1, &buffer->fCmdBuffer));
394     buffer->ref();
395     fSecondaryCommandBuffers.push_back(buffer);
396     // When executing a secondary command buffer all state (besides render pass state) becomes
397     // invalidated and must be reset. This includes bound buffers, pipelines, dynamic state, etc.
398     this->invalidateState();
399 }
400 
submitToQueue(const GrVkGpu * gpu,VkQueue queue,GrVkGpu::SyncQueue sync,const GrVkSemaphore::Resource * signalSemaphore,SkTArray<const GrVkSemaphore::Resource * > & waitSemaphores)401 void GrVkPrimaryCommandBuffer::submitToQueue(
402         const GrVkGpu* gpu,
403         VkQueue queue,
404         GrVkGpu::SyncQueue sync,
405         const GrVkSemaphore::Resource* signalSemaphore,
406         SkTArray<const GrVkSemaphore::Resource*>& waitSemaphores) {
407     SkASSERT(!fIsActive);
408 
409     VkResult err;
410     if (VK_NULL_HANDLE == fSubmitFence) {
411         VkFenceCreateInfo fenceInfo;
412         memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
413         fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
414         err = GR_VK_CALL(gpu->vkInterface(), CreateFence(gpu->device(), &fenceInfo, nullptr,
415                                                          &fSubmitFence));
416         SkASSERT(!err);
417     } else {
418         GR_VK_CALL(gpu->vkInterface(), ResetFences(gpu->device(), 1, &fSubmitFence));
419     }
420 
421     if (signalSemaphore) {
422         this->addResource(signalSemaphore);
423     }
424 
425     int waitCount = waitSemaphores.count();
426     SkTArray<VkSemaphore> vkWaitSems(waitCount);
427     SkTArray<VkPipelineStageFlags> vkWaitStages(waitCount);
428     if (waitCount) {
429         for (int i = 0; i < waitCount; ++i) {
430             this->addResource(waitSemaphores[i]);
431             vkWaitSems.push_back(waitSemaphores[i]->semaphore());
432             vkWaitStages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
433         }
434     }
435     SkTArray<VkSemaphore> vkSignalSem;
436     if (signalSemaphore) {
437         vkSignalSem.push_back(signalSemaphore->semaphore());
438     }
439 
440     VkSubmitInfo submitInfo;
441     memset(&submitInfo, 0, sizeof(VkSubmitInfo));
442     submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
443     submitInfo.pNext = nullptr;
444     submitInfo.waitSemaphoreCount = waitCount;
445     submitInfo.pWaitSemaphores = vkWaitSems.begin();
446     submitInfo.pWaitDstStageMask = vkWaitStages.begin();
447     submitInfo.commandBufferCount = 1;
448     submitInfo.pCommandBuffers = &fCmdBuffer;
449     submitInfo.signalSemaphoreCount = vkSignalSem.count();
450     submitInfo.pSignalSemaphores = vkSignalSem.begin();
451     GR_VK_CALL_ERRCHECK(gpu->vkInterface(), QueueSubmit(queue, 1, &submitInfo, fSubmitFence));
452 
453     if (GrVkGpu::kForce_SyncQueue == sync) {
454         err = GR_VK_CALL(gpu->vkInterface(),
455                          WaitForFences(gpu->device(), 1, &fSubmitFence, true, UINT64_MAX));
456         if (VK_TIMEOUT == err) {
457             SkDebugf("Fence failed to signal: %d\n", err);
458             SkFAIL("failing");
459         }
460         SkASSERT(!err);
461 
462         // Destroy the fence
463         GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr));
464         fSubmitFence = VK_NULL_HANDLE;
465     }
466 }
467 
finished(const GrVkGpu * gpu) const468 bool GrVkPrimaryCommandBuffer::finished(const GrVkGpu* gpu) const {
469     if (VK_NULL_HANDLE == fSubmitFence) {
470         return true;
471     }
472 
473     VkResult err = GR_VK_CALL(gpu->vkInterface(), GetFenceStatus(gpu->device(), fSubmitFence));
474     switch (err) {
475         case VK_SUCCESS:
476             return true;
477 
478         case VK_NOT_READY:
479             return false;
480 
481         default:
482             SkDebugf("Error getting fence status: %d\n", err);
483             SkFAIL("failing");
484             break;
485     }
486 
487     return false;
488 }
489 
onReset(GrVkGpu * gpu)490 void GrVkPrimaryCommandBuffer::onReset(GrVkGpu* gpu) {
491     for (int i = 0; i < fSecondaryCommandBuffers.count(); ++i) {
492         gpu->resourceProvider().recycleSecondaryCommandBuffer(fSecondaryCommandBuffers[i]);
493     }
494     fSecondaryCommandBuffers.reset();
495 }
496 
copyImage(const GrVkGpu * gpu,GrVkImage * srcImage,VkImageLayout srcLayout,GrVkImage * dstImage,VkImageLayout dstLayout,uint32_t copyRegionCount,const VkImageCopy * copyRegions)497 void GrVkPrimaryCommandBuffer::copyImage(const GrVkGpu* gpu,
498                                          GrVkImage* srcImage,
499                                          VkImageLayout srcLayout,
500                                          GrVkImage* dstImage,
501                                          VkImageLayout dstLayout,
502                                          uint32_t copyRegionCount,
503                                          const VkImageCopy* copyRegions) {
504     SkASSERT(fIsActive);
505     SkASSERT(!fActiveRenderPass);
506     this->addResource(srcImage->resource());
507     this->addResource(dstImage->resource());
508     GR_VK_CALL(gpu->vkInterface(), CmdCopyImage(fCmdBuffer,
509                                                 srcImage->image(),
510                                                 srcLayout,
511                                                 dstImage->image(),
512                                                 dstLayout,
513                                                 copyRegionCount,
514                                                 copyRegions));
515 }
516 
blitImage(const GrVkGpu * gpu,const GrVkResource * srcResource,VkImage srcImage,VkImageLayout srcLayout,const GrVkResource * dstResource,VkImage dstImage,VkImageLayout dstLayout,uint32_t blitRegionCount,const VkImageBlit * blitRegions,VkFilter filter)517 void GrVkPrimaryCommandBuffer::blitImage(const GrVkGpu* gpu,
518                                          const GrVkResource* srcResource,
519                                          VkImage srcImage,
520                                          VkImageLayout srcLayout,
521                                          const GrVkResource* dstResource,
522                                          VkImage dstImage,
523                                          VkImageLayout dstLayout,
524                                          uint32_t blitRegionCount,
525                                          const VkImageBlit* blitRegions,
526                                          VkFilter filter) {
527     SkASSERT(fIsActive);
528     SkASSERT(!fActiveRenderPass);
529     this->addResource(srcResource);
530     this->addResource(dstResource);
531     GR_VK_CALL(gpu->vkInterface(), CmdBlitImage(fCmdBuffer,
532                                                 srcImage,
533                                                 srcLayout,
534                                                 dstImage,
535                                                 dstLayout,
536                                                 blitRegionCount,
537                                                 blitRegions,
538                                                 filter));
539 }
540 
copyImageToBuffer(const GrVkGpu * gpu,GrVkImage * srcImage,VkImageLayout srcLayout,GrVkTransferBuffer * dstBuffer,uint32_t copyRegionCount,const VkBufferImageCopy * copyRegions)541 void GrVkPrimaryCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu,
542                                                  GrVkImage* srcImage,
543                                                  VkImageLayout srcLayout,
544                                                  GrVkTransferBuffer* dstBuffer,
545                                                  uint32_t copyRegionCount,
546                                                  const VkBufferImageCopy* copyRegions) {
547     SkASSERT(fIsActive);
548     SkASSERT(!fActiveRenderPass);
549     this->addResource(srcImage->resource());
550     this->addResource(dstBuffer->resource());
551     GR_VK_CALL(gpu->vkInterface(), CmdCopyImageToBuffer(fCmdBuffer,
552                                                         srcImage->image(),
553                                                         srcLayout,
554                                                         dstBuffer->buffer(),
555                                                         copyRegionCount,
556                                                         copyRegions));
557 }
558 
copyBufferToImage(const GrVkGpu * gpu,GrVkTransferBuffer * srcBuffer,GrVkImage * dstImage,VkImageLayout dstLayout,uint32_t copyRegionCount,const VkBufferImageCopy * copyRegions)559 void GrVkPrimaryCommandBuffer::copyBufferToImage(const GrVkGpu* gpu,
560                                                  GrVkTransferBuffer* srcBuffer,
561                                                  GrVkImage* dstImage,
562                                                  VkImageLayout dstLayout,
563                                                  uint32_t copyRegionCount,
564                                                  const VkBufferImageCopy* copyRegions) {
565     SkASSERT(fIsActive);
566     SkASSERT(!fActiveRenderPass);
567     this->addResource(srcBuffer->resource());
568     this->addResource(dstImage->resource());
569     GR_VK_CALL(gpu->vkInterface(), CmdCopyBufferToImage(fCmdBuffer,
570                                                         srcBuffer->buffer(),
571                                                         dstImage->image(),
572                                                         dstLayout,
573                                                         copyRegionCount,
574                                                         copyRegions));
575 }
576 
updateBuffer(GrVkGpu * gpu,GrVkBuffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const void * data)577 void GrVkPrimaryCommandBuffer::updateBuffer(GrVkGpu* gpu,
578                                             GrVkBuffer* dstBuffer,
579                                             VkDeviceSize dstOffset,
580                                             VkDeviceSize dataSize,
581                                             const void* data) {
582     SkASSERT(fIsActive);
583     SkASSERT(!fActiveRenderPass);
584     SkASSERT(0 == (dstOffset & 0x03));   // four byte aligned
585     // TODO: handle larger transfer sizes
586     SkASSERT(dataSize <= 65536);
587     SkASSERT(0 == (dataSize & 0x03));    // four byte aligned
588     this->addResource(dstBuffer->resource());
589     GR_VK_CALL(gpu->vkInterface(), CmdUpdateBuffer(fCmdBuffer,
590                                                    dstBuffer->buffer(),
591                                                    dstOffset,
592                                                    dataSize,
593                                                    (const uint32_t*) data));
594 }
595 
clearColorImage(const GrVkGpu * gpu,GrVkImage * image,const VkClearColorValue * color,uint32_t subRangeCount,const VkImageSubresourceRange * subRanges)596 void GrVkPrimaryCommandBuffer::clearColorImage(const GrVkGpu* gpu,
597                                                GrVkImage* image,
598                                                const VkClearColorValue* color,
599                                                uint32_t subRangeCount,
600                                                const VkImageSubresourceRange* subRanges) {
601     SkASSERT(fIsActive);
602     SkASSERT(!fActiveRenderPass);
603     this->addResource(image->resource());
604     GR_VK_CALL(gpu->vkInterface(), CmdClearColorImage(fCmdBuffer,
605                                                       image->image(),
606                                                       image->currentLayout(),
607                                                       color,
608                                                       subRangeCount,
609                                                       subRanges));
610 }
611 
clearDepthStencilImage(const GrVkGpu * gpu,GrVkImage * image,const VkClearDepthStencilValue * color,uint32_t subRangeCount,const VkImageSubresourceRange * subRanges)612 void GrVkPrimaryCommandBuffer::clearDepthStencilImage(const GrVkGpu* gpu,
613                                                       GrVkImage* image,
614                                                       const VkClearDepthStencilValue* color,
615                                                       uint32_t subRangeCount,
616                                                       const VkImageSubresourceRange* subRanges) {
617     SkASSERT(fIsActive);
618     SkASSERT(!fActiveRenderPass);
619     this->addResource(image->resource());
620     GR_VK_CALL(gpu->vkInterface(), CmdClearDepthStencilImage(fCmdBuffer,
621                                                              image->image(),
622                                                              image->currentLayout(),
623                                                              color,
624                                                              subRangeCount,
625                                                              subRanges));
626 }
627 
resolveImage(GrVkGpu * gpu,const GrVkImage & srcImage,const GrVkImage & dstImage,uint32_t regionCount,const VkImageResolve * regions)628 void GrVkPrimaryCommandBuffer::resolveImage(GrVkGpu* gpu,
629                                             const GrVkImage& srcImage,
630                                             const GrVkImage& dstImage,
631                                             uint32_t regionCount,
632                                             const VkImageResolve* regions) {
633     SkASSERT(fIsActive);
634     SkASSERT(!fActiveRenderPass);
635 
636     this->addResource(srcImage.resource());
637     this->addResource(dstImage.resource());
638 
639     GR_VK_CALL(gpu->vkInterface(), CmdResolveImage(fCmdBuffer,
640                                                    srcImage.image(),
641                                                    srcImage.currentLayout(),
642                                                    dstImage.image(),
643                                                    dstImage.currentLayout(),
644                                                    regionCount,
645                                                    regions));
646 }
647 
onFreeGPUData(const GrVkGpu * gpu) const648 void GrVkPrimaryCommandBuffer::onFreeGPUData(const GrVkGpu* gpu) const {
649     SkASSERT(!fActiveRenderPass);
650     // Destroy the fence, if any
651     if (VK_NULL_HANDLE != fSubmitFence) {
652         GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr));
653     }
654 }
655 
656 ///////////////////////////////////////////////////////////////////////////////
657 // SecondaryCommandBuffer
658 ////////////////////////////////////////////////////////////////////////////////
659 
Create(const GrVkGpu * gpu,VkCommandPool cmdPool)660 GrVkSecondaryCommandBuffer* GrVkSecondaryCommandBuffer::Create(const GrVkGpu* gpu,
661                                                                VkCommandPool cmdPool) {
662     const VkCommandBufferAllocateInfo cmdInfo = {
663         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
664         NULL,                                             // pNext
665         cmdPool,                                          // commandPool
666         VK_COMMAND_BUFFER_LEVEL_SECONDARY,                // level
667         1                                                 // bufferCount
668     };
669 
670     VkCommandBuffer cmdBuffer;
671     VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateCommandBuffers(gpu->device(),
672                                                                          &cmdInfo,
673                                                                          &cmdBuffer));
674     if (err) {
675         return nullptr;
676     }
677     return new GrVkSecondaryCommandBuffer(cmdBuffer);
678 }
679 
680 
begin(const GrVkGpu * gpu,const GrVkFramebuffer * framebuffer,const GrVkRenderPass * compatibleRenderPass)681 void GrVkSecondaryCommandBuffer::begin(const GrVkGpu* gpu, const GrVkFramebuffer* framebuffer,
682                                        const GrVkRenderPass* compatibleRenderPass) {
683     SkASSERT(!fIsActive);
684     SkASSERT(compatibleRenderPass);
685     fActiveRenderPass = compatibleRenderPass;
686 
687     VkCommandBufferInheritanceInfo inheritanceInfo;
688     memset(&inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo));
689     inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
690     inheritanceInfo.pNext = nullptr;
691     inheritanceInfo.renderPass = fActiveRenderPass->vkRenderPass();
692     inheritanceInfo.subpass = 0; // Currently only using 1 subpass for each render pass
693     inheritanceInfo.framebuffer = framebuffer ? framebuffer->framebuffer() : VK_NULL_HANDLE;
694     inheritanceInfo.occlusionQueryEnable = false;
695     inheritanceInfo.queryFlags = 0;
696     inheritanceInfo.pipelineStatistics = 0;
697 
698     VkCommandBufferBeginInfo cmdBufferBeginInfo;
699     memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
700     cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
701     cmdBufferBeginInfo.pNext = nullptr;
702     cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT |
703                                VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
704     cmdBufferBeginInfo.pInheritanceInfo = &inheritanceInfo;
705 
706     GR_VK_CALL_ERRCHECK(gpu->vkInterface(), BeginCommandBuffer(fCmdBuffer,
707                                                                &cmdBufferBeginInfo));
708     fIsActive = true;
709 }
710 
end(const GrVkGpu * gpu)711 void GrVkSecondaryCommandBuffer::end(const GrVkGpu* gpu) {
712     SkASSERT(fIsActive);
713     GR_VK_CALL_ERRCHECK(gpu->vkInterface(), EndCommandBuffer(fCmdBuffer));
714     this->invalidateState();
715     fIsActive = false;
716 }
717 
718