Files
Seele/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp
T

515 lines
16 KiB
C++
Raw Normal View History

2020-03-24 21:05:32 +01:00
#include "VulkanCommandBuffer.h"
#include "VulkanInitializer.h"
#include "VulkanGraphics.h"
2020-05-05 01:51:13 +02:00
#include "VulkanPipeline.h"
2020-03-24 21:05:32 +01:00
#include "VulkanGraphicsEnums.h"
#include "VulkanFramebuffer.h"
#include "VulkanRenderPass.h"
2020-05-05 01:51:13 +02:00
#include "VulkanPipeline.h"
#include "VulkanDescriptorSets.h"
2020-06-02 11:46:18 +02:00
#include "Graphics/MeshBatch.h"
2020-03-24 21:05:32 +01:00
using namespace Seele;
using namespace Seele::Vulkan;
2020-09-19 14:36:50 +02:00
CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager)
: graphics(graphics)
2021-04-01 16:40:14 +02:00
, manager(manager)
, renderPass(nullptr)
, framebuffer(nullptr)
, subpassIndex(0)
, owner(cmdPool)
2020-03-24 21:05:32 +01:00
{
VkCommandBufferAllocateInfo allocInfo =
init::CommandBufferAllocateInfo(cmdPool,
2020-04-12 15:47:19 +02:00
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1);
std::unique_lock lock(handleLock);
2020-03-24 21:05:32 +01:00
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle))
2020-04-12 15:47:19 +02:00
fence = new Fence(graphics);
2020-03-24 21:05:32 +01:00
state = State::ReadyBegin;
}
CmdBuffer::~CmdBuffer()
{
std::unique_lock lock(handleLock);
2020-03-24 21:05:32 +01:00
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
2020-04-12 15:47:19 +02:00
renderPass = nullptr;
framebuffer = nullptr;
waitSemaphores.clear();
2020-03-24 21:05:32 +01:00
}
void CmdBuffer::begin()
{
VkCommandBufferBeginInfo beginInfo =
init::CommandBufferBeginInfo();
beginInfo.pInheritanceInfo = nullptr;
std::unique_lock lock(handleLock);
2020-03-24 21:05:32 +01:00
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
state = State::InsideBegin;
}
void CmdBuffer::end()
{
std::unique_lock lock(handleLock);
2020-03-24 21:05:32 +01:00
VK_CHECK(vkEndCommandBuffer(handle));
state = State::Ended;
}
2020-04-12 15:47:19 +02:00
void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFramebuffer)
2020-03-24 21:05:32 +01:00
{
std::unique_lock lock(handleLock);
2020-04-12 15:47:19 +02:00
renderPass = newRenderPass;
framebuffer = newFramebuffer;
2020-03-24 21:05:32 +01:00
VkRenderPassBeginInfo beginInfo =
init::RenderPassBeginInfo();
2021-03-31 12:18:16 +02:00
beginInfo.clearValueCount = (uint32)renderPass->getClearValueCount();
2020-03-24 21:05:32 +01:00
beginInfo.pClearValues = renderPass->getClearValues();
beginInfo.renderArea = renderPass->getRenderArea();
beginInfo.renderPass = renderPass->getHandle();
beginInfo.framebuffer = framebuffer->getHandle();
vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents());
2020-04-12 15:47:19 +02:00
state = State::RenderPassActive;
2020-03-24 21:05:32 +01:00
}
void CmdBuffer::endRenderPass()
{
std::unique_lock lock(handleLock);
2020-03-24 21:05:32 +01:00
vkCmdEndRenderPass(handle);
2020-04-12 15:47:19 +02:00
state = State::InsideBegin;
}
2021-05-10 23:57:55 +02:00
void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
2020-04-12 15:47:19 +02:00
{
assert(state == State::RenderPassActive);
2021-12-02 13:00:03 +01:00
if(commands.size() == 0)
{
return;
}
std::unique_lock lock(handleLock);
2020-04-12 15:47:19 +02:00
Array<VkCommandBuffer> cmdBuffers(commands.size());
for (uint32 i = 0; i < commands.size(); ++i)
{
2021-05-10 23:57:55 +02:00
auto command = commands[i].cast<RenderCommand>();
command->end();
2021-05-10 23:57:55 +02:00
executingRenders.add(command);
for(auto descriptor : command->boundDescriptors)
{
2021-11-13 19:28:18 +01:00
descriptor->free();
boundDescriptors.add(descriptor);
}
2021-05-10 23:57:55 +02:00
cmdBuffers[i] = command->getHandle();
}
vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data());
}
void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands)
{
std::unique_lock lock(handleLock);
2021-12-02 13:00:03 +01:00
if(commands.size() == 0)
{
return;
}
2021-05-10 23:57:55 +02:00
Array<VkCommandBuffer> cmdBuffers(commands.size());
for (uint32 i = 0; i < commands.size(); ++i)
{
auto command = commands[i].cast<ComputeCommand>();
command->end();
executingComputes.add(command);
for(auto descriptor : command->boundDescriptors)
{
2021-11-13 19:28:18 +01:00
descriptor->free();
boundDescriptors.add(descriptor);
}
cmdBuffers[i] = command->getHandle();
2020-04-12 15:47:19 +02:00
}
2021-03-31 12:18:16 +02:00
vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data());
2020-04-12 15:47:19 +02:00
}
void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore)
{
std::unique_lock lock(handleLock);
2020-04-12 15:47:19 +02:00
waitSemaphores.add(semaphore);
waitFlags.add(flags);
}
void CmdBuffer::refreshFence()
{
std::unique_lock lock(handleLock);
2020-04-12 15:47:19 +02:00
if (state == State::Submitted)
{
if (fence->isSignaled())
{
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
2021-04-13 23:09:16 +02:00
fence->reset();
2021-05-10 23:57:55 +02:00
for(auto command : executingComputes)
{
command->reset();
}
2021-05-10 23:57:55 +02:00
executingComputes.clear();
for(auto command : executingRenders)
{
command->reset();
}
executingRenders.clear();
for(auto descriptor : boundDescriptors)
{
descriptor->unbind();
}
2021-10-16 12:59:11 +02:00
boundDescriptors.clear();
2021-04-13 23:09:16 +02:00
state = State::ReadyBegin;
2020-04-12 15:47:19 +02:00
}
}
else
{
assert(!fence->isSignaled());
}
2020-03-24 21:05:32 +01:00
}
2021-05-10 23:57:55 +02:00
void CmdBuffer::waitForCommand(uint32 timeout)
{
std::unique_lock lock(handleLock);
2021-05-10 23:57:55 +02:00
fence->wait(timeout);
refreshFence();
}
Event CmdBuffer::asyncWait() const
{
return fence->asyncWait();
}
2021-05-10 23:57:55 +02:00
2020-05-05 01:51:13 +02:00
PFence CmdBuffer::getFence()
{
return fence;
}
2020-09-19 14:36:50 +02:00
PCommandBufferManager CmdBuffer::getManager()
{
return manager;
}
RenderCommand::RenderCommand(PGraphics graphics, VkCommandPool cmdPool)
: graphics(graphics)
, owner(cmdPool)
2020-03-24 21:05:32 +01:00
{
VkCommandBufferAllocateInfo allocInfo =
init::CommandBufferAllocateInfo(cmdPool,
2020-04-12 15:47:19 +02:00
VK_COMMAND_BUFFER_LEVEL_SECONDARY,
1);
2020-03-24 21:05:32 +01:00
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle));
}
2021-05-10 23:57:55 +02:00
RenderCommand::~RenderCommand()
{
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
2021-05-10 23:57:55 +02:00
}
void RenderCommand::begin(PCmdBuffer parent)
{
threadId = std::this_thread::get_id();
2021-05-10 23:57:55 +02:00
ready = false;
VkCommandBufferBeginInfo beginInfo =
init::CommandBufferBeginInfo();
VkCommandBufferInheritanceInfo inheritanceInfo =
init::CommandBufferInheritanceInfo();
inheritanceInfo.framebuffer = parent->framebuffer->getHandle();
inheritanceInfo.renderPass = parent->renderPass->getHandle();
inheritanceInfo.subpass = parent->subpassIndex;
beginInfo.pInheritanceInfo = &inheritanceInfo;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
}
void RenderCommand::end()
{
assert(threadId == std::this_thread::get_id());
VK_CHECK(vkEndCommandBuffer(handle));
}
void RenderCommand::reset()
{
assert(threadId == std::this_thread::get_id());
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
boundDescriptors.clear();
ready = true;
}
2021-05-10 23:57:55 +02:00
bool RenderCommand::isReady()
{
2021-04-13 23:09:16 +02:00
return ready;
}
2021-05-10 23:57:55 +02:00
void RenderCommand::setViewport(Gfx::PViewport viewport)
2020-10-03 11:00:10 +02:00
{
assert(threadId == std::this_thread::get_id());
2020-10-03 11:00:10 +02:00
VkViewport vp = viewport.cast<Viewport>()->getHandle();
VkRect2D scissors = init::Rect2D(viewport->getSizeX(), viewport->getSizeY(), viewport->getOffsetX(), viewport->getOffsetY());
vkCmdSetViewport(handle, 0, 1, &vp);
vkCmdSetScissor(handle, 0, 1, &scissors);
}
2021-05-10 23:57:55 +02:00
void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline)
2020-05-05 01:51:13 +02:00
{
assert(threadId == std::this_thread::get_id());
2020-05-05 01:51:13 +02:00
pipeline = gfxPipeline.cast<GraphicsPipeline>();
pipeline->bind(handle);
}
2021-05-10 23:57:55 +02:00
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
2020-05-05 01:51:13 +02:00
{
assert(threadId == std::this_thread::get_id());
auto descriptor = descriptorSet.cast<DescriptorSet>();
2021-04-13 23:09:16 +02:00
boundDescriptors.add(descriptor.getHandle());
descriptor->bind();
2021-09-23 10:10:39 +02:00
VkDescriptorSet setHandle = descriptor->getHandle();
2020-05-05 01:51:13 +02:00
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr);
}
2021-05-10 23:57:55 +02:00
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets)
2020-10-03 11:00:10 +02:00
{
assert(threadId == std::this_thread::get_id());
2020-10-03 11:00:10 +02:00
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
for(uint32 i = 0; i < descriptorSets.size(); ++i)
{
auto descriptorSet = descriptorSets[i].cast<DescriptorSet>();
descriptorSet->bind();
2021-09-23 10:10:39 +02:00
2021-04-13 23:09:16 +02:00
boundDescriptors.add(descriptorSet.getHandle());
2020-10-03 11:00:10 +02:00
sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle();
}
2021-03-31 12:18:16 +02:00
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr);
2020-10-03 11:00:10 +02:00
delete[] sets;
}
2021-05-10 23:57:55 +02:00
void RenderCommand::bindVertexBuffer(const Array<VertexInputStream>& streams)
2020-05-05 01:51:13 +02:00
{
assert(threadId == std::this_thread::get_id());
2020-06-08 01:44:47 +02:00
Array<VkBuffer> buffers(streams.size());
Array<VkDeviceSize> offsets(streams.size());
for(uint32 i = 0; i < streams.size(); ++i)
{
PVertexBuffer buf = streams[i].vertexBuffer.cast<VertexBuffer>();
buffers[i] = buf->getHandle();
offsets[i] = streams[i].offset;
};
2021-03-31 12:18:16 +02:00
vkCmdBindVertexBuffers(handle, 0, (uint32)streams.size(), buffers.data(), offsets.data());
2020-05-05 01:51:13 +02:00
}
2021-05-10 23:57:55 +02:00
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
2020-05-05 01:51:13 +02:00
{
assert(threadId == std::this_thread::get_id());
2020-05-05 01:51:13 +02:00
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
2020-10-23 01:47:56 +02:00
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, cast(buf->getIndexType()));
2020-05-05 01:51:13 +02:00
}
2021-05-10 23:57:55 +02:00
void RenderCommand::draw(const MeshBatchElement& data)
2020-05-05 01:51:13 +02:00
{
assert(threadId == std::this_thread::get_id());
2020-06-02 11:46:18 +02:00
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
2020-05-05 01:51:13 +02:00
}
2021-09-23 10:10:39 +02:00
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance)
{
assert(threadId == std::this_thread::get_id());
2021-09-23 10:10:39 +02:00
vkCmdDraw(handle, vertexCount, instanceCount, firstVertex, firstInstance);
}
2021-05-10 23:57:55 +02:00
ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool)
: graphics(graphics)
, owner(cmdPool)
2021-05-10 23:57:55 +02:00
{
VkCommandBufferAllocateInfo allocInfo =
init::CommandBufferAllocateInfo(cmdPool,
VK_COMMAND_BUFFER_LEVEL_SECONDARY,
1);
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle));
2021-05-10 23:57:55 +02:00
}
2021-05-10 23:57:55 +02:00
ComputeCommand::~ComputeCommand()
{
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
2021-05-10 23:57:55 +02:00
}
2021-10-15 23:12:29 +02:00
void ComputeCommand::begin(PCmdBuffer)
2021-05-10 23:57:55 +02:00
{
threadId = std::this_thread::get_id();
2021-05-10 23:57:55 +02:00
ready = false;
VkCommandBufferBeginInfo beginInfo =
init::CommandBufferBeginInfo();
VkCommandBufferInheritanceInfo inheritanceInfo =
init::CommandBufferInheritanceInfo();
inheritanceInfo.framebuffer = VK_NULL_HANDLE;
inheritanceInfo.renderPass = VK_NULL_HANDLE;
inheritanceInfo.subpass = 0;
beginInfo.pInheritanceInfo = &inheritanceInfo;
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
}
void ComputeCommand::end()
{
assert(threadId == std::this_thread::get_id());
VK_CHECK(vkEndCommandBuffer(handle));
}
void ComputeCommand::reset()
{
assert(threadId == std::this_thread::get_id());
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
boundDescriptors.clear();
ready = true;
}
2021-05-10 23:57:55 +02:00
bool ComputeCommand::isReady()
{
return ready;
}
void ComputeCommand::bindPipeline(Gfx::PComputePipeline computePipeline)
{
assert(threadId == std::this_thread::get_id());
2021-05-10 23:57:55 +02:00
pipeline = computePipeline.cast<ComputePipeline>();
pipeline->bind(handle);
}
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
{
assert(threadId == std::this_thread::get_id());
2021-05-10 23:57:55 +02:00
auto descriptor = descriptorSet.cast<DescriptorSet>();
boundDescriptors.add(descriptor.getHandle());
descriptor->bind();
2021-10-19 23:04:38 +02:00
2021-05-10 23:57:55 +02:00
VkDescriptorSet setHandle = descriptor->getHandle();
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr);
}
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets)
{
assert(threadId == std::this_thread::get_id());
2021-05-10 23:57:55 +02:00
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
for(uint32 i = 0; i < descriptorSets.size(); ++i)
{
auto descriptorSet = descriptorSets[i].cast<DescriptorSet>();
boundDescriptors.add(descriptorSet.getHandle());
descriptorSet->bind();
//std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl;
2021-05-10 23:57:55 +02:00
sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle();
}
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr);
delete[] sets;
}
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ)
{
assert(threadId == std::this_thread::get_id());
2021-05-10 23:57:55 +02:00
vkCmdDispatch(handle, threadX, threadY, threadZ);
}
2020-04-01 02:17:49 +02:00
CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue)
2020-06-08 01:44:47 +02:00
: graphics(graphics), queue(queue), queueFamilyIndex(queue->getFamilyIndex())
2020-03-24 21:05:32 +01:00
{
VkCommandPoolCreateInfo info =
init::CommandPoolCreateInfo();
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
info.queueFamilyIndex = queue->getFamilyIndex();
VK_CHECK(vkCreateCommandPool(graphics->getDevice(), &info, nullptr, &commandPool));
2020-09-19 14:36:50 +02:00
activeCmdBuffer = new CmdBuffer(graphics, commandPool, this);
2020-03-24 21:05:32 +01:00
activeCmdBuffer->begin();
2021-10-19 23:04:38 +02:00
std::unique_lock lock(allocatedBufferLock);
2020-04-12 15:47:19 +02:00
allocatedBuffers.add(activeCmdBuffer);
2020-03-24 21:05:32 +01:00
}
CommandBufferManager::~CommandBufferManager()
{
vkDestroyCommandPool(graphics->getDevice(), commandPool, nullptr);
2020-04-12 15:47:19 +02:00
graphics = nullptr;
queue = nullptr;
2020-03-24 21:05:32 +01:00
}
PCmdBuffer CommandBufferManager::getCommands()
{
return activeCmdBuffer;
}
2021-05-10 23:57:55 +02:00
PRenderCommand CommandBufferManager::createRenderCommand(const std::string& name)
2020-03-24 21:05:32 +01:00
{
std::unique_lock lck(allocatedRenderLock);
2021-05-10 23:57:55 +02:00
for (uint32 i = 0; i < allocatedRenderCommands.size(); ++i)
2021-04-13 23:09:16 +02:00
{
2021-05-10 23:57:55 +02:00
PRenderCommand cmdBuffer = allocatedRenderCommands[i];
2021-10-16 12:59:11 +02:00
if (cmdBuffer->isReady())
2021-04-13 23:09:16 +02:00
{
2021-10-19 23:04:38 +02:00
cmdBuffer->name = name;
2021-04-13 23:09:16 +02:00
cmdBuffer->begin(activeCmdBuffer);
return cmdBuffer;
}
}
2021-05-10 23:57:55 +02:00
PRenderCommand result = new RenderCommand(graphics, commandPool);
result->name = name;
result->begin(activeCmdBuffer);
allocatedRenderCommands.add(result);
2021-05-10 23:57:55 +02:00
return result;
}
PComputeCommand CommandBufferManager::createComputeCommand(const std::string& name)
{
std::unique_lock lck(allocatedComputeLock);
2021-05-10 23:57:55 +02:00
for (uint32 i = 0; i < allocatedComputeCommands.size(); ++i)
{
PComputeCommand cmdBuffer = allocatedComputeCommands[i];
if (cmdBuffer->isReady())
2021-05-10 23:57:55 +02:00
{
2021-10-19 23:04:38 +02:00
cmdBuffer->name = name;
2021-05-10 23:57:55 +02:00
cmdBuffer->begin(activeCmdBuffer);
return cmdBuffer;
}
}
PComputeCommand result = new ComputeCommand(graphics, commandPool);
result->name = name;
2021-04-13 23:09:16 +02:00
result->begin(activeCmdBuffer);
allocatedComputeCommands.add(result);
2021-04-13 23:09:16 +02:00
return result;
2020-03-24 21:05:32 +01:00
}
2020-04-01 02:17:49 +02:00
void CommandBufferManager::submitCommands(PSemaphore signalSemaphore)
2020-03-24 21:05:32 +01:00
{
2020-04-12 15:47:19 +02:00
if (activeCmdBuffer->state == CmdBuffer::State::InsideBegin || activeCmdBuffer->state == CmdBuffer::State::RenderPassActive)
2020-04-01 02:17:49 +02:00
{
2020-04-12 15:47:19 +02:00
if (activeCmdBuffer->state == CmdBuffer::State::RenderPassActive)
2020-04-01 02:17:49 +02:00
{
std::cout << "End of renderpass forced" << std::endl;
activeCmdBuffer->endRenderPass();
}
activeCmdBuffer->end();
2020-04-12 15:47:19 +02:00
if (signalSemaphore != nullptr)
2020-04-01 02:17:49 +02:00
{
queue->submitCommandBuffer(activeCmdBuffer, signalSemaphore->getHandle());
}
else
{
queue->submitCommandBuffer(activeCmdBuffer);
}
}
std::unique_lock lock(allocatedBufferLock);
2020-04-12 15:47:19 +02:00
for (uint32 i = 0; i < allocatedBuffers.size(); ++i)
2020-04-01 02:17:49 +02:00
{
PCmdBuffer cmdBuffer = allocatedBuffers[i];
2020-04-12 15:47:19 +02:00
cmdBuffer->refreshFence();
if (cmdBuffer->state == CmdBuffer::State::ReadyBegin)
2020-04-01 02:17:49 +02:00
{
activeCmdBuffer = cmdBuffer;
activeCmdBuffer->begin();
return;
}
else
{
assert(cmdBuffer->state == CmdBuffer::State::Submitted);
}
}
2020-09-19 14:36:50 +02:00
activeCmdBuffer = new CmdBuffer(graphics, commandPool, this);
2020-04-01 02:17:49 +02:00
allocatedBuffers.add(activeCmdBuffer);
activeCmdBuffer->begin();
2020-03-24 21:05:32 +01:00
}