diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h index c4d44ea8..16c07cdf 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h @@ -3,7 +3,7 @@ namespace SHADE { // 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_PRESENT = 0x02, @@ -11,7 +11,8 @@ namespace SHADE STENCIL = 0x08, DEPTH_STENCIL = 0x10, INPUT = 0x20, - STORAGE = 0x40 + STORAGE = 0x40, + SHARED = 0x80 // if resource is meant to be used across render graphs, mark this flag }; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 93be2413..b897eb06 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -11,6 +11,7 @@ #include "SHAttachmentDescInitParams.h" #include "SHRenderGraphStorage.h" #include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h" +#include "Tools/SHUtilities.h" namespace SHADE { @@ -49,7 +50,7 @@ namespace SHADE */ /***************************************************************************/ - void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list typeFlags, uint32_t w /*= static_cast(-1)*/, uint32_t h /*= static_cast(-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 typeFlags, uint32_t w /*= static_cast(-1)*/, uint32_t h /*= static_cast(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/) { // If we set to if (w == static_cast(-1) && h == static_cast(-1)) @@ -59,7 +60,32 @@ namespace SHADE format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format; } - renderGraphStorage->graphResources->try_emplace(resourceName, resourceManager->Create(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags)); + renderGraphStorage->graphResources->try_emplace(resourceName, renderGraphStorage->resourceHub->Create(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags)); + } + + void SHRenderGraph::LinkNonOwningResource(Handle resourceOrigin, std::string resourceName) noexcept + { + // resource to link + Handle 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; } + // 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 - if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))) + if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast(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 (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++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]; + resource->GetInfoTracker()->TrackLayout(node, {}, att.finalLayout); } ++i; } @@ -145,12 +200,13 @@ namespace SHADE attDesc.stencilLoadOp = vk::AttachmentLoadOp::eLoad; 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 // 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. 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) { auto resource = node->attResources[inputAtt.attachment]; - if (resource->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::INPUT)) + if (resource->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT)) { - if (resource->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR) || - resource->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) + if (resource->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR) || + resource->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) colorRead |= (1 << i); - else if (resource->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL)) + else if (resource->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL)) depthRead |= (1 << i); } else @@ -353,17 +409,17 @@ namespace SHADE */ /***************************************************************************/ - void SHRenderGraph::Init(Handle logicalDevice, Handle swapchain) noexcept + void SHRenderGraph::Init(Handle logicalDevice, Handle swapchain, SHResourceHub* resourceHub) noexcept { - resourceManager = std::make_shared(); + //resourceHub = std::make_shared(); - renderGraphStorage = resourceManager->Create(); - renderGraphStorage->graphResources = resourceManager->Create>>(); + renderGraphStorage = resourceHub->Create(); + renderGraphStorage->graphResources = resourceHub->Create>>(); renderGraphStorage->logicalDevice = logicalDevice; renderGraphStorage->swapchain = swapchain; - renderGraphStorage->resourceManager = resourceManager; + renderGraphStorage->resourceHub = resourceHub; renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools(); } @@ -381,7 +437,7 @@ namespace SHADE SHRenderGraph::SHRenderGraph(void) noexcept : renderGraphStorage{} , nodes{} - , resourceManager{nullptr} + , resourceHub{nullptr} { } @@ -389,7 +445,7 @@ namespace SHADE : renderGraphStorage{ rhs.renderGraphStorage } , nodeIndexing{ std::move(rhs.nodeIndexing) } , nodes{ std::move(rhs.nodes) } - , resourceManager{ std::move(rhs.resourceManager) } + , resourceHub{ std::move(rhs.resourceHub) } { } @@ -402,7 +458,7 @@ namespace SHADE renderGraphStorage = rhs.renderGraphStorage; nodeIndexing = std::move(rhs.nodeIndexing); nodes = std::move(rhs.nodes); - resourceManager = std::move(rhs.resourceManager); + resourceHub = std::move(rhs.resourceHub); return *this; } @@ -467,7 +523,7 @@ namespace SHADE } } - nodes.emplace_back(resourceManager->Create(renderGraphStorage, std::move(descInitParams), std::move(predecessors))); + nodes.emplace_back(renderGraphStorage->resourceHub->Create(renderGraphStorage, std::move(descInitParams), std::move(predecessors))); nodeIndexing.emplace(nodeName, static_cast(nodes.size()) - 1u); return nodes.at(nodeIndexing[nodeName]); } @@ -549,6 +605,11 @@ namespace SHADE } + std::vector> const& SHRenderGraph::GetNodes(void) const noexcept + { + return nodes; + } + Handle SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept { if (renderGraphStorage->graphResources->contains(resourceName)) diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index d90b66df..6429badf 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -67,7 +67,7 @@ namespace SHADE std::vector> nodes; //! Resource library for graph handles - std::shared_ptr resourceManager; + SHResourceHub* resourceHub; public: /*-----------------------------------------------------------------------*/ @@ -81,8 +81,9 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - void Init (Handle logicalDevice, Handle swapchain) noexcept; - void AddResource(std::string resourceName, std::initializer_list typeFlags, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {}); + void Init (Handle logicalDevice, Handle swapchain, SHResourceHub* resourceHub) noexcept; + void AddResource(std::string resourceName, std::initializer_list typeFlags, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {}); + void LinkNonOwningResource (Handle resourceOrigin, std::string resourceName) noexcept; Handle AddNode (std::string nodeName, std::initializer_list resourceInstruction, std::initializer_list predecessorNodes) noexcept; void Generate (void) noexcept; @@ -94,9 +95,27 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ /*-----------------------------------------------------------------------*/ - Handle GetNode (std::string const& nodeName) const noexcept; - Handle GetRenderGraphResource (std::string const& resourceName) const noexcept; + Handle GetNode (std::string const& nodeName) const noexcept; + std::vector> const& GetNodes (void) const noexcept; + Handle GetRenderGraphResource (std::string const& resourceName) const noexcept; }; } #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. + * + */ + + + + + diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index 12f0e246..9e6b7740 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -45,7 +45,7 @@ namespace SHADE for (uint32_t j = 0; j < attResources.size(); ++j) { - uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0; + uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast(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 @@ -72,7 +72,7 @@ namespace SHADE for (uint32_t j = 0; j < attResources.size(); ++j) { - uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0; + uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast(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 @@ -157,7 +157,7 @@ namespace SHADE newDesc.format = attResources[i]->resourceFormat; - if (attResources[i]->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) + if (attResources[i]->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) containsSwapchainImage = true; resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i); @@ -246,7 +246,7 @@ namespace SHADE // Add subpass to container and create mapping for it subpasses.emplace_back ( - graphStorage->resourceManager->Create + graphStorage->resourceHub->Create ( subpassName, graphStorage, GetHandle(), static_cast(subpasses.size()), @@ -255,7 +255,7 @@ namespace SHADE ); subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); Handle subpass = subpasses.back(); - subpass->Init(*graphStorage->resourceManager); + subpass->Init(*graphStorage->resourceHub); // Register the SuperBatch batcher.RegisterSuperBatch(subpass->GetSuperBatch()); @@ -276,7 +276,7 @@ namespace SHADE } // Create the subpass compute with the resources - auto nodeCompute = graphStorage->resourceManager->Create(graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty()); + auto nodeCompute = graphStorage->resourceHub->Create(graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty()); nodeComputes.push_back(nodeCompute); return nodeCompute; @@ -401,4 +401,9 @@ namespace SHADE return {}; } + std::vector> const& SHRenderGraphNode::GetResources(void) const noexcept + { + return attResources; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h index 695d1c31..5965b10d 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h @@ -114,6 +114,7 @@ namespace SHADE Handle GetRenderpass(void) const noexcept; Handle GetSubpass(std::string_view subpassName) const noexcept; Handle GetResource (uint32_t resourceIndex) const noexcept; + std::vector> const& GetResources (void) const noexcept; friend class SHRenderGraph; }; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp index a86acbc7..e8822acd 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp @@ -58,7 +58,7 @@ namespace SHADE if (layouts.size() == SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE + 1) { // create compute resources - computeResource = graphStorage->resourceManager->Create(); + computeResource = graphStorage->resourceHub->Create(); auto computeResourceLayout = layouts[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE]; computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, { 1 }); @@ -108,7 +108,7 @@ namespace SHADE // loop through bindings and write descriptor sets for (auto& binding : pipelineDescSetLayouts->GetBindings()) { - uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0; + uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0; SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle{}, vk::ImageLayout::eGeneral); graphResourceDescSets[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 }); @@ -143,7 +143,7 @@ namespace SHADE .newLayout = vk::ImageLayout::eGeneral, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = resource->GetImage((resource->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(), + .image = resource->GetImage((resource->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(), .subresourceRange = vk::ImageSubresourceRange { .aspectMask = resource->imageAspectFlags, diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp index 502e09b2..327a94b6 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp @@ -6,9 +6,28 @@ #include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/SHVkUtil.h" #include "SHRenderGraphStorage.h" +#include "Graphics/RenderGraph/SHSubpass.h" +#include "Graphics/RenderGraph/SHRenderGraphNode.h" namespace SHADE { + void SHRenderGraphResource::InfoTracker::TrackLayout(Handle node, Handle subpass, vk::ImageLayout layout) noexcept + { + NodeSubpassPair nodeSubpassPair = std::pair(node, subpass); + layoutTracker[std::hash{}(nodeSubpassPair)] = layout; + } + + + vk::ImageLayout SHRenderGraphResource::InfoTracker::GetLayout(Handle node, Handle subpass) const noexcept + { + NodeSubpassPair nodeSubpassPair = std::pair(node, subpass); + std::size_t hashedValue = std::hash{}(nodeSubpassPair); + + if (layoutTracker.contains(hashedValue)) + return layoutTracker.at(hashedValue); + else + return vk::ImageLayout::eUndefined; + } /***************************************************************************/ /*! @@ -46,7 +65,7 @@ namespace SHADE */ /***************************************************************************/ - SHRenderGraphResource::SHRenderGraphResource(Handle renderGraphStorage, std::string const& name, std::initializer_list typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept + SHRenderGraphResource::SHRenderGraphResource(Handle renderGraphStorage, std::string const& name, std::initializer_list typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept : graphStorage{renderGraphStorage} , resourceTypeFlags{ } , resourceFormat{ format } @@ -58,9 +77,9 @@ namespace SHADE , resourceName{ name } { // 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(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT); + resourceTypeFlags |= static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT); // Prepare image view details SHImageViewDetails viewDetails @@ -97,30 +116,30 @@ namespace SHADE // Check the resource type and set image usage flags and image aspect flags accordingly switch (type) { - case SH_ATT_DESC_TYPE_FLAGS::COLOR: + case SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR: usage |= vk::ImageUsageFlagBits::eColorAttachment; imageAspectFlags |= vk::ImageAspectFlagBits::eColor; break; - case SH_ATT_DESC_TYPE_FLAGS::DEPTH: + case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH: usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment; imageAspectFlags |= vk::ImageAspectFlagBits::eDepth; break; - case SH_ATT_DESC_TYPE_FLAGS::STENCIL: + case SH_RENDER_GRAPH_RESOURCE_FLAGS::STENCIL: usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment; imageAspectFlags |= vk::ImageAspectFlagBits::eStencil; break; - case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL: + case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL: usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment; imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth; break; - case SH_ATT_DESC_TYPE_FLAGS::INPUT: + case SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT: usage |= vk::ImageUsageFlagBits::eInputAttachment; usage |= vk::ImageUsageFlagBits::eSampled; break; - case SH_ATT_DESC_TYPE_FLAGS::STORAGE: + case SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE: usage |= vk::ImageUsageFlagBits::eStorage; 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. "); return; @@ -146,6 +165,8 @@ namespace SHADE // just 1 image view created imageViews.push_back(images[0]->CreateImageView(graphStorage->logicalDevice, images[0], viewDetails)); } + + infoTracker = renderGraphStorage->resourceHub->Create(); } /***************************************************************************/ @@ -170,6 +191,7 @@ namespace SHADE , mipLevels{ rhs.mipLevels } , imageAspectFlags{ rhs.imageAspectFlags } , graphStorage{rhs.graphStorage} + , infoTracker {std::move (rhs.infoTracker)} { } @@ -202,6 +224,7 @@ namespace SHADE mipLevels = rhs.mipLevels; imageAspectFlags = rhs.imageAspectFlags; graphStorage = rhs.graphStorage; + infoTracker = std::move(infoTracker); return *this; } @@ -224,7 +247,7 @@ namespace SHADE width = newWidth; height = newHeight; - if ((resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) == 0) + if ((resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) == 0) { // prepare image view details SHImageViewDetails viewDetails @@ -342,4 +365,9 @@ namespace SHADE return resourceName; } + SHADE::Handle SHRenderGraphResource::GetInfoTracker(void) const noexcept + { + return infoTracker; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h index e2fc5d8d..0004bb4a 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h @@ -16,11 +16,35 @@ namespace SHADE class SHVkCommandBuffer; class SHVkBuffer; class SHRenderGraphStorage; + class SHRenderGraphNode; + class SHSubpass; static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0; 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>; + + //! 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 layoutTracker; + + public: + /*-----------------------------------------------------------------------*/ + /* PUBLIC MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + void TrackLayout (Handle node, Handle subpass, vk::ImageLayout layout) noexcept; + + /*-----------------------------------------------------------------------*/ + /* SETTERS AND GETTERS */ + /*-----------------------------------------------------------------------*/ + vk::ImageLayout GetLayout (Handle node, Handle subpass) const noexcept; + }; + private: /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ @@ -62,12 +86,14 @@ namespace SHADE //! usage flags vk::ImageUsageFlags usage = {}; + //! For tracking resource states in stages of the render graphs + Handle infoTracker; public: /*-----------------------------------------------------------------------*/ /* CTORS AND DTORS */ /*-----------------------------------------------------------------------*/ - SHRenderGraphResource(Handle renderGraphStorage, std::string const& name, std::initializer_list typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept; + SHRenderGraphResource(Handle renderGraphStorage, std::string const& name, std::initializer_list 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& operator=(SHRenderGraphResource&& rhs) noexcept; ~SHRenderGraphResource(void) noexcept; @@ -89,6 +115,7 @@ namespace SHADE Handle GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept; uint8_t GetMipLevels (void) const noexcept; std::string GetName (void) const noexcept; + Handle GetInfoTracker (void) const noexcept; friend class SHRenderGraphNode; friend class SHRenderGraph; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h index 54ef705a..d02d8d39 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h @@ -20,7 +20,7 @@ namespace SHADE Handle swapchain; //! Resource manager for creation of objects - std::shared_ptr resourceManager; + SHResourceHub* resourceHub; //! Descriptor pool for the descriptor sets to be created in the subpasses Handle descriptorPool; @@ -28,6 +28,10 @@ namespace SHADE //! For accessing resources anywhere in the graph Handle>> 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 nonOwningResourceInitialLayouts{}; + //SHRenderGraphStorage(void) noexcept; //SHRenderGraphStorage(SHRenderGraphStorage&& rhs) noexcept; //SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index 6e78eb9f..87de0785 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -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; switch (attachmentDescriptionType) { - case SH_ATT_DESC_TYPE_FLAGS::DEPTH: + case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH: imageLayout = vk::ImageLayout::eDepthAttachmentOptimal; break; - case SH_ATT_DESC_TYPE_FLAGS::STENCIL: + case SH_RENDER_GRAPH_RESOURCE_FLAGS::STENCIL: imageLayout = vk::ImageLayout::eStencilAttachmentOptimal; break; - case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL: + case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL: imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; break; default: @@ -309,7 +309,7 @@ namespace SHADE auto resource = graphStorage->graphResources->at(inputNames[binding.BindPoint]); // If resource is swapchain image, get the correct image, if not just get 0. - uint32_t viewIndex = (resource->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0; + uint32_t viewIndex = (resource->resourceTypeFlags & static_cast(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 vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h index c82ebdd0..9b4d7bf9 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h @@ -95,7 +95,7 @@ namespace SHADE // Preparation functions void AddColorOutput(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 AddInput(std::string resourceToReference) noexcept; void AddGeneralInput (std::string resourceToReference) noexcept;