Removing resources now remove subpasses and computes involved
- Added an empty node in the render graph for shadow mapping
This commit is contained in:
parent
d7754e125d
commit
03becd8e47
|
@ -259,9 +259,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
// Shadow map pass will have no resources bound at first. Lighting system will add resources to the node.
|
// Shadow map pass will have no resources bound at first. Lighting system will add resources to the node.
|
||||||
// It will initially also not have any subpasses since they will be added for each light that casts shadows.
|
// It will initially also not have any subpasses since they will be added for each light that casts shadows.
|
||||||
//auto shadowMapPass = renderGraph->AddNode("Shadow Map Pass", {}, {});
|
auto shadowMapPass = renderGraph->AddNode("Shadow Map Pass", {}, {});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* DEFERRED COMPOSITE NODE */
|
/* DEFERRED COMPOSITE NODE */
|
||||||
|
@ -450,6 +448,7 @@ namespace SHADE
|
||||||
InitMiddleEnd();
|
InitMiddleEnd();
|
||||||
InitSubsystems();
|
InitSubsystems();
|
||||||
InitBuiltInResources();
|
InitBuiltInResources();
|
||||||
|
InitEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsSystem::Exit(void)
|
void SHGraphicsSystem::Exit(void)
|
||||||
|
|
|
@ -106,6 +106,9 @@ namespace SHADE
|
||||||
|
|
||||||
for (auto& affectedNode : affectedNodes)
|
for (auto& affectedNode : affectedNodes)
|
||||||
nodes[affectedNode]->CreateFramebuffer();
|
nodes[affectedNode]->CreateFramebuffer();
|
||||||
|
|
||||||
|
renderGraphStorage->graphResources->at(resourceName).Free();
|
||||||
|
renderGraphStorage->graphResources->erase (resourceName);
|
||||||
/*
|
/*
|
||||||
* IMPORTANT NOTES
|
* IMPORTANT NOTES
|
||||||
*
|
*
|
||||||
|
@ -168,65 +171,62 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
// key is handle ID, value is final layout.
|
// key is handle ID, value is final layout.
|
||||||
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
|
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
|
||||||
if (node->subpasses.empty())
|
if (!node->subpasses.empty())
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
|
// We first want to take all resources track their layout as undefined at the start of the node/renderpass
|
||||||
return;
|
auto const resources = node->GetResources();
|
||||||
}
|
for (auto& resource : resources)
|
||||||
|
|
||||||
// We first want to take all resources track their layout as undefined at the start of the node/renderpass
|
|
||||||
auto const resources = node->GetResources();
|
|
||||||
for (auto& resource : resources)
|
|
||||||
{
|
|
||||||
resource->GetInfoTracker()->TrackLayout(node, {}, vk::ImageLayout::eUndefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
// attempt to get all final layouts for all resources
|
|
||||||
for (auto& subpass : node->subpasses)
|
|
||||||
{
|
|
||||||
for (auto& color : subpass->colorReferences)
|
|
||||||
{
|
{
|
||||||
// If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass
|
resource->GetInfoTracker()->TrackLayout(node, {}, vk::ImageLayout::eUndefined);
|
||||||
if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)))
|
|
||||||
resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
|
|
||||||
else
|
|
||||||
resourceAttFinalLayouts[color.attachment] = color.layout;
|
|
||||||
|
|
||||||
node->attResources[color.attachment]->infoTracker->TrackLayout(node, subpass, color.layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& depth : subpass->depthReferences)
|
// attempt to get all final layouts for all resources
|
||||||
|
for (auto& subpass : node->subpasses)
|
||||||
{
|
{
|
||||||
resourceAttFinalLayouts[depth.attachment] = depth.layout;
|
for (auto& color : subpass->colorReferences)
|
||||||
node->attResources[depth.attachment]->infoTracker->TrackLayout(node, subpass, depth.layout);
|
{
|
||||||
|
// If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass
|
||||||
|
if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)))
|
||||||
|
resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
|
||||||
|
else
|
||||||
|
resourceAttFinalLayouts[color.attachment] = color.layout;
|
||||||
|
|
||||||
|
node->attResources[color.attachment]->infoTracker->TrackLayout(node, subpass, color.layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& depth : subpass->depthReferences)
|
||||||
|
{
|
||||||
|
resourceAttFinalLayouts[depth.attachment] = depth.layout;
|
||||||
|
node->attResources[depth.attachment]->infoTracker->TrackLayout(node, subpass, depth.layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& input : subpass->inputReferences)
|
||||||
|
{
|
||||||
|
resourceAttFinalLayouts[input.attachment] = input.layout;
|
||||||
|
node->attResources[input.attachment]->infoTracker->TrackLayout(node, subpass, input.layout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& input : subpass->inputReferences)
|
for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
|
||||||
{
|
{
|
||||||
resourceAttFinalLayouts[input.attachment] = input.layout;
|
auto& att = node->attachmentDescriptions[j];
|
||||||
node->attResources[input.attachment]->infoTracker->TrackLayout(node, subpass, input.layout);
|
auto& resource = node->attResources[j];
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
|
// If resource is from another render graph, use the final layout it had when it was last used in that graph. This is initialized in LinkNonOwningResource.
|
||||||
{
|
// We also want to load the attachment, not "don't care".
|
||||||
auto& att = node->attachmentDescriptions[j];
|
if (resource->resourceTypeFlags & SHUtilities::ConvertEnum(SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED) &&
|
||||||
auto& resource = node->attResources[j];
|
|
||||||
|
|
||||||
// If resource is from another render graph, use the final layout it had when it was last used in that graph. This is initialized in LinkNonOwningResource.
|
|
||||||
// We also want to load the attachment, not "don't care".
|
|
||||||
if (resource->resourceTypeFlags & SHUtilities::ConvertEnum(SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED) &&
|
|
||||||
renderGraphStorage->nonOwningResourceInitialLayouts.contains(resource.GetId().Raw))
|
renderGraphStorage->nonOwningResourceInitialLayouts.contains(resource.GetId().Raw))
|
||||||
{
|
{
|
||||||
att.initialLayout = renderGraphStorage->nonOwningResourceInitialLayouts.at (resource.GetId().Raw);
|
att.initialLayout = renderGraphStorage->nonOwningResourceInitialLayouts.at(resource.GetId().Raw);
|
||||||
att.loadOp = vk::AttachmentLoadOp::eLoad;
|
att.loadOp = vk::AttachmentLoadOp::eLoad;
|
||||||
att.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
|
att.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
att.initialLayout = vk::ImageLayout::eUndefined;
|
att.initialLayout = vk::ImageLayout::eUndefined;
|
||||||
|
|
||||||
att.finalLayout = resourceAttFinalLayouts[j];
|
att.finalLayout = resourceAttFinalLayouts[j];
|
||||||
resource->GetInfoTracker()->TrackLayout(node, {}, att.finalLayout);
|
resource->GetInfoTracker()->TrackLayout(node, {}, att.finalLayout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -532,10 +532,6 @@ namespace SHADE
|
||||||
ConfigureSubSystems();
|
ConfigureSubSystems();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRenderGraph::Regenerate(void) noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
@ -572,10 +568,13 @@ namespace SHADE
|
||||||
|
|
||||||
for (auto& node : nodes)
|
for (auto& node : nodes)
|
||||||
{
|
{
|
||||||
// bind static global data
|
if (node->renderpass)
|
||||||
SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
{
|
||||||
|
// bind static global data
|
||||||
|
SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
||||||
|
|
||||||
node->Execute(cmdBuffer, descPool, frameIndex);
|
node->Execute(cmdBuffer, descPool, frameIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdBuffer->EndLabeledSegment();
|
cmdBuffer->EndLabeledSegment();
|
||||||
|
|
|
@ -134,7 +134,6 @@ namespace SHADE
|
||||||
) noexcept;
|
) noexcept;
|
||||||
|
|
||||||
void Generate (void) noexcept;
|
void Generate (void) noexcept;
|
||||||
void Regenerate (void) noexcept;
|
|
||||||
void CheckForNodeComputes (void) noexcept;
|
void CheckForNodeComputes (void) noexcept;
|
||||||
void Execute (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
|
void Execute (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||||
void Begin (uint32_t frameIndex) noexcept;
|
void Begin (uint32_t frameIndex) noexcept;
|
||||||
|
|
|
@ -32,8 +32,11 @@ namespace SHADE
|
||||||
renderpass.Free();
|
renderpass.Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
if (!spDescs.empty())
|
||||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eRenderPass, renderpass->GetVkRenderpass(), "[RenderPass] " + name);
|
{
|
||||||
|
renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
||||||
|
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eRenderPass, renderpass->GetVkRenderpass(), "[RenderPass] " + name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -46,77 +49,86 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHRenderGraphNode::CreateFramebuffer(void) noexcept
|
void SHRenderGraphNode::CreateFramebuffer(void) noexcept
|
||||||
{
|
{
|
||||||
if (!framebuffers.empty())
|
if (renderpass)
|
||||||
{
|
{
|
||||||
for (auto fbo : framebuffers)
|
if (!framebuffers.empty())
|
||||||
{
|
{
|
||||||
if (fbo)
|
for (auto fbo : framebuffers)
|
||||||
fbo.Free();
|
{
|
||||||
}
|
if (fbo)
|
||||||
}
|
fbo.Free();
|
||||||
|
}
|
||||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
|
||||||
{
|
|
||||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
|
||||||
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
|
||||||
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
|
||||||
|
|
||||||
for (uint32_t j = 0; j < attResources.size(); ++j)
|
|
||||||
{
|
|
||||||
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
|
||||||
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
|
||||||
|
|
||||||
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
|
||||||
if (fbWidth > attResources[j]->width)
|
|
||||||
fbWidth = attResources[j]->width;
|
|
||||||
if (fbHeight > attResources[j]->height)
|
|
||||||
fbHeight = attResources[j]->height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||||
|
{
|
||||||
|
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||||
|
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
||||||
|
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
||||||
|
|
||||||
framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
|
for (uint32_t j = 0; j < attResources.size(); ++j)
|
||||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eFramebuffer, framebuffers[i]->GetVkFramebuffer(), "[Framebuffer] " + name + std::to_string(i));
|
{
|
||||||
|
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
||||||
|
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
||||||
|
|
||||||
|
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
||||||
|
if (fbWidth > attResources[j]->width)
|
||||||
|
fbWidth = attResources[j]->width;
|
||||||
|
if (fbHeight > attResources[j]->height)
|
||||||
|
fbHeight = attResources[j]->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
|
||||||
|
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eFramebuffer, framebuffers[i]->GetVkFramebuffer(), "[Framebuffer] " + name + std::to_string(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRenderGraphNode::HandleResize(void) noexcept
|
void SHRenderGraphNode::HandleResize(void) noexcept
|
||||||
{
|
{
|
||||||
renderpass->HandleResize();
|
if (renderpass)
|
||||||
|
|
||||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
|
||||||
{
|
{
|
||||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
renderpass->HandleResize();
|
||||||
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
|
||||||
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
|
||||||
|
|
||||||
for (uint32_t j = 0; j < attResources.size(); ++j)
|
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||||
{
|
{
|
||||||
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||||
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
||||||
|
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
||||||
|
|
||||||
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
for (uint32_t j = 0; j < attResources.size(); ++j)
|
||||||
if (fbWidth > attResources[j]->width)
|
{
|
||||||
fbWidth = attResources[j]->width;
|
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
||||||
if (fbHeight > attResources[j]->height)
|
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
||||||
fbHeight = attResources[j]->height;
|
|
||||||
|
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
||||||
|
if (fbWidth > attResources[j]->width)
|
||||||
|
fbWidth = attResources[j]->width;
|
||||||
|
if (fbHeight > attResources[j]->height)
|
||||||
|
fbHeight = attResources[j]->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
|
for (auto& subpass : subpasses)
|
||||||
}
|
{
|
||||||
|
subpass->HandleResize();
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& subpass : subpasses)
|
for (auto& nodeCompute : nodeComputes)
|
||||||
{
|
{
|
||||||
subpass->HandleResize();
|
nodeCompute->HandleResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& nodeCompute : nodeComputes)
|
|
||||||
{
|
|
||||||
nodeCompute->HandleResize();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRenderGraphNode::ConfigureSubpasses(void) noexcept
|
void SHRenderGraphNode::ConfigureSubpasses(void) noexcept
|
||||||
{
|
{
|
||||||
|
if (subpasses.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
// Create subpass description and dependencies based on number of subpasses
|
// Create subpass description and dependencies based on number of subpasses
|
||||||
spDescs.resize(subpasses.size());
|
spDescs.resize(subpasses.size());
|
||||||
spDeps.resize(subpasses.size());
|
spDeps.resize(subpasses.size());
|
||||||
|
@ -512,11 +524,8 @@ namespace SHADE
|
||||||
// Remove footprint of attachment from all subpasses as well
|
// Remove footprint of attachment from all subpasses as well
|
||||||
for (auto it = subpasses.begin(); it != subpasses.end(); ++it)
|
for (auto it = subpasses.begin(); it != subpasses.end(); ++it)
|
||||||
{
|
{
|
||||||
// attempt to detach resource from subpass
|
// If the subpass uses the resource, just remove the subpass since the subpass will be invalid
|
||||||
(*it)->DetachResource(resourceName, index);
|
if ((*it)->UsesResource(index))
|
||||||
|
|
||||||
// If the subpass ends up having no attachments after, erase it from the node
|
|
||||||
if ((*it)->HasNoAttachments())
|
|
||||||
{
|
{
|
||||||
// erase from indexing
|
// erase from indexing
|
||||||
subpassIndexing.erase((*it)->GetName());
|
subpassIndexing.erase((*it)->GetName());
|
||||||
|
@ -530,6 +539,24 @@ namespace SHADE
|
||||||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||||
subpasses[i]->SetIndex(i);
|
subpasses[i]->SetIndex(i);
|
||||||
|
|
||||||
|
// remove node computes using the resource
|
||||||
|
for (auto it = nodeComputes.begin(); it != nodeComputes.end(); ++it)
|
||||||
|
{
|
||||||
|
if ((*it)->UsesResource(resourceHandleID))
|
||||||
|
{
|
||||||
|
it = nodeComputes.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// recompute the barriers for the other computes
|
||||||
|
for (auto it = nodeComputes.begin(); it != nodeComputes.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it == nodeComputes.begin())
|
||||||
|
(*it)->SetFollowingEndRenderpass(true);
|
||||||
|
|
||||||
|
(*it)->InitializeBarriers();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -537,37 +564,40 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||||
{
|
{
|
||||||
uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
if (renderpass)
|
||||||
commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
|
||||||
{
|
{
|
||||||
subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
|
uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
||||||
|
commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
|
||||||
|
|
||||||
// Go to next subpass if not last subpass
|
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||||
if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
|
{
|
||||||
commandBuffer->NextSubpass();
|
subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
|
||||||
|
|
||||||
|
// Go to next subpass if not last subpass
|
||||||
|
if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
|
||||||
|
commandBuffer->NextSubpass();
|
||||||
|
}
|
||||||
|
|
||||||
|
commandBuffer->EndRenderpass();
|
||||||
|
|
||||||
|
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::RENDER_GRAPH_NODE_COMPUTE);
|
||||||
|
|
||||||
|
// We bind these 2 descriptor sets here because they apply to all node computes
|
||||||
|
if (!nodeComputes.empty())
|
||||||
|
{
|
||||||
|
commandBuffer->ForceSetPipelineLayout(SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::RENDER_GRAPH_NODE_COMPUTE).dummyPipelineLayout, SH_PIPELINE_TYPE::COMPUTE);
|
||||||
|
|
||||||
|
// bind static global data
|
||||||
|
SHGlobalDescriptorSets::BindStaticGlobalData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
||||||
|
|
||||||
|
// bind lighting data
|
||||||
|
SHGlobalDescriptorSets::BindLightingData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::LIGHTS), frameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute all subpass computes
|
||||||
|
for (auto& sbCompute : nodeComputes)
|
||||||
|
sbCompute->Execute(commandBuffer, frameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
commandBuffer->EndRenderpass();
|
|
||||||
|
|
||||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::RENDER_GRAPH_NODE_COMPUTE);
|
|
||||||
|
|
||||||
// We bind these 2 descriptor sets here because they apply to all node computes
|
|
||||||
if (!nodeComputes.empty())
|
|
||||||
{
|
|
||||||
commandBuffer->ForceSetPipelineLayout(SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::RENDER_GRAPH_NODE_COMPUTE).dummyPipelineLayout, SH_PIPELINE_TYPE::COMPUTE);
|
|
||||||
|
|
||||||
// bind static global data
|
|
||||||
SHGlobalDescriptorSets::BindStaticGlobalData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
|
||||||
|
|
||||||
// bind lighting data
|
|
||||||
SHGlobalDescriptorSets::BindLightingData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::LIGHTS), frameIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute all subpass computes
|
|
||||||
for (auto& sbCompute : nodeComputes)
|
|
||||||
sbCompute->Execute(commandBuffer, frameIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
|
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
|
||||||
|
|
|
@ -14,6 +14,54 @@
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
|
||||||
|
bool SHRenderGraphNodeCompute::UsesResource(uint64_t resourceHandleID) const noexcept
|
||||||
|
{
|
||||||
|
for (auto& resource : resources)
|
||||||
|
{
|
||||||
|
if (resource.GetId().Raw == resourceHandleID)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHRenderGraphNodeCompute::InitializeBarriers(void) noexcept
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; auto & barriers : memoryBarriers)
|
||||||
|
{
|
||||||
|
barriers.clear();
|
||||||
|
|
||||||
|
for (auto& resource : resources)
|
||||||
|
{
|
||||||
|
vk::AccessFlags srcAccessMask = (followingEndRenderpass) ? vk::AccessFlagBits::eInputAttachmentRead : (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite);
|
||||||
|
barriers.push_back(vk::ImageMemoryBarrier
|
||||||
|
{
|
||||||
|
.srcAccessMask = srcAccessMask,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
|
||||||
|
.oldLayout = vk::ImageLayout::eGeneral,
|
||||||
|
.newLayout = vk::ImageLayout::eGeneral,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = resource->GetImage((resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(),
|
||||||
|
.subresourceRange = vk::ImageSubresourceRange
|
||||||
|
{
|
||||||
|
.aspectMask = resource->imageAspectFlags,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = resource->mipLevels,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHRenderGraphNodeCompute::SetFollowingEndRenderpass(uint32_t flag) noexcept
|
||||||
|
{
|
||||||
|
followingEndRenderpass = flag;
|
||||||
|
}
|
||||||
|
|
||||||
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept
|
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept
|
||||||
: computePipeline{}
|
: computePipeline{}
|
||||||
, pipelineLayout{}
|
, pipelineLayout{}
|
||||||
|
@ -157,35 +205,7 @@ namespace SHADE
|
||||||
groupSizeX = maxWidth / workGroupSizeX;
|
groupSizeX = maxWidth / workGroupSizeX;
|
||||||
groupSizeY = maxHeight / workGroupSizeY;
|
groupSizeY = maxHeight / workGroupSizeY;
|
||||||
|
|
||||||
for (uint32_t i = 0; auto& barriers : memoryBarriers)
|
InitializeBarriers();
|
||||||
{
|
|
||||||
barriers.clear();
|
|
||||||
|
|
||||||
for (auto& resource : resources)
|
|
||||||
{
|
|
||||||
vk::AccessFlags srcAccessMask = (followingEndRenderpass) ? vk::AccessFlagBits::eInputAttachmentRead : (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite);
|
|
||||||
barriers.push_back(vk::ImageMemoryBarrier
|
|
||||||
{
|
|
||||||
.srcAccessMask = srcAccessMask,
|
|
||||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
|
|
||||||
.oldLayout = vk::ImageLayout::eGeneral,
|
|
||||||
.newLayout = vk::ImageLayout::eGeneral,
|
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.image = resource->GetImage((resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(),
|
|
||||||
.subresourceRange = vk::ImageSubresourceRange
|
|
||||||
{
|
|
||||||
.aspectMask = resource->imageAspectFlags,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = resource->mipLevels,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = 1,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRenderGraphNodeCompute::SetDynamicOffsets(std::span<uint32_t> perFrameSizes) noexcept
|
void SHRenderGraphNodeCompute::SetDynamicOffsets(std::span<uint32_t> perFrameSizes) noexcept
|
||||||
|
|
|
@ -73,6 +73,18 @@ namespace SHADE
|
||||||
//! Name of this node
|
//! Name of this node
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
bool UsesResource (uint64_t resourceHandleID) const noexcept;
|
||||||
|
void InitializeBarriers (void) noexcept;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE SETTERS AND GETTERS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void SetFollowingEndRenderpass (uint32_t flag) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept;
|
SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept;
|
||||||
|
|
||||||
|
|
|
@ -265,42 +265,24 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHSubpass::DetachResource(std::string const& resourceName, uint32_t attachmentIndex) noexcept
|
bool SHSubpass::UsesResource(uint32_t attachmentIndex) noexcept
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < colorReferences.size(); ++i)
|
for (uint32_t i = 0; i < colorReferences.size(); ++i)
|
||||||
{
|
{
|
||||||
if (colorReferences[i].attachment == attachmentIndex)
|
if (colorReferences[i].attachment == attachmentIndex)
|
||||||
{
|
return true;
|
||||||
colorReferences.erase (colorReferences.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < depthReferences.size(); ++i)
|
for (uint32_t i = 0; i < depthReferences.size(); ++i)
|
||||||
{
|
{
|
||||||
if (depthReferences[i].attachment == attachmentIndex)
|
if (depthReferences[i].attachment == attachmentIndex)
|
||||||
{
|
return true;
|
||||||
depthReferences.erase(depthReferences.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < inputReferences.size(); ++i)
|
for (uint32_t i = 0; i < inputReferences.size(); ++i)
|
||||||
{
|
{
|
||||||
if (inputReferences[i].attachment == attachmentIndex)
|
if (inputReferences[i].attachment == attachmentIndex)
|
||||||
{
|
return true;
|
||||||
inputReferences.erase(inputReferences.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < inputNames.size(); ++i)
|
|
||||||
{
|
|
||||||
if (inputNames[i] == resourceName)
|
|
||||||
{
|
|
||||||
inputNames.erase(inputNames.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,12 @@ namespace SHADE
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
bool UsesResource(uint32_t attachmentIndex) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* CTORS AND DTORS */
|
/* CTORS AND DTORS */
|
||||||
|
@ -119,7 +125,6 @@ namespace SHADE
|
||||||
void Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
void Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||||
void HandleResize (void) noexcept;
|
void HandleResize (void) noexcept;
|
||||||
void BindInputDescriptorSets (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) const noexcept;
|
void BindInputDescriptorSets (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) const noexcept;
|
||||||
void DetachResource (std::string const& resourceName, uint32_t attachmentIndex) noexcept;
|
|
||||||
bool HasNoAttachments (void) const noexcept;
|
bool HasNoAttachments (void) const noexcept;
|
||||||
|
|
||||||
void Init(SHResourceHub& resourceManager) noexcept;
|
void Init(SHResourceHub& resourceManager) noexcept;
|
||||||
|
|
Loading…
Reference in New Issue