From last commit. Whoops.

This commit is contained in:
Brandon Mak 2022-11-11 00:02:18 +08:00
parent c78aade245
commit d17a83ab77
11 changed files with 200 additions and 54 deletions

View File

@ -3,7 +3,7 @@
namespace SHADE namespace SHADE
{ {
// Used for attachment description creation for renderpass node // Used for attachment description creation for renderpass node
enum class SH_ATT_DESC_TYPE_FLAGS enum class SH_RENDER_GRAPH_RESOURCE_FLAGS
{ {
COLOR = 0x01, COLOR = 0x01,
COLOR_PRESENT = 0x02, COLOR_PRESENT = 0x02,
@ -11,7 +11,8 @@ namespace SHADE
STENCIL = 0x08, STENCIL = 0x08,
DEPTH_STENCIL = 0x10, DEPTH_STENCIL = 0x10,
INPUT = 0x20, INPUT = 0x20,
STORAGE = 0x40 STORAGE = 0x40,
SHARED = 0x80 // if resource is meant to be used across render graphs, mark this flag
}; };
} }

View File

@ -11,6 +11,7 @@
#include "SHAttachmentDescInitParams.h" #include "SHAttachmentDescInitParams.h"
#include "SHRenderGraphStorage.h" #include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h" #include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "Tools/SHUtilities.h"
namespace SHADE namespace SHADE
{ {
@ -49,7 +50,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/) void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/)
{ {
// If we set to // If we set to
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1)) if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
@ -59,7 +60,32 @@ namespace SHADE
format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format; format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
} }
renderGraphStorage->graphResources->try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags)); renderGraphStorage->graphResources->try_emplace(resourceName, renderGraphStorage->resourceHub->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags));
}
void SHRenderGraph::LinkNonOwningResource(Handle<SHRenderGraph> resourceOrigin, std::string resourceName) noexcept
{
// resource to link
Handle<SHRenderGraphResource> resourceToLink = resourceOrigin->GetRenderGraphResource(resourceName);
if (!resourceToLink)
{
SHLOG_ERROR("Resource does not exist in render graph, cannot link resource.");
return;
}
// Get the final layout of the resource from the previous render graph
vk::ImageLayout finalLayout{vk::ImageLayout::eUndefined};
auto const& nodes = resourceOrigin->GetNodes();
for (auto& node : nodes)
{
if (vk::ImageLayout layout = resourceToLink->GetInfoTracker()->GetLayout(node, {}); layout != vk::ImageLayout::eUndefined)
finalLayout = layout;
}
renderGraphStorage->graphResources->try_emplace(resourceName, resourceToLink);
// add to this pool so that when we generate later, the attachment descriptions will make its initial layout the layout stored here
renderGraphStorage->nonOwningResourceInitialLayouts.emplace(resourceToLink.GetId().Raw, finalLayout);
} }
/***************************************************************************/ /***************************************************************************/
@ -87,30 +113,59 @@ namespace SHADE
return; return;
} }
// 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 // attempt to get all final layouts for all resources
for (auto& subpass : node->subpasses) for (auto& subpass : node->subpasses)
{ {
for (auto& color : subpass->colorReferences) for (auto& color : subpass->colorReferences)
{ {
// If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass // 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_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))) 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; resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
else else
resourceAttFinalLayouts[color.attachment] = color.layout; resourceAttFinalLayouts[color.attachment] = color.layout;
node->attResources[color.attachment]->infoTracker->TrackLayout(node, subpass, color.layout);
} }
for (auto& depth : subpass->depthReferences) for (auto& depth : subpass->depthReferences)
{
resourceAttFinalLayouts[depth.attachment] = depth.layout; resourceAttFinalLayouts[depth.attachment] = depth.layout;
node->attResources[depth.attachment]->infoTracker->TrackLayout(node, subpass, depth.layout);
}
for (auto& input : subpass->inputReferences) for (auto& input : subpass->inputReferences)
{
resourceAttFinalLayouts[input.attachment] = input.layout; resourceAttFinalLayouts[input.attachment] = input.layout;
node->attResources[input.attachment]->infoTracker->TrackLayout(node, subpass, input.layout);
}
} }
for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j) for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
{ {
auto& att = node->attachmentDescriptions[j]; auto& att = node->attachmentDescriptions[j];
att.initialLayout = vk::ImageLayout::eUndefined; 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::ToUnderlying(SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED) &&
renderGraphStorage->nonOwningResourceInitialLayouts.contains(resource.GetId().Raw))
{
att.initialLayout = renderGraphStorage->nonOwningResourceInitialLayouts.at (resource.GetId().Raw);
att.loadOp = vk::AttachmentLoadOp::eLoad;
att.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
}
else
att.initialLayout = vk::ImageLayout::eUndefined;
att.finalLayout = resourceAttFinalLayouts[j]; att.finalLayout = resourceAttFinalLayouts[j];
resource->GetInfoTracker()->TrackLayout(node, {}, att.finalLayout);
} }
++i; ++i;
} }
@ -145,12 +200,13 @@ namespace SHADE
attDesc.stencilLoadOp = vk::AttachmentLoadOp::eLoad; attDesc.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
attDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore; attDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore;
// TODO: Stencil load and store
// When an image is done being used in a renderpass, the image layout will end up being the finalLayout // When an image is done being used in a renderpass, the image layout will end up being the finalLayout
// value of the attachment description. We want this to carry over to the next renderpass; specifically // value of the attachment description. We want this to carry over to the next renderpass; specifically
// to have the initialLayout of the attachment description in the next renderpass match the finalLayout in the previous. // to have the initialLayout of the attachment description in the next renderpass match the finalLayout in the previous.
attDesc.initialLayout = predAttDesc.finalLayout; attDesc.initialLayout = predAttDesc.finalLayout;
// We also want to track it
predResource->GetInfoTracker()->TrackLayout(node, {}, attDesc.initialLayout);
} }
} }
} }
@ -224,12 +280,12 @@ namespace SHADE
for (auto& inputAtt : subpass->inputReferences) for (auto& inputAtt : subpass->inputReferences)
{ {
auto resource = node->attResources[inputAtt.attachment]; auto resource = node->attResources[inputAtt.attachment];
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::INPUT)) if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT))
{ {
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR) || if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR) ||
resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT))
colorRead |= (1 << i); colorRead |= (1 << i);
else if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL)) else if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL))
depthRead |= (1 << i); depthRead |= (1 << i);
} }
else else
@ -353,17 +409,17 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain, SHResourceHub* resourceHub) noexcept
{ {
resourceManager = std::make_shared<SHResourceHub>(); //resourceHub = std::make_shared<SHResourceHub>();
renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>(); renderGraphStorage = resourceHub->Create<SHRenderGraphStorage>();
renderGraphStorage->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>(); renderGraphStorage->graphResources = resourceHub->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
renderGraphStorage->logicalDevice = logicalDevice; renderGraphStorage->logicalDevice = logicalDevice;
renderGraphStorage->swapchain = swapchain; renderGraphStorage->swapchain = swapchain;
renderGraphStorage->resourceManager = resourceManager; renderGraphStorage->resourceHub = resourceHub;
renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools(); renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools();
} }
@ -381,7 +437,7 @@ namespace SHADE
SHRenderGraph::SHRenderGraph(void) noexcept SHRenderGraph::SHRenderGraph(void) noexcept
: renderGraphStorage{} : renderGraphStorage{}
, nodes{} , nodes{}
, resourceManager{nullptr} , resourceHub{nullptr}
{ {
} }
@ -389,7 +445,7 @@ namespace SHADE
: renderGraphStorage{ rhs.renderGraphStorage } : renderGraphStorage{ rhs.renderGraphStorage }
, nodeIndexing{ std::move(rhs.nodeIndexing) } , nodeIndexing{ std::move(rhs.nodeIndexing) }
, nodes{ std::move(rhs.nodes) } , nodes{ std::move(rhs.nodes) }
, resourceManager{ std::move(rhs.resourceManager) } , resourceHub{ std::move(rhs.resourceHub) }
{ {
} }
@ -402,7 +458,7 @@ namespace SHADE
renderGraphStorage = rhs.renderGraphStorage; renderGraphStorage = rhs.renderGraphStorage;
nodeIndexing = std::move(rhs.nodeIndexing); nodeIndexing = std::move(rhs.nodeIndexing);
nodes = std::move(rhs.nodes); nodes = std::move(rhs.nodes);
resourceManager = std::move(rhs.resourceManager); resourceHub = std::move(rhs.resourceHub);
return *this; return *this;
} }
@ -467,7 +523,7 @@ namespace SHADE
} }
} }
nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(renderGraphStorage, std::move(descInitParams), std::move(predecessors))); nodes.emplace_back(renderGraphStorage->resourceHub->Create<SHRenderGraphNode>(renderGraphStorage, std::move(descInitParams), std::move(predecessors)));
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u); nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
return nodes.at(nodeIndexing[nodeName]); return nodes.at(nodeIndexing[nodeName]);
} }
@ -549,6 +605,11 @@ namespace SHADE
} }
std::vector<Handle<SHRenderGraphNode>> const& SHRenderGraph::GetNodes(void) const noexcept
{
return nodes;
}
Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept
{ {
if (renderGraphStorage->graphResources->contains(resourceName)) if (renderGraphStorage->graphResources->contains(resourceName))

View File

@ -67,7 +67,7 @@ namespace SHADE
std::vector<Handle<SHRenderGraphNode>> nodes; std::vector<Handle<SHRenderGraphNode>> nodes;
//! Resource library for graph handles //! Resource library for graph handles
std::shared_ptr<SHResourceHub> resourceManager; SHResourceHub* resourceHub;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -81,8 +81,9 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept; void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain, SHResourceHub* resourceHub) noexcept;
void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {}); void AddResource(std::string resourceName, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
void LinkNonOwningResource (Handle<SHRenderGraph> resourceOrigin, std::string resourceName) noexcept;
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept; Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
void Generate (void) noexcept; void Generate (void) noexcept;
@ -94,9 +95,27 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept; Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept;
Handle<SHRenderGraphResource> GetRenderGraphResource (std::string const& resourceName) const noexcept; std::vector<Handle<SHRenderGraphNode>> const& GetNodes (void) const noexcept;
Handle<SHRenderGraphResource> GetRenderGraphResource (std::string const& resourceName) const noexcept;
}; };
} }
#endif #endif
/* Some notes here:
* - The graph wasn't implemented with the intention of it being this versatile.
* - Graphs weren't meant to share resources and hence the generating of the render graph doesn't account for it.
* However, because it was eventually necessary that some resources had to be shared and its contents carried over to
* other graphs, the functionality was implemented through a link function in SHRenderGraph.cpp to facilitate this linkage.
* This should ideally be replaced by an implementation more self-contained, perhaps through a higher level class like a canvas
* that manage the resources instead and can facilitate such linking of resources.
*
*/

