Render graph execution fixed
GetVkQueue function deleted. More specific function implemented (Present).
This commit is contained in:
parent
44e529f06f
commit
169822c221
|
@ -48,6 +48,7 @@ namespace Sandbox
|
|||
//SHADE::SHEditor::PreRender();
|
||||
//#endif
|
||||
graphicsSystem->BeginRender();
|
||||
graphicsSystem->Run(1.0f);
|
||||
//#ifdef SHEDITOR
|
||||
//SHADE::SHEditor::PreRender();
|
||||
//SHADE::SHEditor::Update();
|
||||
|
|
|
@ -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{};
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue