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