View File

@ -45,7 +45,7 @@ namespace SHADE
for (uint32_t j = 0; j < attResources.size(); ++j) for (uint32_t j = 0; j < attResources.size(); ++j)
{ {
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0; 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]; 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 // We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
@ -72,7 +72,7 @@ namespace SHADE
for (uint32_t j = 0; j < attResources.size(); ++j) for (uint32_t j = 0; j < attResources.size(); ++j)
{ {
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0; 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]; 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 // We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
@ -157,7 +157,7 @@ namespace SHADE
newDesc.format = attResources[i]->resourceFormat; newDesc.format = attResources[i]->resourceFormat;
if (attResources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) if (attResources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT))
containsSwapchainImage = true; containsSwapchainImage = true;
resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i); resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i);
@ -246,7 +246,7 @@ namespace SHADE
// Add subpass to container and create mapping for it // Add subpass to container and create mapping for it
subpasses.emplace_back subpasses.emplace_back
( (
graphStorage->resourceManager->Create<SHSubpass> graphStorage->resourceHub->Create<SHSubpass>
( (
subpassName, subpassName,
graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()), graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()),
@ -255,7 +255,7 @@ namespace SHADE
); );
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u); subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
Handle<SHSubpass> subpass = subpasses.back(); Handle<SHSubpass> subpass = subpasses.back();
subpass->Init(*graphStorage->resourceManager); subpass->Init(*graphStorage->resourceHub);
// Register the SuperBatch // Register the SuperBatch
batcher.RegisterSuperBatch(subpass->GetSuperBatch()); batcher.RegisterSuperBatch(subpass->GetSuperBatch());
@ -276,7 +276,7 @@ namespace SHADE
} }
// Create the subpass compute with the resources // Create the subpass compute with the resources
auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty()); auto nodeCompute = graphStorage->resourceHub->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty());
nodeComputes.push_back(nodeCompute); nodeComputes.push_back(nodeCompute);
return nodeCompute; return nodeCompute;
@ -401,4 +401,9 @@ namespace SHADE
return {}; return {};
} }
std::vector<Handle<SHRenderGraphResource>> const& SHRenderGraphNode::GetResources(void) const noexcept
{
return attResources;
}
} }

View File

@ -114,6 +114,7 @@ namespace SHADE
Handle<SHVkRenderpass> GetRenderpass(void) const noexcept; Handle<SHVkRenderpass> GetRenderpass(void) const noexcept;
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept; Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept; Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept;
std::vector<Handle<SHRenderGraphResource>> const& GetResources (void) const noexcept;
friend class SHRenderGraph; friend class SHRenderGraph;
}; };

View File

@ -58,7 +58,7 @@ namespace SHADE
if (layouts.size() == SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE + 1) if (layouts.size() == SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE + 1)
{ {
// create compute resources // create compute resources
computeResource = graphStorage->resourceManager->Create<ComputeResource>(); computeResource = graphStorage->resourceHub->Create<ComputeResource>();
auto computeResourceLayout = layouts[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE]; auto computeResourceLayout = layouts[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE];
computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, { 1 }); computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, { 1 });
@ -108,7 +108,7 @@ namespace SHADE
// loop through bindings and write descriptor sets // loop through bindings and write descriptor sets
for (auto& binding : pipelineDescSetLayouts->GetBindings()) for (auto& binding : pipelineDescSetLayouts->GetBindings())
{ {
uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0; uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0;
SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle<SHVkSampler>{}, vk::ImageLayout::eGeneral); SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle<SHVkSampler>{}, vk::ImageLayout::eGeneral);
graphResourceDescSets[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 }); graphResourceDescSets[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 });
@ -143,7 +143,7 @@ namespace SHADE
.newLayout = vk::ImageLayout::eGeneral, .newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = resource->GetImage((resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(), .image = resource->GetImage((resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(),
.subresourceRange = vk::ImageSubresourceRange .subresourceRange = vk::ImageSubresourceRange
{ {
.aspectMask = resource->imageAspectFlags, .aspectMask = resource->imageAspectFlags,

View File

@ -6,9 +6,28 @@
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/SHVkUtil.h" #include "Graphics/SHVkUtil.h"
#include "SHRenderGraphStorage.h" #include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHSubpass.h"
#include "Graphics/RenderGraph/SHRenderGraphNode.h"
namespace SHADE namespace SHADE
{ {
void SHRenderGraphResource::InfoTracker::TrackLayout(Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass, vk::ImageLayout layout) noexcept
{
NodeSubpassPair nodeSubpassPair = std::pair(node, subpass);
layoutTracker[std::hash<NodeSubpassPair>{}(nodeSubpassPair)] = layout;
}
vk::ImageLayout SHRenderGraphResource::InfoTracker::GetLayout(Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass) const noexcept
{
NodeSubpassPair nodeSubpassPair = std::pair(node, subpass);
std::size_t hashedValue = std::hash<NodeSubpassPair>{}(nodeSubpassPair);
if (layoutTracker.contains(hashedValue))
return layoutTracker.at(hashedValue);
else
return vk::ImageLayout::eUndefined;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -46,7 +65,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
: graphStorage{renderGraphStorage} : graphStorage{renderGraphStorage}
, resourceTypeFlags{ } , resourceTypeFlags{ }
, resourceFormat{ format } , resourceFormat{ format }
@ -58,9 +77,9 @@ namespace SHADE
, resourceName{ name } , resourceName{ name }
{ {
// If the resource type is an arbitrary image and not swapchain image // If the resource type is an arbitrary image and not swapchain image
if (typeFlags.size() == 1 && *typeFlags.begin() == SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT) if (typeFlags.size() == 1 && *typeFlags.begin() == SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)
{ {
resourceTypeFlags |= static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT); resourceTypeFlags |= static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT);
// Prepare image view details // Prepare image view details
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
@ -97,30 +116,30 @@ namespace SHADE
// Check the resource type and set image usage flags and image aspect flags accordingly // Check the resource type and set image usage flags and image aspect flags accordingly
switch (type) switch (type)
{ {
case SH_ATT_DESC_TYPE_FLAGS::COLOR: case SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR:
usage |= vk::ImageUsageFlagBits::eColorAttachment; usage |= vk::ImageUsageFlagBits::eColorAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eColor; imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH: case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment; usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eDepth; imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::STENCIL: case SH_RENDER_GRAPH_RESOURCE_FLAGS::STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment; usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil; imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL: case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment; usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth; imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::INPUT: case SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT:
usage |= vk::ImageUsageFlagBits::eInputAttachment; usage |= vk::ImageUsageFlagBits::eInputAttachment;
usage |= vk::ImageUsageFlagBits::eSampled; usage |= vk::ImageUsageFlagBits::eSampled;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::STORAGE: case SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE:
usage |= vk::ImageUsageFlagBits::eStorage; usage |= vk::ImageUsageFlagBits::eStorage;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT: case SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT:
{ {
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. "); SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
return; return;
@ -146,6 +165,8 @@ namespace SHADE
// just 1 image view created // just 1 image view created
imageViews.push_back(images[0]->CreateImageView(graphStorage->logicalDevice, images[0], viewDetails)); imageViews.push_back(images[0]->CreateImageView(graphStorage->logicalDevice, images[0], viewDetails));
} }
infoTracker = renderGraphStorage->resourceHub->Create<InfoTracker>();
} }
/***************************************************************************/ /***************************************************************************/
@ -170,6 +191,7 @@ namespace SHADE
, mipLevels{ rhs.mipLevels } , mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags } , imageAspectFlags{ rhs.imageAspectFlags }
, graphStorage{rhs.graphStorage} , graphStorage{rhs.graphStorage}
, infoTracker {std::move (rhs.infoTracker)}
{ {
} }
@ -202,6 +224,7 @@ namespace SHADE
mipLevels = rhs.mipLevels; mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags; imageAspectFlags = rhs.imageAspectFlags;
graphStorage = rhs.graphStorage; graphStorage = rhs.graphStorage;
infoTracker = std::move(infoTracker);
return *this; return *this;
} }
@ -224,7 +247,7 @@ namespace SHADE
width = newWidth; width = newWidth;
height = newHeight; height = newHeight;
if ((resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) == 0) if ((resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) == 0)
{ {
// prepare image view details // prepare image view details
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
@ -342,4 +365,9 @@ namespace SHADE
return resourceName; return resourceName;
} }
SHADE::Handle<SHADE::SHRenderGraphResource::InfoTracker> SHRenderGraphResource::GetInfoTracker(void) const noexcept
{
return infoTracker;
}
} }

View File

@ -16,11 +16,35 @@ namespace SHADE
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkBuffer; class SHVkBuffer;
class SHRenderGraphStorage; class SHRenderGraphStorage;
class SHRenderGraphNode;
class SHSubpass;
static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0; static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
class SH_API SHRenderGraphResource class SH_API SHRenderGraphResource
{ {
public:
// For keeping track of resources as it gets passed down the pipeline (between multiple render graphs)
class InfoTracker
{
private:
using NodeSubpassPair = std::pair<Handle<SHRenderGraphNode>, Handle<SHSubpass>>;
//! key here is the render graph node and subpass name combined, value is the layout of the resource at that node and subpass
std::unordered_map<std::size_t, vk::ImageLayout> layoutTracker;
public:
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void TrackLayout (Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass, vk::ImageLayout layout) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
vk::ImageLayout GetLayout (Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass) const noexcept;
};
private: private:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
@ -62,12 +86,14 @@ namespace SHADE
//! usage flags //! usage flags
vk::ImageUsageFlags usage = {}; vk::ImageUsageFlags usage = {};
//! For tracking resource states in stages of the render graphs
Handle<InfoTracker> infoTracker;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept; SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept; ~SHRenderGraphResource(void) noexcept;
@ -89,6 +115,7 @@ namespace SHADE
Handle<SHVkImage> GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept; Handle<SHVkImage> GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
uint8_t GetMipLevels (void) const noexcept; uint8_t GetMipLevels (void) const noexcept;
std::string GetName (void) const noexcept; std::string GetName (void) const noexcept;
Handle<InfoTracker> GetInfoTracker (void) const noexcept;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;

View File

@ -20,7 +20,7 @@ namespace SHADE
Handle<SHVkSwapchain> swapchain; Handle<SHVkSwapchain> swapchain;
//! Resource manager for creation of objects //! Resource manager for creation of objects
std::shared_ptr<SHResourceHub> resourceManager; SHResourceHub* resourceHub;
//! Descriptor pool for the descriptor sets to be created in the subpasses //! Descriptor pool for the descriptor sets to be created in the subpasses
Handle<SHVkDescriptorPool> descriptorPool; Handle<SHVkDescriptorPool> descriptorPool;
@ -28,6 +28,10 @@ namespace SHADE
//! For accessing resources anywhere in the graph //! For accessing resources anywhere in the graph
Handle<std::unordered_map<std::string, Handle<SHRenderGraphResource>>> graphResources; Handle<std::unordered_map<std::string, Handle<SHRenderGraphResource>>> graphResources;
//! HACK: Because there's no interface to specify a dependency between graphs, this will help attachment descriptions
//! use the correct layout, when a resource is shared between graphs
std::unordered_map<uint64_t, vk::ImageLayout> nonOwningResourceInitialLayouts{};
//SHRenderGraphStorage(void) noexcept; //SHRenderGraphStorage(void) noexcept;
//SHRenderGraphStorage(SHRenderGraphStorage&& rhs) noexcept; //SHRenderGraphStorage(SHRenderGraphStorage&& rhs) noexcept;
//SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept; //SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept;

View File

@ -148,18 +148,18 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType) noexcept void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_RENDER_GRAPH_RESOURCE_FLAGS attachmentDescriptionType) noexcept
{ {
vk::ImageLayout imageLayout; vk::ImageLayout imageLayout;
switch (attachmentDescriptionType) switch (attachmentDescriptionType)
{ {
case SH_ATT_DESC_TYPE_FLAGS::DEPTH: case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH:
imageLayout = vk::ImageLayout::eDepthAttachmentOptimal; imageLayout = vk::ImageLayout::eDepthAttachmentOptimal;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::STENCIL: case SH_RENDER_GRAPH_RESOURCE_FLAGS::STENCIL:
imageLayout = vk::ImageLayout::eStencilAttachmentOptimal; imageLayout = vk::ImageLayout::eStencilAttachmentOptimal;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL: case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL:
imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
break; break;
default: default:
@ -309,7 +309,7 @@ namespace SHADE
auto resource = graphStorage->graphResources->at(inputNames[binding.BindPoint]); auto resource = graphStorage->graphResources->at(inputNames[binding.BindPoint]);
// If resource is swapchain image, get the correct image, if not just get 0. // If resource is swapchain image, get the correct image, if not just get 0.
uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0; uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
// layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL // layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL
vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal; vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;

View File

@ -95,7 +95,7 @@ namespace SHADE
// Preparation functions // Preparation functions
void AddColorOutput(std::string resourceToReference) noexcept; void AddColorOutput(std::string resourceToReference) noexcept;
void AddGeneralColorOutput(std::string resourceToReference) noexcept; void AddGeneralColorOutput(std::string resourceToReference) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept; void AddDepthOutput(std::string resourceToReference, SH_RENDER_GRAPH_RESOURCE_FLAGS attachmentDescriptionType = SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL) noexcept;
void AddGeneralDepthOutput(std::string resourceToReference) noexcept; void AddGeneralDepthOutput(std::string resourceToReference) noexcept;
void AddInput(std::string resourceToReference) noexcept; void AddInput(std::string resourceToReference) noexcept;
void AddGeneralInput (std::string resourceToReference) noexcept; void AddGeneralInput (std::string resourceToReference) noexcept;