Added UI functionality to the Graphics System #232
|
@ -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
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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<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 (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
|
||||
|
@ -59,7 +60,32 @@ namespace SHADE
|
|||
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;
|
||||
}
|
||||
|
||||
// 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<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;
|
||||
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];
|
||||
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<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) ||
|
||||
resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))
|
||||
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR) ||
|
||||
resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT))
|
||||
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);
|
||||
}
|
||||
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->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
|
||||
renderGraphStorage = resourceHub->Create<SHRenderGraphStorage>();
|
||||
renderGraphStorage->graphResources = resourceHub->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
|
||||
|
||||
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<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);
|
||||
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
|
||||
{
|
||||
if (renderGraphStorage->graphResources->contains(resourceName))
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace SHADE
|
|||
std::vector<Handle<SHRenderGraphNode>> nodes;
|
||||
|
||||
//! Resource library for graph handles
|
||||
std::shared_ptr<SHResourceHub> resourceManager;
|
||||
SHResourceHub* resourceHub;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -81,8 +81,9 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) 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 Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain, SHResourceHub* resourceHub) noexcept;
|
||||
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;
|
||||
|
||||
void Generate (void) noexcept;
|
||||
|
@ -95,8 +96,26 @@ namespace SHADE
|
|||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept;
|
||||
std::vector<Handle<SHRenderGraphNode>> const& GetNodes (void) const noexcept;
|
||||
Handle<SHRenderGraphResource> 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace SHADE
|
|||
|
||||
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];
|
||||
|
||||
// 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<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];
|
||||
|
||||
// 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<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;
|
||||
|
||||
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<SHSubpass>
|
||||
graphStorage->resourceHub->Create<SHSubpass>
|
||||
(
|
||||
subpassName,
|
||||
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);
|
||||
Handle<SHSubpass> 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<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);
|
||||
|
||||
return nodeCompute;
|
||||
|
@ -401,4 +401,9 @@ namespace SHADE
|
|||
return {};
|
||||
}
|
||||
|
||||
std::vector<Handle<SHRenderGraphResource>> const& SHRenderGraphNode::GetResources(void) const noexcept
|
||||
{
|
||||
return attResources;
|
||||
}
|
||||
|
||||
}
|
|
@ -114,6 +114,7 @@ namespace SHADE
|
|||
Handle<SHVkRenderpass> GetRenderpass(void) const noexcept;
|
||||
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
|
||||
Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept;
|
||||
std::vector<Handle<SHRenderGraphResource>> const& GetResources (void) const noexcept;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace SHADE
|
|||
if (layouts.size() == SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE + 1)
|
||||
{
|
||||
// create compute resources
|
||||
computeResource = graphStorage->resourceManager->Create<ComputeResource>();
|
||||
computeResource = graphStorage->resourceHub->Create<ComputeResource>();
|
||||
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<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);
|
||||
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<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
|
||||
{
|
||||
.aspectMask = resource->imageAspectFlags,
|
||||
|
|
|
@ -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<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}
|
||||
, 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<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
|
||||
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<InfoTracker>();
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -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<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
|
||||
SHImageViewDetails viewDetails
|
||||
|
@ -342,4 +365,9 @@ namespace SHADE
|
|||
return resourceName;
|
||||
}
|
||||
|
||||
SHADE::Handle<SHADE::SHRenderGraphResource::InfoTracker> SHRenderGraphResource::GetInfoTracker(void) const noexcept
|
||||
{
|
||||
return infoTracker;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<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 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> infoTracker;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* 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& operator=(SHRenderGraphResource&& rhs) noexcept;
|
||||
~SHRenderGraphResource(void) noexcept;
|
||||
|
@ -89,6 +115,7 @@ namespace SHADE
|
|||
Handle<SHVkImage> GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
|
||||
uint8_t GetMipLevels (void) const noexcept;
|
||||
std::string GetName (void) const noexcept;
|
||||
Handle<InfoTracker> GetInfoTracker (void) const noexcept;
|
||||
|
||||
friend class SHRenderGraphNode;
|
||||
friend class SHRenderGraph;
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace SHADE
|
|||
Handle<SHVkSwapchain> swapchain;
|
||||
|
||||
//! 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
|
||||
Handle<SHVkDescriptorPool> descriptorPool;
|
||||
|
@ -28,6 +28,10 @@ namespace SHADE
|
|||
//! For accessing resources anywhere in the graph
|
||||
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(SHRenderGraphStorage&& rhs) noexcept;
|
||||
//SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept;
|
||||
|
|
|
@ -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<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
|
||||
vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue