More refactoring

This commit is contained in:
Dynamitos
2023-11-15 00:06:00 +01:00
parent 59d6c9d794
commit f8f48352a3
49 changed files with 930 additions and 1015 deletions
+526
View File
@@ -0,0 +1,526 @@
#include "CommandBuffer.h"
#include "Initializer.h"
#include "Graphics.h"
#include "Pipeline.h"
#include "Enums.h"
#include "Framebuffer.h"
#include "RenderPass.h"
#include "Pipeline.h"
#include "DescriptorSets.h"
#include "RenderTarget.h"
#include <vulkan/vulkan_core.h>
using namespace Seele;
using namespace Seele::Vulkan;
Command::Command(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager)
: graphics(graphics)
, manager(manager)
, owner(cmdPool)
{
VkCommandBufferAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = nullptr,
.commandPool = owner,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
};
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle))
fence = new Fence(graphics);
state = State::Init;
}
Command::~Command()
{
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
waitSemaphores.clear();
}
void Command::begin()
{
VkCommandBufferBeginInfo beginInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.pNext = nullptr,
.flags = 0,
.pInheritanceInfo = nullptr,
};
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
state = State::Begin;
}
void Command::end()
{
VK_CHECK(vkEndCommandBuffer(handle));
state = State::End;
}
void Command::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer)
{
assert(state == State::Begin);
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(),
};
vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents());
state = State::RenderPass;
}
void Command::endRenderPass()
{
vkCmdEndRenderPass(handle);
state = State::Begin;
}
void Command::executeCommands(const Array<Gfx::PRenderCommand>& commands)
{
assert(state == State::RenderPass);
if(commands.size() == 0)
{
//std::cout << "No commands provided" << std::endl;
return;
}
Array<VkCommandBuffer> cmdBuffers(commands.size());
for (uint32 i = 0; i < commands.size(); ++i)
{
auto command = commands[i].cast<RenderCommand>();
command->end();
executingRenders.add(command);
for(auto& descriptor : command->boundDescriptors)
{
boundDescriptors.add(descriptor);
}
cmdBuffers[i] = command->getHandle();
}
vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data());
}
void Command::executeCommands(const Array<Gfx::PComputeCommand>& commands)
{
if(commands.size() == 0)
{
return;
}
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)
{
boundDescriptors.add(descriptor);
}
cmdBuffers[i] = command->getHandle();
}
vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data());
}
void Command::waitForSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore)
{
waitSemaphores.add(semaphore);
waitFlags.add(flags);
}
void Command::checkFence()
{
assert(state == State::Submit || !fence->isSignaled());
if (fence->isSignaled())
{
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
fence->reset();
for(auto& command : executingComputes)
{
command->reset();
}
executingComputes.clear();
for(auto& command : executingRenders)
{
command->reset();
}
executingRenders.clear();
for(auto& descriptor : boundDescriptors)
{
descriptor->unbind();
}
boundDescriptors.clear();
graphics->getDestructionManager()->notifyCmdComplete(this);
state = State::Init;
}
}
void Command::waitForCommand(uint32 timeout)
{
manager->submitCommands();
if (state == State::Begin)
{
// is already done
return;
}
fence->wait(timeout);
checkFence();
}
PFence Command::getFence()
{
return fence;
}
PCommandBufferManager Command::getManager()
{
return manager;
}
RenderCommand::RenderCommand(PGraphics graphics, VkCommandPool cmdPool)
: graphics(graphics)
, owner(cmdPool)
{
VkCommandBufferAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = nullptr,
.commandPool = owner,
.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY,
.commandBufferCount = 1,
};
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle));
}
RenderCommand::~RenderCommand()
{
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
}
void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer)
{
threadId = std::this_thread::get_id();
ready = false;
VkCommandBufferBeginInfo beginInfo =
init::CommandBufferBeginInfo();
VkCommandBufferInheritanceInfo inheritanceInfo =
init::CommandBufferInheritanceInfo();
inheritanceInfo.framebuffer = framebuffer->getHandle();
inheritanceInfo.renderPass = renderPass->getHandle();
inheritanceInfo.subpass = 0;
beginInfo.pInheritanceInfo = &inheritanceInfo;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
}
void RenderCommand::end()
{
VK_CHECK(vkEndCommandBuffer(handle));
}
void RenderCommand::reset()
{
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
boundDescriptors.clear();
ready = true;
}
bool RenderCommand::isReady()
{
return ready;
}
void RenderCommand::setViewport(Gfx::PViewport viewport)
{
assert(threadId == std::this_thread::get_id());
VkViewport vp = viewport.cast<Viewport>()->getHandle();
VkRect2D scissors = init::Rect2D(viewport->getWidth(), viewport->getHeight(), viewport->getOffsetX(), viewport->getOffsetY());
vkCmdSetViewport(handle, 0, 1, &vp);
vkCmdSetScissor(handle, 0, 1, &scissors);
}
void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline)
{
assert(threadId == std::this_thread::get_id());
pipeline = gfxPipeline.cast<GraphicsPipeline>();
pipeline->bind(handle);
}
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
{
assert(threadId == std::this_thread::get_id());
auto descriptor = descriptorSet.cast<DescriptorSet>();
assert(descriptor->writeDescriptors.size() == 0);
boundDescriptors.add(descriptor.getHandle());
descriptor->bind();
VkDescriptorSet setHandle = descriptor->getHandle();
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr);
}
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets)
{
assert(threadId == std::this_thread::get_id());
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
for(uint32 i = 0; i < descriptorSets.size(); ++i)
{
auto descriptorSet = descriptorSets[i].cast<DescriptorSet>();
assert(descriptorSet->writeDescriptors.size() == 0);
descriptorSet->bind();
boundDescriptors.add(descriptorSet.getHandle());
sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle();
}
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr);
delete[] sets;
}
void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer>& streams)
{
assert(threadId == std::this_thread::get_id());
Array<VkBuffer> buffers(streams.size());
Array<VkDeviceSize> offsets(streams.size());
for(uint32 i = 0; i < streams.size(); ++i)
{
PVertexBuffer buf = streams[i].cast<VertexBuffer>();
buffers[i] = buf->getHandle();
offsets[i] = 0;
};
vkCmdBindVertexBuffers(handle, 0, (uint32)streams.size(), buffers.data(), offsets.data());
}
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
{
assert(threadId == std::this_thread::get_id());
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, cast(buf->getIndexType()));
}
void RenderCommand::pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data)
{
assert(threadId == std::this_thread::get_id());
vkCmdPushConstants(handle, layout.cast<PipelineLayout>()->getHandle(), stage, offset, size, data);
}
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance)
{
assert(threadId == std::this_thread::get_id());
vkCmdDraw(handle, vertexCount, instanceCount, firstVertex, firstInstance);
}
void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance)
{
assert(threadId == std::this_thread::get_id());
vkCmdDrawIndexed(handle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
}
void RenderCommand::dispatch(uint32 groupX, uint32 groupY, uint32 groupZ)
{
assert(threadId == std::this_thread::get_id());
graphics->vkCmdDrawMeshTasksEXT(handle, groupX, groupY, groupZ);
}
ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool)
: graphics(graphics)
, owner(cmdPool)
{
VkCommandBufferAllocateInfo allocInfo =
init::CommandBufferAllocateInfo(cmdPool,
VK_COMMAND_BUFFER_LEVEL_SECONDARY,
1);
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle));
}
ComputeCommand::~ComputeCommand()
{
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
}
void ComputeCommand::begin(PCmdBuffer)
{
threadId = std::this_thread::get_id();
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;
}
bool ComputeCommand::isReady()
{
return ready;
}
void ComputeCommand::bindPipeline(Gfx::PComputePipeline computePipeline)
{
assert(threadId == std::this_thread::get_id());
pipeline = computePipeline.cast<ComputePipeline>();
pipeline->bind(handle);
}
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
{
assert(threadId == std::this_thread::get_id());
auto descriptor = descriptorSet.cast<DescriptorSet>();
assert(descriptor->writeDescriptors.size() == 0);
boundDescriptors.add(descriptor.getHandle());
descriptor->bind();
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());
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
for(uint32 i = 0; i < descriptorSets.size(); ++i)
{
auto descriptorSet = descriptorSets[i].cast<DescriptorSet>();
assert(descriptorSet->writeDescriptors.size() == 0);
descriptorSet->bind();
//std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl;
boundDescriptors.add(descriptorSet.getHandle());
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::pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data)
{
assert(threadId == std::this_thread::get_id());
vkCmdPushConstants(handle, layout.cast<PipelineLayout>()->getHandle(), stage, offset, size, data);
}
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ)
{
assert(threadId == std::this_thread::get_id());
vkCmdDispatch(handle, threadX, threadY, threadZ);
}
CommandPool::CommandPool(PGraphics graphics, PQueue queue)
: graphics(graphics), queue(queue), queueFamilyIndex(queue->getFamilyIndex())
{
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));
allocatedBuffers.add(new Command(graphics, commandPool, this));
command = allocatedBuffers.back();
command->begin();
}
CommandPool::~CommandPool()
{
vkDestroyCommandPool(graphics->getDevice(), commandPool, nullptr);
graphics = nullptr;
queue = nullptr;
}
PCmdBuffer CommandPool::getCommands()
{
return command;
}
PRenderCommand CommandPool::createRenderCommand(PRenderPass renderPass, PFramebuffer framebuffer, const std::string& name)
{
std::scoped_lock lck(allocatedRenderLock);
for (uint32 i = 0; i < allocatedRenderCommands.size(); ++i)
{
PRenderCommand cmdBuffer = allocatedRenderCommands[i];
if (cmdBuffer->isReady())
{
cmdBuffer->name = name;
cmdBuffer->begin(renderPass, framebuffer);
return cmdBuffer;
}
}
allocatedRenderCommands.add(new RenderCommand(graphics, commandPool));
PRenderCommand result = allocatedRenderCommands.back();
result->name = name;
result->begin(renderPass, framebuffer);
return result;
}
PComputeCommand CommandPool::createComputeCommand(const std::string& name)
{
std::scoped_lock lck(allocatedComputeLock);
for (uint32 i = 0; i < allocatedComputeCommands.size(); ++i)
{
PComputeCommand cmdBuffer = allocatedComputeCommands[i];
if (cmdBuffer->isReady())
{
cmdBuffer->name = name;
cmdBuffer->begin(command);
return cmdBuffer;
}
}
allocatedComputeCommands.add(new ComputeCommand(graphics, commandPool));
PComputeCommand result = allocatedComputeCommands.back();
result->name = name;
result->begin(command);
return result;
}
void CommandPool::submitCommands(PSemaphore signalSemaphore)
{
if (command->state == Command::State::Begin || command->state == Command::State::RenderPass)
{
if (command->state == Command::State::RenderPass)
{
std::cout << "End of renderpass forced" << std::endl;
command->endRenderPass();
}
command->end();
if (signalSemaphore != nullptr)
{
queue->submitCommandBuffer(command, signalSemaphore->getHandle());
}
else
{
queue->submitCommandBuffer(command);
}
}
std::scoped_lock map(allocatedBufferLock);
for (uint32 i = 0; i < allocatedBuffers.size(); ++i)
{
PCmdBuffer cmdBuffer = allocatedBuffers[i];
cmdBuffer->checkFence();
if (cmdBuffer->state == Command::State::Init)
{
command = cmdBuffer;
command->begin();
return;
}
else
{
assert(cmdBuffer->state == Command::State::Submit);
}
}
allocatedBuffers.add(new Command(graphics, commandPool, this));
command = allocatedBuffers.back();
command->begin();
}