LCOV - code coverage report
Current view: top level - xenolith/backend/vk - XLVkDeviceQueue.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 412 492 83.7 %
Date: 2024-05-12 00:16:13 Functions: 67 80 83.8 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2021 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #include "XLVkDeviceQueue.h"
      25             : #include "XLVkDevice.h"
      26             : #include "XLVkSync.h"
      27             : #include "XLVkObject.h"
      28             : #include "XLCoreImageStorage.h"
      29             : #include "XLCoreFrameQueue.h"
      30             : #include "XLVkPipeline.h"
      31             : #include "XLVkRenderPass.h"
      32             : 
      33             : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk {
      34             : 
      35         840 : DeviceQueue::~DeviceQueue() { }
      36             : 
      37         420 : bool DeviceQueue::init(Device &device, VkQueue queue, uint32_t index, QueueOperations ops) {
      38         420 :         _device = &device;
      39         420 :         _queue = queue;
      40         420 :         _index = index;
      41         420 :         _ops = ops;
      42         420 :         return true;
      43             : }
      44             : 
      45      172586 : bool DeviceQueue::submit(const FrameSync &sync, Fence &fence, CommandPool &commandPool, SpanView<const CommandBuffer *> buffers, IdleMode idle) {
      46      172586 :         Vector<VkSemaphore> waitSem;
      47      172586 :         Vector<VkPipelineStageFlags> waitStages;
      48      172586 :         Vector<VkSemaphore> signalSem;
      49      172585 :         Vector<VkCommandBuffer> vkBuffers; vkBuffers.reserve(buffers.size());
      50             : 
      51      345176 :         for (auto &it : buffers) {
      52      172588 :                 if (it) {
      53      172588 :                         vkBuffers.emplace_back(it->getBuffer());
      54             :                 }
      55             :         }
      56             : 
      57      336611 :         for (auto &it : sync.waitAttachments) {
      58      164026 :                 if (it.semaphore) {
      59      164026 :                         auto sem = ((Semaphore *)it.semaphore.get())->getSemaphore();
      60             : 
      61      164026 :                         if (!it.semaphore->isWaited()) {
      62      164026 :                                 waitSem.emplace_back(sem);
      63      164026 :                                 waitStages.emplace_back(VkPipelineStageFlags(it.stages));
      64             :                         }
      65      164026 :                         commandPool.autorelease(it.semaphore.get());
      66             :                 }
      67             :         }
      68             : 
      69      336686 :         for (auto &it : sync.signalAttachments) {
      70      164102 :                 if (it.semaphore) {
      71      164104 :                         auto sem = ((Semaphore *)it.semaphore.get())->getSemaphore();
      72             : 
      73      164104 :                         signalSem.emplace_back(sem);
      74      164100 :                         commandPool.autorelease(it.semaphore.get());
      75             :                 }
      76             :         }
      77             : 
      78      172571 :         VkSubmitInfo submitInfo{};
      79      172571 :         submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
      80      172571 :         submitInfo.pNext = nullptr;
      81      172571 :         submitInfo.waitSemaphoreCount = waitSem.size();
      82      172585 :         submitInfo.pWaitSemaphores = waitSem.data();
      83      172585 :         submitInfo.pWaitDstStageMask = waitStages.data();
      84      172585 :         submitInfo.commandBufferCount = vkBuffers.size();
      85      172585 :         submitInfo.pCommandBuffers = vkBuffers.data();
      86      172585 :         submitInfo.signalSemaphoreCount = signalSem.size();
      87      172585 :         submitInfo.pSignalSemaphores = signalSem.data();
      88             : 
      89             : #if XL_VKAPI_DEBUG
      90             :         auto t = platform::clock(core::ClockType::Monotonic);
      91             :         fence.addRelease([frameIdx = _frameIdx, t] (bool success) {
      92             :                 XL_VKAPI_LOG("[", frameIdx,  "] vkQueueSubmit [complete]",
      93             :                                 " [", platform::clock(core::ClockType::Monotonic) - t, "]");
      94             :         }, nullptr, "DeviceQueue::submit");
      95             : #endif
      96             : 
      97      172586 :         _device->makeApiCall([&, this] (const DeviceTable &table, VkDevice device) {
      98      172586 :                 switch (idle) {
      99           0 :                 case IdleMode::Queue:
     100           0 :                         table.vkQueueWaitIdle(_queue);
     101           0 :                         break;
     102           0 :                 case IdleMode::Device:
     103           0 :                         table.vkDeviceWaitIdle(_device->getDevice());
     104           0 :                         break;
     105      172586 :                 case IdleMode::None:
     106      172586 :                         break;
     107             :                 }
     108             : #if XL_VKAPI_DEBUG
     109             :                 auto t = platform::clock(core::ClockType::Monotonic);
     110             :                 _result = table.vkQueueSubmit(_queue, 1, &submitInfo, fence.getFence());
     111             :                 XL_VKAPI_LOG("[", _frameIdx,  "] vkQueueSubmit: ", _result, " ", (void *)_queue,
     112             :                                 " [", platform::clock(core::ClockType::Monotonic) - t, "]");
     113             : #else
     114      172586 :                 _result = table.vkQueueSubmit(_queue, 1, &submitInfo, fence.getFence());
     115             : #endif
     116      172598 :         });
     117             : 
     118      172598 :         if (_result == VK_SUCCESS) {
     119             :                 // mark semaphores
     120             : 
     121      336624 :                 for (auto &it : sync.waitAttachments) {
     122      164026 :                         if (it.semaphore) {
     123      164026 :                                 it.semaphore->setWaited(true);
     124      164026 :                                 if (it.image && !it.image->isSemaphorePersistent()) {
     125       19034 :                                         fence.addRelease([img = it.image, sem = it.semaphore.get(), t = it.semaphore->getTimeline()] (bool success) {
     126        9517 :                                                 sem->setInUse(false, t);
     127        9517 :                                                 img->releaseSemaphore(sem);
     128        9517 :                                         }, it.image, "DeviceQueue::submit::!isSemaphorePersistent");
     129             :                                 } else {
     130      154509 :                                         fence.addRelease([sem = it.semaphore.get(), t = it.semaphore->getTimeline()] (bool success) {
     131      154509 :                                                 sem->setInUse(false, t);
     132      154509 :                                         }, it.semaphore, "DeviceQueue::submit::isSemaphorePersistent");
     133             :                                 }
     134      164026 :                                 fence.autorelease(it.semaphore.get());
     135      164026 :                                 commandPool.autorelease(it.semaphore.get());
     136             :                         }
     137             :                 }
     138             : 
     139      336707 :                 for (auto &it : sync.signalAttachments) {
     140      164110 :                         if (it.semaphore) {
     141      164110 :                                 it.semaphore->setSignaled(true);
     142      164110 :                                 it.semaphore->setInUse(true, it.semaphore->getTimeline());
     143      164110 :                                 fence.autorelease(it.semaphore.get());
     144      164110 :                                 commandPool.autorelease(it.semaphore.get());
     145             :                         }
     146             :                 }
     147             : 
     148      172579 :                 fence.setArmed(*this);
     149             : 
     150      220201 :                 for (auto &it : sync.images) {
     151       47606 :                         it.image->setLayout(it.newLayout);
     152             :                 }
     153             : 
     154      172595 :                 return true;
     155             :         }
     156           0 :         return false;
     157      172595 : }
     158             : 
     159       25305 : bool DeviceQueue::submit(Fence &fence, const CommandBuffer *buffer, IdleMode idle) {
     160       25305 :         return submit(fence, makeSpanView(&buffer, 1), idle);
     161             : }
     162             : 
     163       25305 : bool DeviceQueue::submit(Fence &fence, SpanView<const CommandBuffer *> buffers, IdleMode idle) {
     164       25305 :         Vector<VkCommandBuffer> vkBuffers; vkBuffers.reserve(buffers.size());
     165             : 
     166       50610 :         for (auto &it : buffers) {
     167       25305 :                 if (it) {
     168       25305 :                         vkBuffers.emplace_back(it->getBuffer());
     169             :                 }
     170             :         }
     171             : 
     172       25305 :         VkSubmitInfo submitInfo{};
     173       25305 :         submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
     174       25305 :         submitInfo.pNext = nullptr;
     175       25305 :         submitInfo.waitSemaphoreCount = 0;
     176       25305 :         submitInfo.pWaitSemaphores = nullptr;
     177       25305 :         submitInfo.pWaitDstStageMask = 0;
     178       25305 :         submitInfo.commandBufferCount = vkBuffers.size();
     179       25305 :         submitInfo.pCommandBuffers = vkBuffers.data();
     180       25305 :         submitInfo.signalSemaphoreCount = 0;
     181       25305 :         submitInfo.pSignalSemaphores = nullptr;
     182             : 
     183             : #if XL_VKAPI_DEBUG
     184             :         [[maybe_unused]] auto frameIdx = _frameIdx;
     185             :         [[maybe_unused]] auto t = platform::clock(core::ClockType::Monotonic);
     186             :         fence.addRelease([=] (bool success) {
     187             :                 XL_VKAPI_LOG("[", frameIdx,  "] vkQueueSubmit [complete]",
     188             :                                 " [", platform::clock(core::ClockType::Monotonic) - t, "]");
     189             :         }, nullptr, "DeviceQueue::submit");
     190             : #endif
     191             : 
     192       25305 :         _device->makeApiCall([&, this] (const DeviceTable &table, VkDevice device) {
     193       25305 :                 switch (idle) {
     194           0 :                 case IdleMode::Queue:
     195           0 :                         table.vkQueueWaitIdle(_queue);
     196           0 :                         break;
     197           0 :                 case IdleMode::Device:
     198           0 :                         table.vkDeviceWaitIdle(_device->getDevice());
     199           0 :                         break;
     200       25305 :                 case IdleMode::None:
     201       25305 :                         break;
     202             :                 }
     203             : #if XL_VKAPI_DEBUG
     204             :                 auto t = platform::clock(core::ClockType::Monotonic);
     205             :                 _result = table.vkQueueSubmit(_queue, 1, &submitInfo, fence.getFence());
     206             :                 XL_VKAPI_LOG("[", _frameIdx,  "] vkQueueSubmit: ", _result, " ", (void *)_queue,
     207             :                                 " [", platform::clock(core::ClockType::Monotonic) - t, "]");
     208             : #else
     209       25305 :                 _result = table.vkQueueSubmit(_queue, 1, &submitInfo, fence.getFence());
     210             : #endif
     211       25305 :         });
     212             : 
     213       25305 :         if (_result == VK_SUCCESS) {
     214       25305 :                 fence.setArmed(*this);
     215       25305 :                 return true;
     216             :         }
     217           0 :         return false;
     218       25305 : }
     219             : 
     220          21 : void DeviceQueue::waitIdle() {
     221          21 :         _device->makeApiCall([&, this] (const DeviceTable &table, VkDevice device) {
     222          21 :                 table.vkQueueWaitIdle(_queue);
     223          21 :         });
     224          21 : }
     225             : 
     226           0 : uint32_t DeviceQueue::getActiveFencesCount() {
     227           0 :         return _nfences.load();
     228             : }
     229             : 
     230      197901 : void DeviceQueue::retainFence(const Fence &fence) {
     231      197901 :         ++ _nfences;
     232      197902 : }
     233             : 
     234      197903 : void DeviceQueue::releaseFence(const Fence &fence) {
     235      197903 :         -- _nfences;
     236      197903 : }
     237             : 
     238      172577 : void DeviceQueue::setOwner(FrameHandle &frame) {
     239      172577 :         _frameIdx = frame.getOrder();
     240      172577 : }
     241             : 
     242      207399 : void DeviceQueue::reset() {
     243      207399 :         _result = VK_ERROR_UNKNOWN;
     244      207399 :         _frameIdx = 0;
     245      207399 : }
     246             : 
     247       10856 : ImageMemoryBarrier::ImageMemoryBarrier(Image *image, VkAccessFlags src, VkAccessFlags dst,
     248       10856 :                 VkImageLayout old, VkImageLayout _new)
     249       10856 : : srcAccessMask(src), dstAccessMask(dst), oldLayout(old), newLayout(_new)
     250       21712 : , image(image), subresourceRange(VkImageSubresourceRange{
     251       10856 :         image->getAspectMask(), 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS
     252       10856 : }) { }
     253             : 
     254           0 : ImageMemoryBarrier::ImageMemoryBarrier(Image *image, VkAccessFlags src, VkAccessFlags dst,
     255           0 :                 VkImageLayout old, VkImageLayout _new, VkImageSubresourceRange range)
     256           0 : : srcAccessMask(src), dstAccessMask(dst), oldLayout(old), newLayout(_new)
     257           0 : , image(image), subresourceRange(range) { }
     258             : 
     259       10625 : ImageMemoryBarrier::ImageMemoryBarrier(Image *image, VkAccessFlags src, VkAccessFlags dst,
     260       10625 :                 VkImageLayout old, VkImageLayout _new, QueueFamilyTransfer transfer)
     261       10625 : : srcAccessMask(src), dstAccessMask(dst), oldLayout(old), newLayout(_new), familyTransfer(transfer)
     262       21250 : , image(image), subresourceRange(VkImageSubresourceRange{
     263       10625 :         image->getAspectMask(), 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS
     264       10625 : }) { }
     265             : 
     266           0 : ImageMemoryBarrier::ImageMemoryBarrier(Image *image, VkAccessFlags src, VkAccessFlags dst,
     267           0 :          VkImageLayout old, VkImageLayout _new, QueueFamilyTransfer transfer, VkImageSubresourceRange range)
     268           0 : : srcAccessMask(src), dstAccessMask(dst), oldLayout(old), newLayout(_new), familyTransfer(transfer)
     269           0 : , image(image), subresourceRange(range) { }
     270             : 
     271          63 : ImageMemoryBarrier::ImageMemoryBarrier(const VkImageMemoryBarrier &barrier)
     272          63 : : srcAccessMask(barrier.srcAccessMask), dstAccessMask(barrier.dstAccessMask)
     273          63 : , oldLayout(barrier.oldLayout), newLayout(barrier.newLayout)
     274          63 : , familyTransfer(QueueFamilyTransfer{barrier.srcQueueFamilyIndex, barrier.dstQueueFamilyIndex})
     275          63 : , image(nullptr), subresourceRange(barrier.subresourceRange) { }
     276             : 
     277     1624503 : BufferMemoryBarrier::BufferMemoryBarrier(Buffer *buf, VkAccessFlags src, VkAccessFlags dst)
     278     1624503 : : srcAccessMask(src), dstAccessMask(dst), buffer(buf) { }
     279             : 
     280           0 : BufferMemoryBarrier::BufferMemoryBarrier(Buffer *buf, VkAccessFlags src, VkAccessFlags dst,
     281           0 :                 QueueFamilyTransfer transfer)
     282           0 : : srcAccessMask(src), dstAccessMask(dst), familyTransfer(transfer), buffer(buf) { }
     283             : 
     284       19911 : BufferMemoryBarrier::BufferMemoryBarrier(Buffer *buf, VkAccessFlags src, VkAccessFlags dst,
     285       19911 :                 QueueFamilyTransfer transfer, VkDeviceSize offset, VkDeviceSize size)
     286       19911 : : srcAccessMask(src), dstAccessMask(dst), familyTransfer(transfer),
     287       19911 :   buffer(buf), offset(offset), size(size) { }
     288             : 
     289         420 : BufferMemoryBarrier::BufferMemoryBarrier(const VkBufferMemoryBarrier &barrier)
     290         420 : : srcAccessMask(barrier.srcAccessMask), dstAccessMask(barrier.dstAccessMask)
     291         420 : , familyTransfer(QueueFamilyTransfer{barrier.srcQueueFamilyIndex, barrier.dstQueueFamilyIndex})
     292         420 : , buffer(nullptr), offset(barrier.offset), size(barrier.size) { }
     293             : 
     294             : 
     295       28569 : DescriptorImageInfo::~DescriptorImageInfo() { }
     296             : 
     297       28463 : DescriptorImageInfo::DescriptorImageInfo(const PipelineDescriptor *desc, uint32_t index, bool external)
     298       28463 : : DescriptorInfo(desc, index, external) { }
     299             : 
     300     1581483 : DescriptorBufferInfo::~DescriptorBufferInfo() { }
     301             : 
     302     1581483 : DescriptorBufferInfo::DescriptorBufferInfo(const PipelineDescriptor *desc, uint32_t index, bool external)
     303     1581483 : : DescriptorInfo(desc, index, external) { }
     304             : 
     305           0 : DescriptorBufferViewInfo::~DescriptorBufferViewInfo() { }
     306             : 
     307           0 : DescriptorBufferViewInfo::DescriptorBufferViewInfo(const PipelineDescriptor *desc, uint32_t index, bool external)
     308           0 : : DescriptorInfo(desc, index, external) { }
     309             : 
     310      395806 : CommandBuffer::~CommandBuffer() {
     311      197903 :         invalidate();
     312      395806 : }
     313             : 
     314      197899 : bool CommandBuffer::init(const CommandPool *pool, const DeviceTable *table, VkCommandBuffer buffer) {
     315      197899 :         _pool = pool;
     316      197899 :         _table = table;
     317      197899 :         _buffer = buffer;
     318      197899 :         return true;
     319             : }
     320             : 
     321      197903 : void CommandBuffer::invalidate() {
     322      197903 :         _buffer = VK_NULL_HANDLE;
     323      197903 : }
     324             : 
     325        7378 : void CommandBuffer::cmdPipelineBarrier(VkPipelineStageFlags srcFlags, VkPipelineStageFlags dstFlags, VkDependencyFlags deps,
     326             :                 SpanView<ImageMemoryBarrier> imageBarriers) {
     327        7378 :         Vector<VkImageMemoryBarrier> images; images.reserve(imageBarriers.size());
     328       14798 :         for (auto &it : imageBarriers) {
     329        7420 :                 images.emplace_back(VkImageMemoryBarrier{
     330             :                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, nullptr,
     331        7420 :                         it.srcAccessMask, it.dstAccessMask,
     332        7420 :                         it.oldLayout, it.newLayout,
     333        7420 :                         it.familyTransfer.srcQueueFamilyIndex, it.familyTransfer.dstQueueFamilyIndex,
     334        7420 :                         it.image->getImage(), it.subresourceRange
     335             :                 });
     336        7420 :                 bindImage(it.image);
     337             :         }
     338             : 
     339        7378 :         _table->vkCmdPipelineBarrier(_buffer, srcFlags, dstFlags, deps, 0, nullptr, 0, nullptr, images.size(), images.data());
     340        7378 : }
     341             : 
     342     1061942 : void CommandBuffer::cmdPipelineBarrier(VkPipelineStageFlags srcFlags, VkPipelineStageFlags dstFlags, VkDependencyFlags deps,
     343             :                 SpanView<BufferMemoryBarrier> bufferBarriers) {
     344     1061942 :         Vector<VkBufferMemoryBarrier> buffers; buffers.reserve(bufferBarriers.size());
     345     3031082 :         for (auto &it : bufferBarriers) {
     346           0 :                 buffers.emplace_back(VkBufferMemoryBarrier{
     347             :                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, nullptr,
     348     1969141 :                         it.srcAccessMask, it.dstAccessMask,
     349     1969141 :                         it.familyTransfer.srcQueueFamilyIndex, it.familyTransfer.dstQueueFamilyIndex,
     350     1969141 :                         it.buffer->getBuffer(), it.offset, it.size
     351             :                 });
     352     1969141 :                 bindBuffer(it.buffer);
     353             :         }
     354             : 
     355     1061937 :         _table->vkCmdPipelineBarrier(_buffer, srcFlags, dstFlags, deps, 0, nullptr, buffers.size(), buffers.data(), 0, nullptr);
     356     1061942 : }
     357             : 
     358             : 
     359       24644 : void CommandBuffer::cmdPipelineBarrier(VkPipelineStageFlags srcFlags, VkPipelineStageFlags dstFlags, VkDependencyFlags deps,
     360             :                 SpanView<BufferMemoryBarrier> bufferBarriers, SpanView<ImageMemoryBarrier> imageBarriers) {
     361       24644 :         Vector<VkBufferMemoryBarrier> buffers; buffers.reserve(bufferBarriers.size());
     362       65247 :         for (auto &it : bufferBarriers) {
     363           0 :                 buffers.emplace_back(VkBufferMemoryBarrier{
     364             :                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, nullptr,
     365       40603 :                         it.srcAccessMask, it.dstAccessMask,
     366       40603 :                         it.familyTransfer.srcQueueFamilyIndex, it.familyTransfer.dstQueueFamilyIndex,
     367       40603 :                         it.buffer->getBuffer(), it.offset, it.size
     368             :                 });
     369       40603 :                 bindBuffer(it.buffer);
     370             :         }
     371             : 
     372       24644 :         Vector<VkImageMemoryBarrier> images; images.reserve(imageBarriers.size());
     373       49330 :         for (auto &it : imageBarriers) {
     374       24686 :                 images.emplace_back(VkImageMemoryBarrier{
     375             :                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, nullptr,
     376       24686 :                         it.srcAccessMask, it.dstAccessMask,
     377       24686 :                         it.oldLayout, it.newLayout,
     378       24686 :                         it.familyTransfer.srcQueueFamilyIndex, it.familyTransfer.dstQueueFamilyIndex,
     379       24686 :                         it.image->getImage(), it.subresourceRange
     380             :                 });
     381       24686 :                 bindImage(it.image);
     382             :         }
     383             : 
     384       24644 :         _table->vkCmdPipelineBarrier(_buffer, srcFlags, dstFlags, deps, 0, nullptr,
     385       24644 :                         buffers.size(), buffers.data(), images.size(), images.data());
     386       24644 : }
     387             : 
     388      154525 : void CommandBuffer::cmdCopyBuffer(Buffer *src, Buffer *dst) {
     389      154525 :         VkBufferCopy copy{0, 0, std::min(src->getSize(), dst->getSize())};
     390      154525 :         cmdCopyBuffer(src, dst, makeSpanView(&copy, 1));
     391      154525 : }
     392             : 
     393           0 : void CommandBuffer::cmdCopyBuffer(Buffer *src, Buffer *dst, VkDeviceSize srcOffset, VkDeviceSize dstOffset, VkDeviceSize size) {
     394           0 :         VkBufferCopy copy{srcOffset, dstOffset, size};
     395           0 :         cmdCopyBuffer(src, dst, makeSpanView(&copy, 1));
     396           0 : }
     397             : 
     398      154610 : void CommandBuffer::cmdCopyBuffer(Buffer *src, Buffer *dst, SpanView<VkBufferCopy> copy) {
     399      154610 :         bindBuffer(src);
     400      154610 :         bindBuffer(dst);
     401             : 
     402      154610 :         _table->vkCmdCopyBuffer(_buffer, src->getBuffer(), dst->getBuffer(), copy.size(), copy.data());
     403      154610 : }
     404             : 
     405          21 : void CommandBuffer::cmdCopyImage(Image *src, VkImageLayout srcLayout, Image *dst, VkImageLayout dstLayout, VkFilter filter) {
     406          21 :         auto sourceExtent = src->getInfo().extent;
     407          21 :         auto targetExtent = dst->getInfo().extent;
     408             : 
     409          21 :         if (sourceExtent == targetExtent) {
     410          21 :                 VkImageCopy copy{
     411          42 :                         VkImageSubresourceLayers{src->getAspectMask(), 0, 0, src->getInfo().arrayLayers.get()},
     412             :                         VkOffset3D{0, 0, 0},
     413          21 :                         VkImageSubresourceLayers{dst->getAspectMask(), 0, 0, dst->getInfo().arrayLayers.get()},
     414             :                         VkOffset3D{0, 0, 0},
     415          21 :                         VkExtent3D{targetExtent.width, targetExtent.height, targetExtent.depth}
     416          42 :                 };
     417             : 
     418          21 :                 _table->vkCmdCopyImage(_buffer, src->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
     419             :                                 dst->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy);
     420             :         } else {
     421           0 :                 VkImageBlit blit{
     422           0 :                         VkImageSubresourceLayers{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, src->getInfo().arrayLayers.get()},
     423           0 :                         { VkOffset3D{0, 0, 0}, VkOffset3D{int32_t(sourceExtent.width), int32_t(sourceExtent.height), int32_t(sourceExtent.depth)} },
     424           0 :                         VkImageSubresourceLayers{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, dst->getInfo().arrayLayers.get()},
     425           0 :                         { VkOffset3D{0, 0, 0}, VkOffset3D{int32_t(targetExtent.width), int32_t(targetExtent.height), int32_t(targetExtent.depth)} },
     426           0 :                 };
     427             : 
     428           0 :                 _table->vkCmdBlitImage(_buffer, src->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
     429             :                                 dst->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, filter);
     430             :         }
     431          21 : }
     432             : 
     433           0 : void CommandBuffer::cmdCopyImage(Image *src, VkImageLayout srcLayout, Image *dst, VkImageLayout dstLayout, const VkImageCopy &copy) {
     434           0 :         bindImage(src);
     435           0 :         bindImage(dst);
     436             : 
     437           0 :         _table->vkCmdCopyImage(_buffer, src->getImage(), srcLayout, dst->getImage(), dstLayout, 1, &copy);
     438           0 : }
     439             : 
     440           0 : void CommandBuffer::cmdCopyImage(Image *src, VkImageLayout srcLayout, Image *dst, VkImageLayout dstLayout, SpanView<VkImageCopy> copy) {
     441           0 :         bindImage(src);
     442           0 :         bindImage(dst);
     443             : 
     444           0 :         _table->vkCmdCopyImage(_buffer, src->getImage(), srcLayout, dst->getImage(), dstLayout, copy.size(), copy.data());
     445           0 : }
     446             : 
     447          42 : void CommandBuffer::cmdCopyBufferToImage(Buffer *buf, Image *img, VkImageLayout layout, VkDeviceSize offset) {
     448          42 :         auto &extent = img->getInfo().extent;
     449          42 :         VkImageSubresourceLayers copyLayers({ img->getAspectMask(), 0, 0, img->getInfo().arrayLayers.get() });
     450             : 
     451          42 :         VkBufferImageCopy copyRegion{offset, 0, 0, copyLayers, VkOffset3D{0, 0, 0},
     452          42 :                 VkExtent3D{extent.width, extent.height, extent.depth}};
     453             : 
     454          42 :         cmdCopyBufferToImage(buf, img, layout, makeSpanView(&copyRegion, 1));
     455          42 : }
     456             : 
     457        2153 : void CommandBuffer::cmdCopyBufferToImage(Buffer *buf, Image *img, VkImageLayout layout, SpanView<VkBufferImageCopy> copy) {
     458        2153 :         bindBuffer(buf);
     459        2153 :         bindImage(img);
     460             : 
     461        2153 :         _table->vkCmdCopyBufferToImage(_buffer, buf->getBuffer(), img->getImage(), layout, copy.size(), copy.data());
     462        2153 : }
     463             : 
     464          21 : void CommandBuffer::cmdCopyImageToBuffer(Image *img, VkImageLayout layout, Buffer *buf, VkDeviceSize offset) {
     465          21 :         auto &extent = img->getInfo().extent;
     466          21 :         VkImageSubresourceLayers copyLayers({ img->getAspectMask(), 0, 0, img->getInfo().arrayLayers.get() });
     467             : 
     468          21 :         VkBufferImageCopy copyRegion{offset, 0, 0, copyLayers, VkOffset3D{0, 0, 0},
     469          21 :                 VkExtent3D{extent.width, extent.height, extent.depth}};
     470             : 
     471          21 :         cmdCopyImageToBuffer(img, layout, buf, makeSpanView(&copyRegion, 1));
     472          21 : }
     473             : 
     474          21 : void CommandBuffer::cmdCopyImageToBuffer(Image *img, VkImageLayout layout, Buffer *buf, SpanView<VkBufferImageCopy> copy) {
     475          21 :         bindBuffer(buf);
     476          21 :         bindImage(img);
     477             : 
     478          21 :         _table->vkCmdCopyImageToBuffer(_buffer, img->getImage(), layout, buf->getBuffer(), copy.size(), copy.data());
     479          21 : }
     480             : 
     481        7273 : void CommandBuffer::cmdClearColorImage(Image *image, VkImageLayout layout, const Color4F &color) {
     482             :         VkClearColorValue clearColorEmpty;
     483        7273 :         clearColorEmpty.float32[0] = color.r;
     484        7273 :         clearColorEmpty.float32[1] = color.g;
     485        7273 :         clearColorEmpty.float32[2] = color.b;
     486        7273 :         clearColorEmpty.float32[3] = color.a;
     487             : 
     488        7273 :         VkImageSubresourceRange range{ image->getAspectMask(), 0, image->getInfo().mipLevels.get(), 0, image->getInfo().arrayLayers.get() };
     489             : 
     490        7273 :         bindImage(image);
     491        7273 :         _table->vkCmdClearColorImage(_buffer, image->getImage(), layout,
     492             :                         &clearColorEmpty, 1, &range);
     493        7273 : }
     494             : 
     495        9517 : void CommandBuffer::cmdBeginRenderPass(RenderPass *pass, Framebuffer *fb, VkSubpassContents subpass, bool alt) {
     496        9517 :         auto &clearValues = pass->getClearValues();
     497        9517 :         auto currentExtent = fb->getExtent();
     498             : 
     499        9517 :         VkRenderPassBeginInfo renderPassInfo {
     500             :                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr
     501             :         };
     502        9517 :         renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
     503        9517 :         renderPassInfo.pNext = nullptr;
     504        9517 :         renderPassInfo.renderPass = pass->getRenderPass(alt);
     505        9517 :         renderPassInfo.framebuffer = fb->getFramebuffer();
     506        9517 :         renderPassInfo.renderArea.offset = { 0, 0 };
     507        9517 :         renderPassInfo.renderArea.extent = VkExtent2D{currentExtent.width, currentExtent.height};
     508        9517 :         renderPassInfo.clearValueCount = clearValues.size();
     509        9517 :         renderPassInfo.pClearValues = clearValues.data();
     510             : 
     511        9517 :         bindFramebuffer(fb);
     512        9517 :         _table->vkCmdBeginRenderPass(_buffer, &renderPassInfo, subpass);
     513             : 
     514        9517 :         _currentSubpass = 0;
     515        9517 :         _withinRenderpass = true;
     516        9517 : }
     517             : 
     518        9517 : void CommandBuffer::cmdEndRenderPass() {
     519        9517 :         _table->vkCmdEndRenderPass(_buffer);
     520             : 
     521        9517 :         _withinRenderpass = false;
     522        9517 :         _currentSubpass = 0;
     523        9517 : }
     524             : 
     525       11845 : void CommandBuffer::cmdSetViewport(uint32_t firstViewport, SpanView<VkViewport> viewports) {
     526       11845 :         _table->vkCmdSetViewport(_buffer, firstViewport, viewports.size(), viewports.data());
     527       11845 : }
     528             : 
     529       18842 : void CommandBuffer::cmdSetScissor(uint32_t firstScissor, SpanView<VkRect2D> scissors) {
     530             :         //log::verbose("CommandBuffer", "cmdSetScissor: ", scissors.front().offset.x, " ", scissors.front().offset.y, " ",
     531             :         //              scissors.front().extent.width, " ", scissors.front().extent.height);
     532       18842 :         _table->vkCmdSetScissor(_buffer, firstScissor, scissors.size(), scissors.data());
     533       18842 : }
     534             : 
     535       21362 : void CommandBuffer::cmdBindPipeline(GraphicPipeline *pipeline) {
     536       21362 :         _table->vkCmdBindPipeline(_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getPipeline());
     537       21362 : }
     538             : 
     539     1246349 : void CommandBuffer::cmdBindPipeline(ComputePipeline *pipeline) {
     540     1246349 :         _table->vkCmdBindPipeline(_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getPipeline());
     541     1246349 : }
     542             : 
     543        9517 : void CommandBuffer::cmdBindIndexBuffer(Buffer *buf, VkDeviceSize offset, VkIndexType indexType) {
     544        9517 :         _table->vkCmdBindIndexBuffer(_buffer, buf->getBuffer(), offset, indexType);
     545        9517 : }
     546             : 
     547      240989 : void CommandBuffer::cmdBindDescriptorSets(RenderPass *pass, uint32_t layoutIndex, uint32_t firstSet) {
     548      240989 :         auto &sets = pass->getDescriptorSets(layoutIndex);
     549             : 
     550      240989 :         Vector<VkDescriptorSet> bindSets; bindSets.reserve(sets.size());
     551      481975 :         for (auto &it : sets) {
     552      240987 :                 bindSets.emplace_back(it->set);
     553      240986 :                 _descriptorSets.emplace(it);
     554             :         }
     555             : 
     556      240983 :         cmdBindDescriptorSets(pass, layoutIndex, bindSets, firstSet);
     557      240994 : }
     558             : 
     559      250504 : void CommandBuffer::cmdBindDescriptorSets(RenderPass *pass, uint32_t layoutIndex, SpanView<VkDescriptorSet> sets, uint32_t firstSet) {
     560      250504 :         auto bindPoint = (pass->getType() == core::PassType::Compute) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
     561             : 
     562      250504 :         _boundLayoutIndex = layoutIndex;
     563      250504 :         _boundLayout = pass->getPipelineLayout(layoutIndex);
     564             : 
     565      501007 :         _table->vkCmdBindDescriptorSets(_buffer, bindPoint, _boundLayout, firstSet,
     566      250503 :                         sets.size(), sets.data(), 0, nullptr);
     567      250511 : }
     568             : 
     569           0 : void CommandBuffer::cmdBindGraphicDescriptorSets(VkPipelineLayout layout, SpanView<VkDescriptorSet> sets, uint32_t firstSet) {
     570           0 :         _table->vkCmdBindDescriptorSets(_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, firstSet,
     571           0 :                         sets.size(), sets.data(), 0, nullptr);
     572           0 : }
     573             : 
     574           0 : void CommandBuffer::cmdBindComputeDescriptorSets(VkPipelineLayout layout, SpanView<VkDescriptorSet> sets, uint32_t firstSet) {
     575           0 :         _table->vkCmdBindDescriptorSets(_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, firstSet,
     576           0 :                         sets.size(), sets.data(), 0, nullptr);
     577           0 : }
     578             : 
     579           0 : void CommandBuffer::cmdDraw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
     580           0 :         _table->vkCmdDraw(_buffer, vertexCount, instanceCount, firstVertex, firstInstance);
     581           0 : }
     582       45830 : void CommandBuffer::cmdDrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex,
     583             :                 int32_t vertexOffset, uint32_t firstInstance) {
     584       45830 :         _table->vkCmdDrawIndexed(_buffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
     585       45830 : }
     586             : 
     587       43502 : void CommandBuffer::cmdPushConstants(VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, BytesView data) {
     588       43502 :         _table->vkCmdPushConstants(_buffer, layout, stageFlags, offset, data.size(), data.data());
     589       43502 : }
     590             : 
     591      909528 : void CommandBuffer::cmdPushConstants(VkShaderStageFlags stageFlags, uint32_t offset, BytesView data) {
     592      909528 :         XLASSERT(_boundLayout, "cmdPushConstants without bound layout");
     593      909528 :         _table->vkCmdPushConstants(_buffer, _boundLayout, stageFlags, offset, data.size(), data.data());
     594      909528 : }
     595             : 
     596        2370 : void CommandBuffer::cmdFillBuffer(Buffer *buffer, uint32_t data) {
     597        2370 :         cmdFillBuffer(buffer, 0, VK_WHOLE_SIZE, data);
     598        2370 : }
     599             : 
     600        2370 : void CommandBuffer::cmdFillBuffer(Buffer *buffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
     601        2370 :         bindBuffer(buffer);
     602        2370 :         _table->vkCmdFillBuffer(_buffer, buffer->getBuffer(), dstOffset, size, data);
     603        2370 : }
     604             : 
     605     1246349 : void CommandBuffer::cmdDispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
     606     1246349 :         _table->vkCmdDispatch(_buffer, groupCountX, groupCountY, groupCountZ);
     607     1246349 : }
     608             : 
     609      529200 : void CommandBuffer::cmdDispatchPipeline(ComputePipeline *pipeline, uint32_t countX, uint32_t countY, uint32_t countZ) {
     610      529200 :         cmdBindPipeline(pipeline);
     611      529200 :         cmdDispatch((countX - 1) / pipeline->getLocalX() + 1,
     612      529200 :                         (countY - 1) / pipeline->getLocalY() + 1,
     613      529200 :                         (countZ - 1) / pipeline->getLocalZ() + 1);
     614      529200 : }
     615             : 
     616       59917 : uint32_t CommandBuffer::cmdNextSubpass() {
     617       59917 :         if (_withinRenderpass) {
     618        9517 :                 _table->vkCmdNextSubpass(_buffer, VK_SUBPASS_CONTENTS_INLINE);
     619        9517 :                 ++ _currentSubpass;
     620        9517 :                 return _currentSubpass;
     621             :         }
     622       50400 :         return 0;
     623             : }
     624             : 
     625          42 : void CommandBuffer::writeImageTransfer(uint32_t sourceFamily, uint32_t targetFamily, const Rc<Buffer> &buffer, const Rc<Image> &image) {
     626             :         ImageMemoryBarrier inImageBarrier(image, 0, VK_ACCESS_TRANSFER_WRITE_BIT,
     627          42 :                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
     628             : 
     629          42 :         cmdPipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, makeSpanView(&inImageBarrier, 1));
     630             : 
     631          42 :         auto sourceFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
     632          42 :         auto targetFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
     633             : 
     634          42 :         if (image->getInfo().type != core::PassType::Generic && sourceFamily != VK_QUEUE_FAMILY_IGNORED && targetFamily != VK_QUEUE_FAMILY_IGNORED) {
     635          42 :                 if (sourceFamily != targetFamily) {
     636          42 :                         sourceFamilyIndex = sourceFamily;
     637          42 :                         targetFamilyIndex = targetFamily;
     638             :                 }
     639             :         }
     640             : 
     641          42 :         cmdCopyBufferToImage(buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0);
     642             : 
     643             :         ImageMemoryBarrier outImageBarrier(image, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
     644             :                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
     645          42 :                 QueueFamilyTransfer{sourceFamilyIndex, targetFamilyIndex});
     646             : 
     647          42 :         cmdPipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, makeSpanView(&outImageBarrier, 1));
     648             : 
     649          42 :         if (targetFamilyIndex != VK_QUEUE_FAMILY_IGNORED) {
     650          42 :                 image->setPendingBarrier(outImageBarrier);
     651             :         }
     652          42 : }
     653             : 
     654     2323508 : void CommandBuffer::bindBuffer(core::BufferObject *buffer) {
     655     2323508 :         core::CommandBuffer::bindBuffer(buffer);
     656     2323508 :         if (auto pool = static_cast<Buffer *>(buffer)->getMemory()->getPool()) {
     657     1481913 :                 _memPool.emplace(pool);
     658             :         }
     659     2323508 : }
     660             : 
     661         882 : CommandPool::~CommandPool() {
     662         441 :         if (_commandPool) {
     663           0 :                 log::error("VK-Error", "CommandPool was not destroyed");
     664             :         }
     665         882 : }
     666             : 
     667         441 : bool CommandPool::init(Device &dev, uint32_t familyIdx, QueueOperations c, bool transient) {
     668         441 :         _familyIdx = familyIdx;
     669         441 :         _class = c;
     670         441 :         VkCommandPoolCreateInfo poolInfo{};
     671         441 :         poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
     672         441 :         poolInfo.pNext = nullptr;
     673         441 :         poolInfo.queueFamilyIndex = familyIdx;
     674         441 :         poolInfo.flags = 0; // transient ? VK_COMMAND_POOL_CREATE_TRANSIENT_BIT : 0;
     675             : 
     676         441 :         return dev.getTable()->vkCreateCommandPool(dev.getDevice(), &poolInfo, nullptr, &_commandPool) == VK_SUCCESS;
     677             : }
     678             : 
     679         441 : void CommandPool::invalidate(Device &dev) {
     680         441 :         if (_commandPool) {
     681         441 :                 dev.getTable()->vkDestroyCommandPool(dev.getDevice(), _commandPool, nullptr);
     682         441 :                 _commandPool = VK_NULL_HANDLE;
     683             :         } else {
     684           0 :                 log::error("VK-Error", "CommandPool is not defined");
     685             :         }
     686         441 : }
     687             : 
     688      197903 : const CommandBuffer *CommandPool::recordBuffer(Device &dev, const Callback<bool(CommandBuffer &)> &cb,
     689             :                 VkCommandBufferUsageFlagBits flags, Level level) {
     690      197903 :         if (!_commandPool) {
     691           0 :                 return nullptr;
     692             :         }
     693             : 
     694      197903 :         VkCommandBufferAllocateInfo allocInfo{};
     695      197903 :         allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
     696      197903 :         allocInfo.commandPool = _commandPool;
     697      197903 :         allocInfo.level = VkCommandBufferLevel(level);
     698      197903 :         allocInfo.commandBufferCount = 1;
     699             : 
     700             :         VkCommandBuffer buf;
     701      197903 :         if (dev.getTable()->vkAllocateCommandBuffers(dev.getDevice(), &allocInfo, &buf) != VK_SUCCESS) {
     702           0 :                 return nullptr;
     703             :         }
     704             : 
     705             : 
     706      197903 :         VkCommandBufferBeginInfo beginInfo { };
     707      197903 :         beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
     708      197903 :         beginInfo.pNext = nullptr;
     709      197903 :         beginInfo.flags = flags;
     710      197903 :         beginInfo.pInheritanceInfo = nullptr;
     711             : 
     712      197903 :         if (dev.getTable()->vkBeginCommandBuffer(buf, &beginInfo) != VK_SUCCESS) {
     713           0 :                 dev.getTable()->vkFreeCommandBuffers(dev.getDevice(), _commandPool, 1, &buf);
     714           0 :                 return nullptr;
     715             :         }
     716             : 
     717      197903 :         auto b = Rc<CommandBuffer>::create(this, dev.getTable(), buf);
     718      197899 :         if (!b) {
     719           0 :                 dev.getTable()->vkEndCommandBuffer(buf);
     720           0 :                 dev.getTable()->vkFreeCommandBuffers(dev.getDevice(), _commandPool, 1, &buf);
     721           0 :                 return nullptr;
     722             :         }
     723             : 
     724      197899 :         auto result = cb(*b);
     725             : 
     726      197903 :         dev.getTable()->vkEndCommandBuffer(buf);
     727             : 
     728      197903 :         if (!result) {
     729           0 :                 dev.getTable()->vkFreeCommandBuffers(dev.getDevice(), _commandPool, 1, &buf);
     730           0 :                 return nullptr;
     731             :         }
     732             : 
     733      197903 :         return _buffers.emplace_back(move(b)).get();
     734      197902 : }
     735             : 
     736           0 : void CommandPool::freeDefaultBuffers(Device &dev, Vector<VkCommandBuffer> &vec) {
     737           0 :         if (_commandPool) {
     738           0 :                 dev.getTable()->vkFreeCommandBuffers(dev.getDevice(), _commandPool, static_cast<uint32_t>(vec.size()), vec.data());
     739             :         }
     740           0 :         vec.clear();
     741           0 : }
     742             : 
     743      395781 : void CommandPool::reset(Device &dev, bool release) {
     744      395781 :         if (_commandPool) {
     745             :                 //dev.getTable()->vkResetCommandPool(dev.getDevice(), _commandPool, release ? VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT : 0);
     746             : 
     747      395781 :                 Vector<VkCommandBuffer> buffersToFree;
     748      593683 :                 for (auto &it : _buffers) {
     749      197903 :                         if (it) {
     750      197903 :                                 buffersToFree.emplace_back(it->getBuffer());
     751             :                         }
     752             :                 }
     753      395779 :                 if (buffersToFree.size() > 0) {
     754      197903 :                         dev.getTable()->vkFreeCommandBuffers(dev.getDevice(), _commandPool, static_cast<uint32_t>(buffersToFree.size()), buffersToFree.data());
     755             :                 }
     756      395784 :                 dev.getTable()->vkDestroyCommandPool(dev.getDevice(), _commandPool, nullptr);
     757             : 
     758      395784 :                 VkCommandPoolCreateInfo poolInfo{};
     759      395784 :                 poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
     760      395784 :                 poolInfo.pNext = nullptr;
     761      395784 :                 poolInfo.queueFamilyIndex = _familyIdx;
     762      395784 :                 poolInfo.flags = 0; // transient ? VK_COMMAND_POOL_CREATE_TRANSIENT_BIT : 0;
     763             : 
     764      395784 :                 dev.getTable()->vkCreateCommandPool(dev.getDevice(), &poolInfo, nullptr, &_commandPool);
     765             : 
     766      395785 :                 _buffers.clear();
     767      395779 :                 _autorelease.clear();
     768      395780 :         }
     769      395782 : }
     770             : 
     771      656158 : void CommandPool::autorelease(Rc<Ref> &&ref) {
     772      656158 :         _autorelease.emplace_back(move(ref));
     773      656126 : }
     774             : 
     775             : }

Generated by: LCOV version 1.14