Render graph execution fixed

GetVkQueue function deleted. More specific function implemented (Present).
This commit is contained in:
Brandon Mak 2022-09-15 09:16:13 +08:00
parent 44e529f06f
commit 169822c221
10 changed files with 127 additions and 47 deletions

View File

@ -48,6 +48,7 @@ namespace Sandbox
//SHADE::SHEditor::PreRender();
//#endif
graphicsSystem->BeginRender();
graphicsSystem->Run(1.0f);
//#ifdef SHEDITOR
//SHADE::SHEditor::PreRender();
//SHADE::SHEditor::Update();

View File

@ -76,7 +76,10 @@ namespace SHADE
// Check if command buffer is ready to record.
if (cmdBufferState != SH_CMD_BUFFER_STATE::INITIAL)
{
SHLOG_ERROR("Command buffer not in initial state, cannot begin recording. ");
SHLOG_ERROR("Command buffer not in initial state, cannot begin recording. Command buffer could be: \n"
"- corrupted and in invalid state\n"
"- in executable state\n"
"- in pending state\n");
return;
}
@ -182,7 +185,9 @@ namespace SHADE
// Check if render area is optimal
if (!IsRenderAreaOptimal(renderpassHdl, framebufferExtent, renderPassInfo.renderArea))
{
SHLOG_ERROR("Render area in renderpass begin info is not optimal. See Vulkan vkGetRenderAreaGranularity for details.");
}
// Begin the render pass
vkCommandBuffer.beginRenderPass (&renderPassInfo, vk::SubpassContents::eInline);
@ -431,6 +436,16 @@ namespace SHADE
);
}
bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept
{
return cmdBufferState == SH_CMD_BUFFER_STATE::EXECUTABLE;
}
void SHVkCommandBuffer::HandlePostSubmit(void) noexcept
{
SetState(SH_CMD_BUFFER_STATE::PENDING);
}
//void SHVkCommandBuffer::PipelineBarrier(vk::PipelineStageFlags ) const noexcept
//{
// //vkCommandBuffer.pipelineBarrier()
@ -493,9 +508,7 @@ namespace SHADE
{
vk::Extent2D granularity = parentPool->GetLogicalDevice()->GetVkLogicalDevice().getRenderAreaGranularity(renderpassHdl->GetVkRenderpass());
return (renderArea.offset.x % granularity.width == 0 && renderArea.offset.y % granularity.height == 0 &&
(renderArea.extent.width % granularity.width || renderArea.offset.x + renderArea.extent.width == framebufferExtent.width) &&
(renderArea.extent.height % granularity.height || renderArea.offset.y + renderArea.extent.height == framebufferExtent.height));
return (renderArea.offset.x % granularity.width == 0 && renderArea.offset.y % granularity.height == 0 && (renderArea.extent.width % granularity.width || renderArea.offset.x + renderArea.extent.width == framebufferExtent.width) && (renderArea.extent.height % granularity.height || renderArea.offset.y + renderArea.extent.height == framebufferExtent.height));
}
/***************************************************************************/
@ -559,6 +572,7 @@ namespace SHADE
, usageFlags{}
, commandBufferCount{ 0 }
, parentPool{commandPool}
, pushConstantData{}
{
vk::CommandBufferAllocateInfo allocateInfo{};

View File

@ -125,6 +125,8 @@ namespace SHADE
std::vector<vk::ImageMemoryBarrier> const& imageMemoryBarriers
) const noexcept;
bool IsReadyToSubmit (void) const noexcept;
void HandlePostSubmit (void) noexcept;
// Push Constant variable setting
template <typename T>

View File

@ -150,20 +150,19 @@ namespace SHADE
logicalDeviceHdl->GetVkLogicalDevice().resetCommandPool(vkCommandPool, vk::CommandPoolResetFlagBits::eReleaseResources);
for (auto& primary : primaries)
{
if (primary->GetState() != SH_CMD_BUFFER_STATE::PENDING)
primary->SetState(SH_CMD_BUFFER_STATE::INITIAL);
else
SHLOG_ERROR("Primary command buffer in pending state, could not reset. ");
// #NoteToSelf: Since there is no way to set the state of a command buffer back to initial, we just hard set it to initial. Ditto for secondaries.
//if (primary->GetState() != SH_CMD_BUFFER_STATE::PENDING)
primary->SetState(SH_CMD_BUFFER_STATE::INITIAL);
// From the spec: Any primary command buffer allocated from another VkCommandPool that is in the recording or
// executable state and has a secondary command buffer allocated from commandPool recorded into it,
// becomes invalid. TODO: Might want to check and throw exception for these conditions after making sure this actually happens using validation layers.
}
for (auto& secondary : secondaries)
{
if (secondary->GetState() != SH_CMD_BUFFER_STATE::PENDING)
secondary->SetState(SH_CMD_BUFFER_STATE::INITIAL);
else
SHLOG_ERROR("Secondary command buffer in pending state, could not reset. ");
//if (secondary->GetState() != SH_CMD_BUFFER_STATE::PENDING)
secondary->SetState(SH_CMD_BUFFER_STATE::INITIAL);
// TODO: Ditto from TODO in primary check
}

View File

@ -54,7 +54,7 @@ namespace SHADE
});
// Create graphics queue
queue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0);
graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0);
// Create Render Context
@ -101,7 +101,7 @@ namespace SHADE
auto node = renderGraph.AddNode("G-Buffer", { "Position", "Normals", "Composite" }, {}); // no predecessors
// First subpass to write to G-Buffer
auto writeSubpass = node->AddSubpass("G-Buffer Write");
auto writeSubpass = node->AddSubpass("G-Buffer Write");
writeSubpass->AddColorOutput("Position");
writeSubpass->AddColorOutput("Normals");
@ -111,11 +111,11 @@ namespace SHADE
compositeSubpass->AddInput("Normals");
compositeSubpass->AddInput("Position");
auto compositeNode = renderGraph.AddNode("Bloom", { "Composite", "Downscale", "Present"}, {"G-Buffer"});
auto bloomSubpass = compositeNode->AddSubpass("Downsample");
bloomSubpass->AddInput("Composite");
bloomSubpass->AddColorOutput("Downscale");
bloomSubpass->AddColorOutput("Present");
//auto compositeNode = renderGraph.AddNode("Bloom", { "Composite", "Downscale", "Present"}, {"G-Buffer"});
//auto bloomSubpass = compositeNode->AddSubpass("Downsample");
//bloomSubpass->AddInput("Composite");
// bloomSubpass->AddColorOutput("Downscale");
// bloomSubpass->AddColorOutput("Present");
renderGraph.Generate();
@ -127,6 +127,14 @@ namespace SHADE
void SHGraphicsSystem::Run(float dt)
{
auto const& frameData = renderContext.GetCurrentFrameData();
renderGraph.Execute(renderContext.GetCurrentFrame());
graphicsQueue->SubmitCommandBuffer({ renderGraph.GetCommandBuffer(renderContext.GetCurrentFrame()) },
{ frameData.semRenderFinishHdl },
{ frameData.semImgAvailableHdl },
vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests);
}
@ -134,7 +142,7 @@ namespace SHADE
{
//renderPass.Free();
renderContext.Destroy();
queue.Free();
graphicsQueue.Free();
swapchain.Free();
surface.Free();
device.Free();
@ -208,7 +216,7 @@ namespace SHADE
presentInfo.pImageIndices = &CURR_FRAME_IDX;
// #BackEndTest: queues an image for presentation
if (auto result = device->GetQueue(SH_Q_FAM::GRAPHICS, 0)->GetVkQueue().presentKHR(&presentInfo); result != vk::Result::eSuccess)
if (auto result = graphicsQueue->Present(swapchain, {currFrameData.semRenderFinishHdl}, CURR_FRAME_IDX); result != vk::Result::eSuccess)
{
// If swapchain is incompatible/outdated
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)

View File

@ -114,7 +114,7 @@ namespace SHADE
Handle<SHVkSwapchain> GetSwapchain() const { return swapchain; }
Handle<SHVkSurface> GetSurface() const { return surface; }
Handle<SHVkPhysicalDevice> GetPhysicalDevice() const {return physicalDevice;}
Handle<SHVkQueue> GetQueue() const { return queue; }
Handle<SHVkQueue> GetQueue() const { return graphicsQueue; }
Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; }
SHRenderGraph const& GetRenderGraph (void) const noexcept;
@ -130,7 +130,7 @@ namespace SHADE
Handle<SHVkLogicalDevice> device;
Handle<SHVkSurface> surface;
Handle<SHVkSwapchain> swapchain;
Handle<SHVkQueue> queue;
Handle<SHVkQueue> graphicsQueue;
Handle<SHVkDescriptorPool> descPool;
//Handle<SHVkRenderpass> renderPass; // Potentially bring out?
std::vector<SHScreenSegment> screenSegments;

