2023-11-15 17:42:57 +01:00
|
|
|
#include "Command.h"
|
2023-10-26 18:37:29 +02:00
|
|
|
#include "Graphics.h"
|
|
|
|
|
#include "Pipeline.h"
|
|
|
|
|
#include "Enums.h"
|
|
|
|
|
#include "Framebuffer.h"
|
|
|
|
|
#include "RenderPass.h"
|
|
|
|
|
#include "Pipeline.h"
|
2023-11-15 17:42:57 +01:00
|
|
|
#include "Descriptor.h"
|
2023-11-16 22:58:47 +01:00
|
|
|
#include "Window.h"
|
2020-03-24 21:05:32 +01:00
|
|
|
|
|
|
|
|
using namespace Seele;
|
|
|
|
|
using namespace Seele::Vulkan;
|
|
|
|
|
|
|
|
|
|
|
2024-04-10 08:43:56 +02:00
|
|
|
Command::Command(PGraphics graphics, PCommandPool pool)
|
2021-10-19 11:00:39 +02:00
|
|
|
: graphics(graphics)
|
2023-11-15 17:42:57 +01:00
|
|
|
, pool(pool)
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
VkCommandBufferAllocateInfo allocInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
2024-04-10 08:43:56 +02:00
|
|
|
.commandPool = pool->getHandle(),
|
2023-11-15 00:06:00 +01:00
|
|
|
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
|
|
|
|
.commandBufferCount = 1,
|
|
|
|
|
};
|
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);
|
2023-11-17 16:53:37 +01:00
|
|
|
signalSemaphore = new Semaphore(graphics);
|
2023-11-15 00:06:00 +01:00
|
|
|
state = State::Init;
|
2023-11-17 16:53:37 +01:00
|
|
|
//std::cout << "Cmd " << handle << " semaphore " << signalSemaphore->getHandle() << std::endl;
|
2020-03-24 21:05:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
Command::~Command()
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2024-04-10 08:43:56 +02:00
|
|
|
vkFreeCommandBuffers(graphics->getDevice(), pool->getHandle(), 1, &handle);
|
2020-04-12 15:47:19 +02:00
|
|
|
waitSemaphores.clear();
|
2020-03-24 21:05:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
void Command::begin()
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
VkCommandBufferBeginInfo beginInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.flags = 0,
|
|
|
|
|
.pInheritanceInfo = nullptr,
|
|
|
|
|
};
|
2020-03-24 21:05:32 +01:00
|
|
|
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
|
2023-11-15 00:06:00 +01:00
|
|
|
state = State::Begin;
|
2020-03-24 21:05:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
void Command::end()
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
|
|
|
|
VK_CHECK(vkEndCommandBuffer(handle));
|
2023-11-15 00:06:00 +01:00
|
|
|
state = State::End;
|
2020-03-24 21:05:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
void Command::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer)
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
assert(state == State::Begin);
|
2023-11-16 22:58:47 +01:00
|
|
|
boundRenderPass = renderPass;
|
|
|
|
|
boundFramebuffer = framebuffer;
|
2023-11-15 00:06:00 +01:00
|
|
|
VkRenderPassBeginInfo beginInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.renderPass = renderPass->getHandle(),
|
|
|
|
|
.framebuffer = framebuffer->getHandle(),
|
|
|
|
|
.renderArea = renderPass->getRenderArea(),
|
|
|
|
|
.clearValueCount = (uint32)renderPass->getClearValueCount(),
|
|
|
|
|
.pClearValues = renderPass->getClearValues(),
|
|
|
|
|
};
|
2020-03-24 21:05:32 +01:00
|
|
|
vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents());
|
2023-11-15 00:06:00 +01:00
|
|
|
state = State::RenderPass;
|
2020-03-24 21:05:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
void Command::endRenderPass()
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2024-01-31 09:49:53 +01:00
|
|
|
boundRenderPass->endRenderPass();
|
2023-11-16 22:58:47 +01:00
|
|
|
boundRenderPass = nullptr;
|
|
|
|
|
boundFramebuffer = nullptr;
|
2020-03-24 21:05:32 +01:00
|
|
|
vkCmdEndRenderPass(handle);
|
2023-11-15 00:06:00 +01:00
|
|
|
state = State::Begin;
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2024-04-12 09:27:30 +02:00
|
|
|
void Command::executeCommands(Array<Gfx::ORenderCommand> commands)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
assert(state == State::RenderPass);
|
2021-12-02 13:00:03 +01:00
|
|
|
if(commands.size() == 0)
|
|
|
|
|
{
|
2022-03-19 22:45:30 +01:00
|
|
|
//std::cout << "No commands provided" << std::endl;
|
2021-12-02 13:00:03 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2020-04-12 15:47:19 +02:00
|
|
|
Array<VkCommandBuffer> cmdBuffers(commands.size());
|
|
|
|
|
for (uint32 i = 0; i < commands.size(); ++i)
|
|
|
|
|
{
|
2024-04-10 10:23:06 +02:00
|
|
|
auto command = Gfx::PRenderCommand(commands[i]).cast<RenderCommand>();
|
2020-11-03 01:18:30 +01:00
|
|
|
command->end();
|
2024-05-15 15:27:13 +02:00
|
|
|
for(auto& descriptor : command->boundResources)
|
2021-06-04 18:27:49 +02:00
|
|
|
{
|
2024-05-15 15:27:13 +02:00
|
|
|
boundResources.add(descriptor);
|
2023-11-17 16:53:37 +01:00
|
|
|
//std::cout << "Cmd " << handle << " bound descriptor " << descriptor->getHandle() << std::endl;
|
2021-06-04 18:27:49 +02:00
|
|
|
}
|
2021-05-10 23:57:55 +02:00
|
|
|
cmdBuffers[i] = command->getHandle();
|
2024-04-12 09:27:30 +02:00
|
|
|
executingRenders.add(std::move(commands[i]));
|
2021-05-10 23:57:55 +02:00
|
|
|
}
|
|
|
|
|
vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data());
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-12 09:27:30 +02:00
|
|
|
void Command::executeCommands(Array<Gfx::OComputeCommand> commands)
|
2021-05-10 23:57:55 +02:00
|
|
|
{
|
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)
|
|
|
|
|
{
|
2024-04-10 10:23:06 +02:00
|
|
|
auto command = Gfx::PComputeCommand(commands[i]).cast<ComputeCommand>();
|
2021-05-10 23:57:55 +02:00
|
|
|
command->end();
|
2024-05-15 15:27:13 +02:00
|
|
|
for(auto& descriptor : command->boundResources)
|
2021-06-04 18:27:49 +02:00
|
|
|
{
|
2024-05-15 15:27:13 +02:00
|
|
|
boundResources.add(descriptor);
|
2023-11-17 16:53:37 +01:00
|
|
|
//std::cout << "Cmd " << handle << " bound descriptor " << descriptor->getHandle() << std::endl;
|
2021-06-04 18:27:49 +02:00
|
|
|
}
|
2020-11-03 01:18:30 +01:00
|
|
|
cmdBuffers[i] = command->getHandle();
|
2024-04-12 09:27:30 +02:00
|
|
|
executingComputes.add(std::move(commands[i]));
|
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
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
void Command::waitForSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
waitSemaphores.add(semaphore);
|
|
|
|
|
waitFlags.add(flags);
|
2023-11-17 16:53:37 +01:00
|
|
|
//std::cout << "Cmd " << handle << " wait for " << semaphore->getHandle() << std::endl;
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
void Command::checkFence()
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
assert(state == State::Submit || !fence->isSignaled());
|
|
|
|
|
if (fence->isSignaled())
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2023-11-17 16:53:37 +01:00
|
|
|
//std::cout << "Cmd " << handle << " was signaled" << std::endl;
|
2023-11-15 00:06:00 +01:00
|
|
|
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
|
|
|
|
|
fence->reset();
|
|
|
|
|
for(auto& command : executingComputes)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
command->reset();
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
2023-11-15 00:06:00 +01:00
|
|
|
executingComputes.clear();
|
|
|
|
|
for(auto& command : executingRenders)
|
|
|
|
|
{
|
|
|
|
|
command->reset();
|
|
|
|
|
}
|
|
|
|
|
executingRenders.clear();
|
2024-05-15 15:27:13 +02:00
|
|
|
for(auto& descriptor : boundResources)
|
2023-11-15 00:06:00 +01:00
|
|
|
{
|
|
|
|
|
descriptor->unbind();
|
2023-11-17 16:53:37 +01:00
|
|
|
//std::cout << "Cmd " << handle << " unbind " << descriptor->getHandle() << std::endl;
|
2023-11-15 00:06:00 +01:00
|
|
|
}
|
2024-05-15 15:27:13 +02:00
|
|
|
boundResources.clear();
|
|
|
|
|
graphics->getDestructionManager()->notifyCommandComplete();
|
2023-11-15 00:06:00 +01:00
|
|
|
state = State::Init;
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
2020-03-24 21:05:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
void Command::waitForCommand(uint32 timeout)
|
2021-05-10 23:57:55 +02:00
|
|
|
{
|
2023-11-15 17:42:57 +01:00
|
|
|
pool->submitCommands();
|
2023-11-15 00:06:00 +01:00
|
|
|
if (state == State::Begin)
|
2023-02-13 14:56:13 +01:00
|
|
|
{
|
|
|
|
|
// is already done
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-05-10 23:57:55 +02:00
|
|
|
fence->wait(timeout);
|
2023-11-15 00:06:00 +01:00
|
|
|
checkFence();
|
2021-05-10 23:57:55 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-15 15:27:13 +02:00
|
|
|
void Command::bindResource(PCommandBoundResource resource)
|
|
|
|
|
{
|
|
|
|
|
resource->bind();
|
|
|
|
|
boundResources.add(resource);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
PFence Command::getFence()
|
2020-05-05 01:51:13 +02:00
|
|
|
{
|
|
|
|
|
return fence;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-15 17:42:57 +01:00
|
|
|
PCommandPool Command::getPool()
|
2020-09-19 14:36:50 +02:00
|
|
|
{
|
2023-11-15 17:42:57 +01:00
|
|
|
return pool;
|
2020-09-19 14:36:50 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-19 11:00:39 +02:00
|
|
|
RenderCommand::RenderCommand(PGraphics graphics, VkCommandPool cmdPool)
|
|
|
|
|
: graphics(graphics)
|
|
|
|
|
, owner(cmdPool)
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
VkCommandBufferAllocateInfo allocInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.commandPool = owner,
|
|
|
|
|
.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY,
|
|
|
|
|
.commandBufferCount = 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()
|
|
|
|
|
{
|
2021-10-19 11:00:39 +02:00
|
|
|
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
|
2021-05-10 23:57:55 +02:00
|
|
|
}
|
|
|
|
|
|
2022-01-12 14:40:26 +01:00
|
|
|
void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer)
|
2021-05-10 23:57:55 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
threadId = std::this_thread::get_id();
|
2021-05-10 23:57:55 +02:00
|
|
|
ready = false;
|
2023-11-15 17:42:57 +01:00
|
|
|
VkCommandBufferInheritanceInfo inheritanceInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
|
|
|
|
|
.renderPass = renderPass->getHandle(),
|
|
|
|
|
.subpass = 0,
|
|
|
|
|
.framebuffer = framebuffer->getHandle(),
|
|
|
|
|
.occlusionQueryEnable = 0,
|
|
|
|
|
.queryFlags = 0,
|
|
|
|
|
.pipelineStatistics = 0,
|
|
|
|
|
};
|
|
|
|
|
VkCommandBufferBeginInfo beginInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
|
|
|
|
|
.pInheritanceInfo = &inheritanceInfo,
|
|
|
|
|
};
|
2021-05-10 23:57:55 +02:00
|
|
|
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-19 11:00:39 +02:00
|
|
|
void RenderCommand::end()
|
|
|
|
|
{
|
|
|
|
|
VK_CHECK(vkEndCommandBuffer(handle));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RenderCommand::reset()
|
|
|
|
|
{
|
|
|
|
|
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
|
2024-05-15 15:27:13 +02:00
|
|
|
boundResources.clear();
|
2021-10-19 11:00:39 +02:00
|
|
|
ready = true;
|
|
|
|
|
}
|
2021-05-10 23:57:55 +02:00
|
|
|
|
|
|
|
|
bool RenderCommand::isReady()
|
2020-10-30 18:45:35 +01:00
|
|
|
{
|
2021-04-13 23:09:16 +02:00
|
|
|
return ready;
|
2020-10-30 18:45:35 +01:00
|
|
|
}
|
|
|
|
|
|
2021-05-10 23:57:55 +02:00
|
|
|
void RenderCommand::setViewport(Gfx::PViewport viewport)
|
2020-10-03 11:00:10 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2020-10-03 11:00:10 +02:00
|
|
|
VkViewport vp = viewport.cast<Viewport>()->getHandle();
|
2023-11-15 17:42:57 +01:00
|
|
|
VkRect2D scissors = {
|
|
|
|
|
.offset = {
|
|
|
|
|
.x = (int32)viewport->getOffsetX(),
|
|
|
|
|
.y = (int32)viewport->getOffsetY(),
|
|
|
|
|
},
|
|
|
|
|
.extent = {
|
|
|
|
|
.width = viewport->getWidth(),
|
|
|
|
|
.height = viewport->getHeight(),
|
|
|
|
|
},
|
|
|
|
|
};
|
2020-10-03 11:00:10 +02:00
|
|
|
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
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2020-05-05 01:51:13 +02:00
|
|
|
pipeline = gfxPipeline.cast<GraphicsPipeline>();
|
|
|
|
|
pipeline->bind(handle);
|
|
|
|
|
}
|
2024-05-08 10:51:59 +02:00
|
|
|
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array<uint32> dynamicOffsets)
|
2020-05-05 01:51:13 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2020-11-03 01:18:30 +01:00
|
|
|
auto descriptor = descriptorSet.cast<DescriptorSet>();
|
2022-04-15 23:45:44 +02:00
|
|
|
assert(descriptor->writeDescriptors.size() == 0);
|
2021-10-19 11:00:39 +02:00
|
|
|
descriptor->bind();
|
2024-05-16 19:47:35 +02:00
|
|
|
boundResources.add(descriptor.getHandle());
|
2024-05-18 21:23:59 +02:00
|
|
|
for (auto binding : descriptor->boundResources)
|
|
|
|
|
{
|
|
|
|
|
binding->bind();
|
|
|
|
|
boundResources.add(binding);
|
|
|
|
|
}
|
2021-09-23 10:10:39 +02:00
|
|
|
|
2020-11-03 01:18:30 +01:00
|
|
|
VkDescriptorSet setHandle = descriptor->getHandle();
|
2024-05-08 10:51:59 +02:00
|
|
|
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, dynamicOffsets.size(), dynamicOffsets.data());
|
2020-05-05 01:51:13 +02:00
|
|
|
}
|
2024-05-15 15:27:13 +02:00
|
|
|
|
2024-05-08 10:51:59 +02:00
|
|
|
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets, Array<uint32> dynamicOffsets)
|
2020-10-03 11:00:10 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01: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>();
|
2022-04-15 23:45:44 +02:00
|
|
|
assert(descriptorSet->writeDescriptors.size() == 0);
|
2021-10-19 11:00:39 +02:00
|
|
|
descriptorSet->bind();
|
2024-05-15 15:27:13 +02:00
|
|
|
boundResources.add(descriptorSet.getHandle());
|
2024-05-18 21:23:59 +02:00
|
|
|
|
|
|
|
|
for (auto binding : descriptorSet->boundResources)
|
|
|
|
|
{
|
|
|
|
|
binding->bind();
|
|
|
|
|
boundResources.add(binding);
|
|
|
|
|
}
|
2024-04-23 08:11:44 +02:00
|
|
|
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
2020-10-03 11:00:10 +02:00
|
|
|
}
|
2024-05-08 10:51:59 +02:00
|
|
|
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, dynamicOffsets.size(), dynamicOffsets.data());
|
2020-10-03 11:00:10 +02:00
|
|
|
delete[] sets;
|
2024-05-15 15:27:13 +02:00
|
|
|
|
2020-10-03 11:00:10 +02:00
|
|
|
}
|
2023-11-01 23:12:30 +01:00
|
|
|
void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer>& streams)
|
2020-05-05 01:51:13 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01: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)
|
|
|
|
|
{
|
2023-11-01 23:12:30 +01:00
|
|
|
PVertexBuffer buf = streams[i].cast<VertexBuffer>();
|
2020-06-08 01:44:47 +02:00
|
|
|
buffers[i] = buf->getHandle();
|
2023-11-01 23:12:30 +01:00
|
|
|
offsets[i] = 0;
|
2024-05-15 15:27:13 +02:00
|
|
|
buf->getAlloc()->bind();
|
|
|
|
|
boundResources.add(buf->getAlloc());
|
2020-06-08 01:44:47 +02:00
|
|
|
};
|
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
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2020-05-05 01:51:13 +02:00
|
|
|
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
|
2024-05-15 15:27:13 +02:00
|
|
|
buf->getAlloc()->bind();
|
|
|
|
|
boundResources.add(buf->getAlloc());
|
2020-10-23 01:47:56 +02:00
|
|
|
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, cast(buf->getIndexType()));
|
2020-05-05 01:51:13 +02:00
|
|
|
}
|
2022-04-15 11:19:30 +02:00
|
|
|
|
2024-05-12 19:36:32 +02:00
|
|
|
void RenderCommand::pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data)
|
2022-04-15 11:19:30 +02:00
|
|
|
{
|
|
|
|
|
assert(threadId == std::this_thread::get_id());
|
2024-05-12 19:36:32 +02:00
|
|
|
vkCmdPushConstants(handle, pipeline->getLayout(), stage, offset, size, data);
|
2022-04-15 11:19:30 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-23 10:10:39 +02:00
|
|
|
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance)
|
|
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2021-09-23 10:10:39 +02:00
|
|
|
vkCmdDraw(handle, vertexCount, instanceCount, firstVertex, firstInstance);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 22:24:40 +01:00
|
|
|
void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance)
|
|
|
|
|
{
|
|
|
|
|
assert(threadId == std::this_thread::get_id());
|
2023-11-11 13:56:12 +01:00
|
|
|
vkCmdDrawIndexed(handle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
2023-11-06 22:24:40 +01:00
|
|
|
}
|
2024-04-10 08:43:56 +02:00
|
|
|
void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ)
|
2023-10-24 15:01:09 +02:00
|
|
|
{
|
|
|
|
|
assert(threadId == std::this_thread::get_id());
|
2023-11-05 10:36:01 +01:00
|
|
|
graphics->vkCmdDrawMeshTasksEXT(handle, groupX, groupY, groupZ);
|
2023-10-24 15:01:09 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-09 08:41:46 +02:00
|
|
|
void RenderCommand::drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride)
|
|
|
|
|
{
|
|
|
|
|
assert(threadId == std::this_thread::get_id());
|
|
|
|
|
graphics->vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset, drawCount, stride);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-10 23:57:55 +02:00
|
|
|
ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool)
|
2021-10-19 11:00:39 +02:00
|
|
|
: graphics(graphics)
|
|
|
|
|
, owner(cmdPool)
|
2021-05-10 23:57:55 +02:00
|
|
|
{
|
2023-11-15 17:42:57 +01:00
|
|
|
VkCommandBufferAllocateInfo allocInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.commandPool = owner,
|
|
|
|
|
.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY,
|
|
|
|
|
.commandBufferCount = 1,
|
|
|
|
|
};
|
2021-10-19 11:00:39 +02:00
|
|
|
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle));
|
2021-05-10 23:57:55 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-19 11:00:39 +02:00
|
|
|
|
2021-05-10 23:57:55 +02:00
|
|
|
ComputeCommand::~ComputeCommand()
|
|
|
|
|
{
|
2021-10-19 11:00:39 +02:00
|
|
|
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
|
2021-05-10 23:57:55 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 17:42:57 +01:00
|
|
|
void ComputeCommand::begin()
|
2021-05-10 23:57:55 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
threadId = std::this_thread::get_id();
|
2021-05-10 23:57:55 +02:00
|
|
|
ready = false;
|
2023-11-15 17:42:57 +01:00
|
|
|
VkCommandBufferInheritanceInfo inheritanceInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
|
|
|
|
|
.renderPass = VK_NULL_HANDLE,
|
|
|
|
|
.subpass = 0,
|
|
|
|
|
.framebuffer = VK_NULL_HANDLE,
|
|
|
|
|
.occlusionQueryEnable = 0,
|
|
|
|
|
.queryFlags = 0,
|
|
|
|
|
.pipelineStatistics = 0,
|
|
|
|
|
};
|
|
|
|
|
VkCommandBufferBeginInfo beginInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.flags = 0,
|
|
|
|
|
.pInheritanceInfo = &inheritanceInfo,
|
|
|
|
|
};
|
2021-05-10 23:57:55 +02:00
|
|
|
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-19 11:00:39 +02:00
|
|
|
void ComputeCommand::end()
|
|
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2021-10-19 11:00:39 +02:00
|
|
|
VK_CHECK(vkEndCommandBuffer(handle));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ComputeCommand::reset()
|
|
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2021-10-19 11:00:39 +02:00
|
|
|
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
|
2024-05-15 15:27:13 +02:00
|
|
|
boundResources.clear();
|
2021-10-19 11:00:39 +02:00
|
|
|
ready = true;
|
|
|
|
|
}
|
2021-05-10 23:57:55 +02:00
|
|
|
bool ComputeCommand::isReady()
|
|
|
|
|
{
|
|
|
|
|
return ready;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ComputeCommand::bindPipeline(Gfx::PComputePipeline computePipeline)
|
|
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2021-05-10 23:57:55 +02:00
|
|
|
pipeline = computePipeline.cast<ComputePipeline>();
|
|
|
|
|
pipeline->bind(handle);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-08 10:51:59 +02:00
|
|
|
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array<uint32> dynamicOffsets)
|
2021-05-10 23:57:55 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2021-05-10 23:57:55 +02:00
|
|
|
auto descriptor = descriptorSet.cast<DescriptorSet>();
|
2022-04-15 23:45:44 +02:00
|
|
|
assert(descriptor->writeDescriptors.size() == 0);
|
2024-05-15 15:27:13 +02:00
|
|
|
boundResources.add(descriptor.getHandle());
|
2024-05-18 21:23:59 +02:00
|
|
|
|
|
|
|
|
for (auto binding : descriptor->boundResources)
|
|
|
|
|
{
|
|
|
|
|
binding->bind();
|
|
|
|
|
boundResources.add(binding);
|
|
|
|
|
}
|
2021-10-19 23:04:38 +02:00
|
|
|
|
2021-05-10 23:57:55 +02:00
|
|
|
VkDescriptorSet setHandle = descriptor->getHandle();
|
2024-05-08 10:51:59 +02:00
|
|
|
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, dynamicOffsets.size(), dynamicOffsets.data());
|
2021-05-10 23:57:55 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-08 10:51:59 +02:00
|
|
|
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets, Array<uint32> dynamicOffsets)
|
2021-05-10 23:57:55 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
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>();
|
2022-04-15 23:45:44 +02:00
|
|
|
assert(descriptorSet->writeDescriptors.size() == 0);
|
2021-10-19 11:00:39 +02:00
|
|
|
descriptorSet->bind();
|
2024-05-18 21:23:59 +02:00
|
|
|
boundResources.add(descriptorSet.getHandle());
|
2022-04-15 23:45:44 +02:00
|
|
|
|
2021-06-04 18:27:49 +02:00
|
|
|
//std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl;
|
2024-05-18 21:23:59 +02:00
|
|
|
for (auto binding : descriptorSet->boundResources)
|
|
|
|
|
{
|
|
|
|
|
binding->bind();
|
|
|
|
|
boundResources.add(binding);
|
|
|
|
|
}
|
2024-04-23 08:11:44 +02:00
|
|
|
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
2021-05-10 23:57:55 +02:00
|
|
|
}
|
2024-05-08 10:51:59 +02:00
|
|
|
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, dynamicOffsets.size(), dynamicOffsets.data());
|
2021-05-10 23:57:55 +02:00
|
|
|
delete[] sets;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-12 19:36:32 +02:00
|
|
|
void ComputeCommand::pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data)
|
2022-04-15 11:19:30 +02:00
|
|
|
{
|
|
|
|
|
assert(threadId == std::this_thread::get_id());
|
2024-05-12 19:36:32 +02:00
|
|
|
vkCmdPushConstants(handle, pipeline->getLayout(), stage, offset, size, data);
|
2022-04-15 11:19:30 +02:00
|
|
|
}
|
|
|
|
|
|
2021-05-10 23:57:55 +02:00
|
|
|
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ)
|
|
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
assert(threadId == std::this_thread::get_id());
|
2021-05-10 23:57:55 +02:00
|
|
|
vkCmdDispatch(handle, threadX, threadY, threadZ);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
CommandPool::CommandPool(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
|
|
|
{
|
2023-11-15 17:42:57 +01:00
|
|
|
VkCommandPoolCreateInfo info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
|
|
|
|
.queueFamilyIndex = queue->getFamilyIndex(),
|
|
|
|
|
};
|
2020-03-24 21:05:32 +01:00
|
|
|
VK_CHECK(vkCreateCommandPool(graphics->getDevice(), &info, nullptr, &commandPool));
|
2024-01-26 23:19:18 +01:00
|
|
|
// TODO: dont reset individual commands, reset pool instead
|
2024-04-10 08:43:56 +02:00
|
|
|
allocatedBuffers.add(new Command(graphics, this));
|
2023-11-01 23:12:30 +01:00
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
command = allocatedBuffers.back();
|
|
|
|
|
command->begin();
|
2020-03-24 21:05:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
CommandPool::~CommandPool()
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2023-11-26 12:47:48 +01:00
|
|
|
vkDeviceWaitIdle(graphics->getDevice());
|
2024-04-23 08:11:44 +02:00
|
|
|
for (auto& cmd : allocatedBuffers)
|
2023-12-02 10:55:00 +01:00
|
|
|
{
|
2024-04-23 08:11:44 +02:00
|
|
|
cmd->checkFence();
|
2023-12-02 10:55:00 +01:00
|
|
|
}
|
2023-11-17 22:31:26 +01:00
|
|
|
allocatedRenderCommands.clear();
|
|
|
|
|
allocatedComputeCommands.clear();
|
|
|
|
|
allocatedBuffers.clear();
|
2020-03-24 21:05:32 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2023-11-15 17:42:57 +01:00
|
|
|
PCommand CommandPool::getCommands()
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
return command;
|
2020-03-24 21:05:32 +01:00
|
|
|
}
|
2024-04-10 10:23:06 +02:00
|
|
|
void CommandPool::cacheCommands(Array<ORenderCommand> commands)
|
|
|
|
|
{
|
2024-04-23 08:11:44 +02:00
|
|
|
for(auto&& cmd : commands)
|
2024-04-12 09:27:30 +02:00
|
|
|
{
|
2024-04-23 08:11:44 +02:00
|
|
|
allocatedRenderCommands.add(std::move(cmd));
|
2024-04-12 09:27:30 +02:00
|
|
|
}
|
2024-04-10 10:23:06 +02:00
|
|
|
}
|
2020-03-24 21:05:32 +01:00
|
|
|
|
2024-04-10 10:23:06 +02:00
|
|
|
void CommandPool::cacheCommands(Array<OComputeCommand> commands)
|
|
|
|
|
{
|
2024-04-23 08:11:44 +02:00
|
|
|
for(auto&& cmd : commands)
|
2024-04-12 09:27:30 +02:00
|
|
|
{
|
2024-04-23 08:11:44 +02:00
|
|
|
allocatedComputeCommands.add(std::move(cmd));
|
2024-04-12 09:27:30 +02:00
|
|
|
}
|
2024-04-10 10:23:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ORenderCommand CommandPool::createRenderCommand(const std::string& name)
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2021-05-10 23:57:55 +02:00
|
|
|
for (uint32 i = 0; i < allocatedRenderCommands.size(); ++i)
|
2021-04-13 23:09:16 +02:00
|
|
|
{
|
2024-04-10 10:23:06 +02:00
|
|
|
if (allocatedRenderCommands[i]->isReady())
|
2021-04-13 23:09:16 +02:00
|
|
|
{
|
2024-04-10 10:23:06 +02:00
|
|
|
ORenderCommand cmdBuffer = std::move(allocatedRenderCommands[i]);
|
|
|
|
|
allocatedRenderCommands.removeAt(i, false);
|
2021-10-19 23:04:38 +02:00
|
|
|
cmdBuffer->name = name;
|
2023-11-15 17:42:57 +01:00
|
|
|
cmdBuffer->begin(command->boundRenderPass, command->boundFramebuffer);
|
2021-04-13 23:09:16 +02:00
|
|
|
return cmdBuffer;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-10 10:23:06 +02:00
|
|
|
ORenderCommand result = new RenderCommand(graphics, commandPool);
|
2021-05-10 23:57:55 +02:00
|
|
|
result->name = name;
|
2023-11-15 17:42:57 +01:00
|
|
|
result->begin(command->boundRenderPass, command->boundFramebuffer);
|
2021-05-10 23:57:55 +02:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 10:23:06 +02:00
|
|
|
OComputeCommand CommandPool::createComputeCommand(const std::string& name)
|
2021-05-10 23:57:55 +02:00
|
|
|
{
|
|
|
|
|
for (uint32 i = 0; i < allocatedComputeCommands.size(); ++i)
|
|
|
|
|
{
|
2024-04-10 10:23:06 +02:00
|
|
|
if (allocatedComputeCommands[i]->isReady())
|
2021-05-10 23:57:55 +02:00
|
|
|
{
|
2024-04-10 10:23:06 +02:00
|
|
|
OComputeCommand cmdBuffer = std::move(allocatedComputeCommands[i]);
|
|
|
|
|
allocatedComputeCommands.removeAt(i, false);
|
2021-10-19 23:04:38 +02:00
|
|
|
cmdBuffer->name = name;
|
2023-11-15 17:42:57 +01:00
|
|
|
cmdBuffer->begin();
|
2021-05-10 23:57:55 +02:00
|
|
|
return cmdBuffer;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-10 10:23:06 +02:00
|
|
|
OComputeCommand result = new ComputeCommand(graphics, commandPool);
|
2021-05-10 23:57:55 +02:00
|
|
|
result->name = name;
|
2023-11-15 17:42:57 +01:00
|
|
|
result->begin();
|
2021-04-13 23:09:16 +02:00
|
|
|
return result;
|
2020-03-24 21:05:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 00:06:00 +01:00
|
|
|
void CommandPool::submitCommands(PSemaphore signalSemaphore)
|
2020-03-24 21:05:32 +01:00
|
|
|
{
|
2023-11-15 17:42:57 +01:00
|
|
|
assert(command->state == Command::State::Begin); // Not in a renderpass
|
|
|
|
|
command->end();
|
2023-11-17 16:53:37 +01:00
|
|
|
Array<VkSemaphore> semaphores = { command->signalSemaphore->getHandle() };
|
2023-11-15 17:42:57 +01:00
|
|
|
if (signalSemaphore != nullptr)
|
2020-04-01 02:17:49 +02:00
|
|
|
{
|
2023-11-17 16:53:37 +01:00
|
|
|
semaphores.add(signalSemaphore->getHandle());
|
2020-04-01 02:17:49 +02:00
|
|
|
}
|
2023-11-17 16:53:37 +01:00
|
|
|
queue->submitCommandBuffer(command, semaphores);
|
|
|
|
|
//std::cout << "Cmd " << command->getHandle() << " signalling " << command->signalSemaphore->getHandle() << std::endl;
|
|
|
|
|
|
|
|
|
|
PSemaphore waitSemaphore = command->signalSemaphore;
|
2020-04-12 15:47:19 +02:00
|
|
|
for (uint32 i = 0; i < allocatedBuffers.size(); ++i)
|
2020-04-01 02:17:49 +02:00
|
|
|
{
|
2023-11-15 17:42:57 +01:00
|
|
|
PCommand cmdBuffer = allocatedBuffers[i];
|
2023-11-15 00:06:00 +01:00
|
|
|
cmdBuffer->checkFence();
|
|
|
|
|
if (cmdBuffer->state == Command::State::Init)
|
2020-04-01 02:17:49 +02:00
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
command = cmdBuffer;
|
|
|
|
|
command->begin();
|
2023-11-17 16:53:37 +01:00
|
|
|
command->waitForSemaphore(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, waitSemaphore);
|
2020-04-01 02:17:49 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-11-15 00:06:00 +01:00
|
|
|
assert(cmdBuffer->state == Command::State::Submit);
|
2020-04-01 02:17:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-04-10 08:43:56 +02:00
|
|
|
allocatedBuffers.add(new Command(graphics, this));
|
2023-11-15 00:06:00 +01:00
|
|
|
command = allocatedBuffers.back();
|
|
|
|
|
command->begin();
|
2023-11-17 16:53:37 +01:00
|
|
|
command->waitForSemaphore(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, waitSemaphore);
|
2023-11-11 13:56:12 +01:00
|
|
|
}
|