View File

@ -5,6 +5,7 @@
#include "Graphics/Synchronization/SHVkSemaphore.h"
#include "Graphics/Synchronization/SHVkFence.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
namespace SHADE
@ -31,14 +32,10 @@ namespace SHADE
}
vk::Queue SHVkQueue::GetVkQueue(void) const noexcept
void SHVkQueue::SubmitCommandBuffer(std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems /*= {}*/, std::initializer_list<Handle<SHVkSemaphore>> waitSems /*= {}*/, vk::PipelineStageFlags waitDstStageMask /*= {}*/, Handle<SHVkFence> const& optionalFence /*= {}*/) noexcept
{
return vkQueue;
}
void SHVkQueue::SubmitCommandBuffer(std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems /*= {}*/, std::initializer_list<Handle<SHVkSemaphore>> waitSems /*= {}*/, vk::PipelineStageFlagBits waitDstStageMask /*= {}*/, Handle<SHVkFence> const& optionalFence /*= {}*/) noexcept
{
std::vector<vk::Semaphore> vkWaitSems{ waitSems.size() };
// prepare wait sems
std::array<vk::Semaphore, 5> vkWaitSems{ };
uint32_t i = 0;
for (auto& sem : waitSems)
{
@ -46,7 +43,8 @@ namespace SHADE
++i;
}
std::vector<vk::Semaphore> vkSignalSems{ signalSems.size() };
// prepare signal sems
std::array<vk::Semaphore, 5> vkSignalSems{ };
i = 0;
for (auto& sem : signalSems)
{
@ -54,33 +52,76 @@ namespace SHADE
++i;
}
std::vector<vk::CommandBuffer> vkCmdBuffers{ cmdBuffers.size() };
// prepare cmd buffers
std::array<vk::CommandBuffer, 5> vkCmdBuffers{ };
i = 0;
for (auto& cmdBuffer : cmdBuffers)
{
// Check if command buffer is in executable state
if (!cmdBuffer->IsReadyToSubmit())
{
SHLOG_ERROR("Command buffer is not in executable state. Cannot submit command buffer. ");
return;
}
vkCmdBuffers[i] = cmdBuffer->GetVkCommandBuffer();
++i;
}
vk::PipelineStageFlags mask = waitDstStageMask;
// Prepare submit info
vk::SubmitInfo submitInfo
{
.waitSemaphoreCount = static_cast<uint32_t>(vkWaitSems.size()),
.waitSemaphoreCount = static_cast<uint32_t>(waitSems.size()),
.pWaitSemaphores = vkWaitSems.data(),
.pWaitDstStageMask = &mask,
.commandBufferCount = static_cast<uint32_t>(vkCmdBuffers.size()),
.pWaitDstStageMask = &waitDstStageMask,
.commandBufferCount = static_cast<uint32_t>(cmdBuffers.size()),
.pCommandBuffers = vkCmdBuffers.data(),
.signalSemaphoreCount = static_cast<uint32_t>(vkSignalSems.size()),
.signalSemaphoreCount = static_cast<uint32_t>(signalSems.size()),
.pSignalSemaphores = vkSignalSems.data(),
};
// #BackEndTest: Submit the queue
// Submit the queue
if (auto result = vkQueue.submit(1, &submitInfo, (optionalFence) ? optionalFence->GetVkFence() : nullptr); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to submit command buffer. ");
}
else // if success
{
// Change all command buffers to pending state
for (Handle<SHVkCommandBuffer> cmdBuffer : cmdBuffers)
{
cmdBuffer->HandlePostSubmit();
}
}
}
vk::Result SHVkQueue::Present(Handle<SHVkSwapchain> const& swapchain, std::initializer_list<Handle<SHVkSemaphore>> waitSems, uint32_t frameIndex) noexcept
{
vk::PresentInfoKHR presentInfo{};
// prepare wait sems
std::array<vk::Semaphore, 5> vkWaitSems{ };
uint32_t i = 0;
for (auto& sem : waitSems)
{
vkWaitSems[i] = sem->GetVkSem();
++i;
}
// prepare presentation information
presentInfo.waitSemaphoreCount = static_cast<uint32_t>(waitSems.size());
presentInfo.pWaitSemaphores = vkWaitSems.data();
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &swapchain->GetVkSwapchain();
presentInfo.pImageIndices = &frameIndex;
// Present swapchain image.
auto result = vkQueue.presentKHR(&presentInfo);
if (result != vk::Result::eSuccess)
{
SHLOGV_ERROR ("Failed to present swapchain image. ");
}
return result;
}
}

View File

@ -11,6 +11,7 @@ namespace SHADE
class SHVkCommandBuffer;
class SHVkFence;
class SHVkSemaphore;
class SHVkSwapchain;
enum class SH_QUEUE_FAMILY_ARRAY_INDEX : std::size_t
{
@ -45,9 +46,9 @@ namespace SHADE
public:
SHVkQueue(vk::Queue inVkQueue, SHQueueFamilyIndex parent, Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl) noexcept;
vk::Queue GetVkQueue(void) const noexcept;
void SubmitCommandBuffer(std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems = {}, std::initializer_list<Handle<SHVkSemaphore>> waitSems = {}, vk::PipelineStageFlagBits waitDstStageMask = {}, Handle<SHVkFence> const& fence = {}) noexcept;
void SubmitCommandBuffer (std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems = {}, std::initializer_list<Handle<SHVkSemaphore>> waitSems = {}, vk::PipelineStageFlags waitDstStageMask = {}, Handle<SHVkFence> const& fence = {}) noexcept;
vk::Result Present (Handle<SHVkSwapchain> const& swapchain, std::initializer_list<Handle<SHVkSemaphore>> waitSems, uint32_t frameIndex) noexcept;
};
}

View File

@ -552,14 +552,16 @@ namespace SHADE
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
{
frameIndex = (framebuffers.size() > 1) ? frameIndex : 0;
commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]);
for (auto& subpass : subpasses)
for (uint32_t i = 0; i < subpasses.size(); ++i)
{
subpass->Execute(commandBuffer);
subpasses[i]->Execute(commandBuffer);
// Go to next subpass
commandBuffer->NextSubpass();
// Go to next subpass if not last subpass
if (i != subpasses.size() - 1)
commandBuffer->NextSubpass();
}
commandBuffer->EndRenderpass();
@ -892,6 +894,10 @@ namespace SHADE
{
commandPool = logicalDeviceHdl->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
commandBuffers.resize(static_cast<std::size_t>(swapchainHdl->GetNumImages()));
for (auto& cmdBuffer : commandBuffers)
{
cmdBuffer = commandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
}
}
/***************************************************************************/
@ -1019,6 +1025,8 @@ namespace SHADE
void SHRenderGraph::Execute(uint32_t frameIndex) noexcept
{
commandPool->Reset();
auto& cmdBuffer = commandBuffers[frameIndex];
cmdBuffer->BeginRecording();
@ -1027,7 +1035,7 @@ namespace SHADE
node->Execute(commandBuffers[frameIndex], frameIndex);
}
cmdBuffer->EndRenderpass();
cmdBuffer->EndRecording();
}
Handle<SHRenderGraphNode> SHRenderGraph::GetNode(std::string const& nodeName) const noexcept
@ -1038,4 +1046,9 @@ namespace SHADE
return {};
}
Handle<SHVkCommandBuffer> const& SHRenderGraph::GetCommandBuffer(uint32_t frameIndex) const noexcept
{
return commandBuffers[frameIndex];
}
}

View File

@ -275,7 +275,8 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept;
Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept;
Handle<SHVkCommandBuffer> const& GetCommandBuffer (uint32_t frameIndex) const noexcept;
};
}