Refactored Graphics #297
|
@ -5,21 +5,22 @@ typedef uint32_t SHEventIdentifier;
|
|||
typedef uint32_t SHEventHandle;
|
||||
|
||||
//Add your event identifiers here:
|
||||
constexpr SHEventIdentifier SH_EXAMPLE_EVENT { 0 };
|
||||
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 };
|
||||
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_ADD_CHILD_EVENT { 6 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_REMOVE_CHILD_EVENT { 7 };
|
||||
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 8 };
|
||||
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 9 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 10 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 11 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 12 };
|
||||
constexpr SHEventIdentifier SH_SCENE_INIT_PRE { 13 };
|
||||
constexpr SHEventIdentifier SH_SCENE_INIT_POST { 14 };
|
||||
constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 };
|
||||
constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 };
|
||||
constexpr SHEventIdentifier SH_EXAMPLE_EVENT { 0 };
|
||||
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 };
|
||||
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_ADD_CHILD_EVENT { 6 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_REMOVE_CHILD_EVENT { 7 };
|
||||
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 8 };
|
||||
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 9 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 10 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 11 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 12 };
|
||||
constexpr SHEventIdentifier SH_SCENE_INIT_PRE { 13 };
|
||||
constexpr SHEventIdentifier SH_SCENE_INIT_POST { 14 };
|
||||
constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 };
|
||||
constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 };
|
||||
constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 };
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <initializer_list>
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHLightEnableShadowEvent
|
||||
{
|
||||
//! We need to get the light component and initialize the relevant variables.
|
||||
EntityID lightEntity;
|
||||
};
|
||||
}
|
|
@ -183,34 +183,32 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
// Initialize world render graph
|
||||
renderGraph->Init("World Render Graph", device, swapchain, &resourceManager, renderContextCmdPools);
|
||||
renderGraph->AddResource("Position", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Position", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
//worldRenderGraph->AddResource("Tangents", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Light Layer Indices", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("SSAO", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
renderGraph->AddResource("SSAO Blur", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
renderGraph->AddResource("Present", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* MAIN NODE */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
auto gBufferNode = renderGraph->AddNode("G-Buffer",
|
||||
auto gBufferNode = renderGraph->AddNode("G-Buffer",
|
||||
{
|
||||
"Position",
|
||||
"Entity ID",
|
||||
"Position",
|
||||
"Entity ID",
|
||||
"Light Layer Indices",
|
||||
"Normals",
|
||||
"Albedo",
|
||||
"Depth Buffer",
|
||||
"Scene",
|
||||
"Depth Buffer",
|
||||
"SSAO",
|
||||
"SSAO Blur"
|
||||
},
|
||||
},
|
||||
{}); // no predecessors
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -251,23 +249,46 @@ namespace SHADE
|
|||
auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout();
|
||||
|
||||
ssaoPass->ModifyWriteDescImageComputeResource(SHSSAO::DESC_SET_IMAGE_BINDING, { &viewSamplerLayout, 1 });
|
||||
ssaoPass->SetRenderer (worldRenderer);
|
||||
ssaoPass->SetRenderer(worldRenderer);
|
||||
|
||||
// Add another pass to blur SSAO
|
||||
Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute("SSAO Blur Step", ssaoBlurShader, { "SSAO", "SSAO Blur" });
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SHADOW MAP PASS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Shadow map pass will have no resources bound at first. Lighting system will add resources to the node.
|
||||
// It will initially also not have any subpasses since they will be added for each light that casts shadows.
|
||||
//auto shadowMapPass = renderGraph->AddNode("Shadow Map Pass", {}, {});
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEFERRED COMPOSITE NODE */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// This pass will facilitate both lighting and shadows in 1 single pass.
|
||||
auto deferredCompositeNode = renderGraph->AddNode("Deferred Comp Pass",
|
||||
{
|
||||
"Position",
|
||||
"Light Layer Indices",
|
||||
"Normals",
|
||||
"Albedo",
|
||||
"Scene",
|
||||
"SSAO Blur"
|
||||
},
|
||||
{"G-Buffer"});
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEFERRED COMPOSITE SUBPASS INIT */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
gBufferNode->AddNodeCompute("Deferred Composite", deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" });
|
||||
|
||||
deferredCompositeNode->AddNodeCompute("Deferred Composite", deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" });
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEBUG DRAW PASS INIT */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Set up Debug Draw Passes
|
||||
// - Depth Tested
|
||||
auto debugDrawNodeDepth = renderGraph->AddNode("Debug Draw with Depth", { "Scene", "Depth Buffer" }, {"G-Buffer"});
|
||||
auto debugDrawNodeDepth = renderGraph->AddNode("Debug Draw with Depth", { "Scene", "Depth Buffer" }, {"G-Buffer", "Deferred Comp Pass"});
|
||||
auto debugDrawDepthSubpass = debugDrawNodeDepth->AddSubpass("Debug Draw with Depth", worldViewport, worldRenderer);
|
||||
debugDrawDepthSubpass->AddColorOutput("Scene");
|
||||
debugDrawDepthSubpass->AddDepthOutput("Depth Buffer");
|
||||
|
@ -279,7 +300,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* SCREEN SPACE PASS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
auto screenSpaceNode = renderGraph->AddNode("Screen Space Pass", { "Scene", "Entity ID" }, {"G-Buffer", "Debug Draw" });
|
||||
auto screenSpaceNode = renderGraph->AddNode("Screen Space Pass", { "Scene", "Entity ID" }, {"Deferred Comp Pass", "G-Buffer", "Debug Draw" });
|
||||
auto uiSubpass = screenSpaceNode->AddSubpass("UI", worldViewport, screenRenderer);
|
||||
uiSubpass->AddColorOutput("Scene");
|
||||
uiSubpass->AddColorOutput("Entity ID");
|
||||
|
@ -410,6 +431,16 @@ namespace SHADE
|
|||
}
|
||||
|
||||
|
||||
void SHGraphicsSystem::InitEvents(void) noexcept
|
||||
{
|
||||
std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> thisReceiver
|
||||
{
|
||||
std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveLightEnableShadowEvent)
|
||||
};
|
||||
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(thisReceiver);
|
||||
SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, receiver);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructor/Destructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -694,6 +725,18 @@ namespace SHADE
|
|||
renderers.erase(iter);
|
||||
}
|
||||
|
||||
SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr event) noexcept
|
||||
{
|
||||
// Add the shadow map resource to the graph
|
||||
|
||||
// link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer.
|
||||
|
||||
// Add a subpass to render to that shadow map
|
||||
|
||||
//renderGraph->GetNode ();
|
||||
return event->handle;
|
||||
}
|
||||
|
||||
Handle<SHMaterial> SHGraphicsSystem::AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass)
|
||||
{
|
||||
// Retrieve pipeline from pipeline storage or create if unavailable
|
||||
|
|
|
@ -35,6 +35,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Camera/SHCameraDirector.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHFontLibrary.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
||||
#include "Graphics/Events/SHGraphicsEvents.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -102,10 +103,7 @@ namespace SHADE
|
|||
void InitMiddleEnd (void) noexcept;
|
||||
void InitSubsystems (void) noexcept;
|
||||
void InitBuiltInResources (void);
|
||||
|
||||
#ifdef SHEDITOR
|
||||
void InitEditorRenderGraph (void) noexcept;
|
||||
#endif
|
||||
void InitEvents (void) noexcept;
|
||||
|
||||
public:
|
||||
class SH_API BeginRoutine final : public SHSystemRoutine
|
||||
|
@ -176,6 +174,10 @@ namespace SHADE
|
|||
Handle<SHRenderer> AddRenderer(SHRenderer::PROJECTION_TYPE projectionType);
|
||||
void RemoveRenderer(Handle<SHRenderer> renderer);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Light functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr event) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Material Functions */
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHLightComponent.h"
|
||||
#include "Graphics/Events/SHGraphicsEvents.h"
|
||||
#include "Events/SHEventManager.hpp"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -104,6 +106,21 @@ namespace SHADE
|
|||
//MakeDirty();
|
||||
}
|
||||
|
||||
void SHLightComponent::SetEnableShadow(bool flag) noexcept
|
||||
{
|
||||
lightData.castShadows = flag;
|
||||
|
||||
// If the flag is true
|
||||
if (flag && lightData.shadowMapIndex == SHLightData::INVALID_SHADOW_MAP_INDEX)
|
||||
{
|
||||
// Create new event and broadcast it
|
||||
SHLightEnableShadowEvent newEvent;
|
||||
newEvent.lightEntity = GetEID();
|
||||
|
||||
SHEventManager::BroadcastEvent<SHLightEnableShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
SHLightData const& SHLightComponent::GetLightData(void) const noexcept
|
||||
{
|
||||
return lightData;
|
||||
|
|
|
@ -25,7 +25,6 @@ namespace SHADE
|
|||
////! If the light's data is already in the buffers, this will be set to true.
|
||||
//bool bound;
|
||||
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* LIFECYCLE FUNCTIONS */
|
||||
|
@ -49,6 +48,7 @@ namespace SHADE
|
|||
//void Unbind (void) noexcept;
|
||||
//void SetBound (uint32_t inIndexInBuffer) noexcept;
|
||||
void SetStrength (float value) noexcept; // serialized
|
||||
void SetEnableShadow (bool flag) noexcept;
|
||||
|
||||
|
||||
SHLightData const& GetLightData (void) const noexcept;
|
||||
|
@ -59,7 +59,7 @@ namespace SHADE
|
|||
uint32_t const& GetCullingMask (void) const noexcept; // serialized
|
||||
//bool IsDirty (void) const noexcept;
|
||||
//bool GetBound (void) const noexcept;
|
||||
uint32_t GetIndexInBuffer (void) const noexcept;
|
||||
//uint32_t GetIndexInBuffer (void) const noexcept;
|
||||
float GetStrength (void) const noexcept;
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
|
|
|
@ -16,6 +16,12 @@ namespace SHADE
|
|||
|
||||
// Diffuse color set to 1
|
||||
color = SHVec4::One;
|
||||
|
||||
// light will default not cast shadows
|
||||
castShadows = false;
|
||||
|
||||
// shadow map index is invalid.
|
||||
shadowMapIndex = INVALID_SHADOW_MAP_INDEX;
|
||||
}
|
||||
|
||||
}
|
|
@ -26,6 +26,8 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
struct SHLightData
|
||||
{
|
||||
static constexpr uint32_t INVALID_SHADOW_MAP_INDEX = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
//! position of the light
|
||||
SHVec3 position;
|
||||
|
||||
|
@ -46,6 +48,13 @@ namespace SHADE
|
|||
//! Strength of the light
|
||||
float strength;
|
||||
|
||||
//! Whether or not the light will cast a shadow. More technically, whether or
|
||||
//! not the light will result in the addition of a depth map into the render graph
|
||||
//! to be used for shadow mapping calculations.
|
||||
bool castShadows;
|
||||
|
||||
//! Index of the shadow map when it gets placed in the descriptor array of textures (that are all shadow maps).
|
||||
uint32_t shadowMapIndex;
|
||||
|
||||
void Reset (void) noexcept;
|
||||
//! TODO:
|
||||
|
|
|
@ -68,6 +68,56 @@ namespace SHADE
|
|||
renderGraphStorage->graphResources->try_emplace(resourceName, resource);
|
||||
}
|
||||
|
||||
|
||||
void SHRenderGraph::RemoveResource(std::string resourceName) noexcept
|
||||
{
|
||||
// 1. Check if nodes are using said attachment and remove if they are
|
||||
// - Check subpasses while at it and remove as well if used as attachment
|
||||
// 2. Regenerate graph
|
||||
// - Delete all vulkan objects first as well and clear the necessary containers
|
||||
|
||||
if (!renderGraphStorage->graphResources->contains(resourceName))
|
||||
return;
|
||||
|
||||
renderGraphStorage->logicalDevice->WaitIdle();
|
||||
|
||||
uint64_t handleID = renderGraphStorage->graphResources->at (resourceName).GetId().Raw;
|
||||
|
||||
// Record nodes that will be affected
|
||||
std::vector<uint32_t> affectedNodes{};
|
||||
|
||||
// Detach resource from all nodes if applicable
|
||||
for (uint32_t i = 0; i < nodes.size(); ++i)
|
||||
{
|
||||
if (nodes[i]->DetachResource(resourceName, handleID))
|
||||
affectedNodes.emplace_back(i);
|
||||
}
|
||||
|
||||
// Up to this point the nodes and subpasses should have no trace of the deleted resource. Attachment
|
||||
// descriptions and subpass indices should also have been reconfigured at this point. However, this
|
||||
// means that the subpass descriptions and subpass dependencies need to be reconfigured.
|
||||
|
||||
// configure subpass dependencies and descriptions.
|
||||
for (auto& affectedNode : affectedNodes)
|
||||
nodes[affectedNode]->ConfigureSubpasses();
|
||||
|
||||
for (auto& affectedNode : affectedNodes)
|
||||
nodes[affectedNode]->CreateRenderpass();
|
||||
|
||||
for (auto& affectedNode : affectedNodes)
|
||||
nodes[affectedNode]->CreateFramebuffer();
|
||||
/*
|
||||
* IMPORTANT NOTES
|
||||
*
|
||||
* This remove resource function would be more complete if it accounted for renderpass compatibility by
|
||||
* recreating the graphics pipelines stored in render graph nodes. However due to time constraints, this is left out. As such,
|
||||
* pipelines that are recreated with a certain renderpass and subpass will assumed to be compatible when used in different subpasses.
|
||||
*
|
||||
* This function also recreates renderpasses and framebuffers so it does not account for removing of resources that are used in nodes whose
|
||||
* renderpasses and framebuffers are used externally in systems like Editor with ImGui.
|
||||
*/
|
||||
}
|
||||
|
||||
void SHRenderGraph::LinkNonOwningResource(Handle<SHRenderGraph> resourceOrigin, std::string resourceName) noexcept
|
||||
{
|
||||
// resource to link
|
||||
|
@ -236,140 +286,12 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraph::ConfigureSubpasses(void) noexcept
|
||||
void SHRenderGraph::ConfigureAllSubpasses(void) noexcept
|
||||
{
|
||||
// For all nodes
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
// Create subpass description and dependencies based on number of subpasses
|
||||
node->spDescs.resize(node->subpasses.size());
|
||||
node->spDeps.resize(node->subpasses.size());
|
||||
|
||||
// Now we want to loop through all attachments in all subpasses in the node and query
|
||||
// the resources being used. For each resource we want to query the type and record it
|
||||
// in bit fields (1 bit for each subpass).
|
||||
uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
// For all subpasses (see above description about bit field for this).
|
||||
for (auto& subpass : node->subpasses)
|
||||
{
|
||||
// Configure subpass description
|
||||
auto& desc = node->spDescs[i];
|
||||
desc.pColorAttachments = subpass->colorReferences.data();
|
||||
desc.colorAttachmentCount = static_cast<uint32_t>(subpass->colorReferences.size());
|
||||
desc.pInputAttachments = subpass->inputReferences.data();
|
||||
desc.inputAttachmentCount = static_cast<uint32_t>(subpass->inputReferences.size());
|
||||
desc.pDepthStencilAttachment = subpass->depthReferences.data();
|
||||
desc.pipelineBindPoint = vk::PipelineBindPoint::eGraphics; // TODO: Just graphics for now. See if its possible to allow user defined params.
|
||||
|
||||
// Get reference to subpass description
|
||||
auto& dep = node->spDeps[i];
|
||||
|
||||
// Configure subpass index for dependencies
|
||||
dep.srcSubpass = (i == 0) ? VK_SUBPASS_EXTERNAL : i - 1;
|
||||
dep.dstSubpass = i;
|
||||
|
||||
// First we want to see if the subpass has color, depth or input attachments and set bit field accordingly
|
||||
if (subpass->colorReferences.size())
|
||||
{
|
||||
colorRead |= (1 << i);
|
||||
colorWrite |= (1 << i);
|
||||
}
|
||||
|
||||
// Same thing for depth
|
||||
if (subpass->depthReferences.size())
|
||||
{
|
||||
depthRead |= (1 << i);
|
||||
depthWrite |= (1 << i);
|
||||
}
|
||||
if (subpass->inputReferences.size())
|
||||
inputDependencies |= (1 << i);
|
||||
|
||||
// Input attachments can be any type, so we need to check what type it is
|
||||
for (auto& inputAtt : subpass->inputReferences)
|
||||
{
|
||||
auto resource = node->attResources[inputAtt.attachment];
|
||||
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT))
|
||||
{
|
||||
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_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL))
|
||||
depthRead |= (1 << i);
|
||||
}
|
||||
else
|
||||
{
|
||||
SHLOG_ERROR("While configuring subpass, an input reference was detected but the resource to be used is not marked as SH_ATT_DESC_TYPE_FLAGS::INPUT. ");
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
// Loop through all subpasses again but this time we use the bit field to initialize
|
||||
// the dependencies.
|
||||
for (i = 0; i < node->subpasses.size(); ++i)
|
||||
{
|
||||
vk::PipelineStageFlags srcStage;
|
||||
vk::PipelineStageFlags dstStage;
|
||||
vk::AccessFlags srcAccess;
|
||||
vk::AccessFlags dstAccess;
|
||||
auto& dep = node->spDeps[i];
|
||||
|
||||
if (colorRead & (1 << i))
|
||||
{
|
||||
srcStage |= vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
dstStage |= vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
srcAccess |= vk::AccessFlagBits::eColorAttachmentWrite;
|
||||
dstAccess |= vk::AccessFlagBits::eColorAttachmentRead;
|
||||
}
|
||||
if (colorWrite & (1 << i))
|
||||
{
|
||||
srcStage |= vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
dstStage |= vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
srcAccess |= vk::AccessFlagBits::eColorAttachmentWrite;
|
||||
dstAccess |= vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead;
|
||||
}
|
||||
if (depthRead & (1 << i))
|
||||
{
|
||||
srcStage |= vk::PipelineStageFlagBits::eEarlyFragmentTests;
|
||||
dstStage |= vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests;
|
||||
srcAccess |= vk::AccessFlagBits::eDepthStencilAttachmentWrite;
|
||||
dstAccess |= vk::AccessFlagBits::eDepthStencilAttachmentRead;
|
||||
}
|
||||
if (depthWrite & (1 << i))
|
||||
{
|
||||
srcStage |= vk::PipelineStageFlagBits::eEarlyFragmentTests;
|
||||
dstStage |= vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests;
|
||||
srcAccess |= vk::AccessFlagBits::eDepthStencilAttachmentWrite;
|
||||
dstAccess |= vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
|
||||
}
|
||||
if (inputDependencies & (1 << i))
|
||||
{
|
||||
dstStage |= vk::PipelineStageFlagBits::eFragmentShader;
|
||||
dstAccess |= vk::AccessFlagBits::eInputAttachmentRead;
|
||||
}
|
||||
|
||||
//// If subpass of first renderpass, stage flag should be bottom of pipe
|
||||
//if (&node == &nodes.front() && i == 0)
|
||||
// srcStage = vk::PipelineStageFlagBits::eBottomOfPipe;
|
||||
|
||||
//// If subpass of last renderpass, stage flag should be bottom of pipe
|
||||
//if (&node == &nodes.back() && i == node->subpasses.size() - 1)
|
||||
// dstStage = vk::PipelineStageFlagBits::eTopOfPipe;
|
||||
|
||||
dep.srcStageMask = srcStage;
|
||||
dep.dstStageMask = dstStage;
|
||||
dep.srcAccessMask = srcAccess;
|
||||
dep.dstAccessMask = dstAccess;
|
||||
|
||||
dep.srcStageMask = srcStage;
|
||||
|
||||
// initialize input descriptors
|
||||
node->subpasses[i]->CreateInputDescriptors();
|
||||
}
|
||||
node->ConfigureSubpasses();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,12 +526,17 @@ namespace SHADE
|
|||
{
|
||||
CheckForNodeComputes();
|
||||
ConfigureAttachmentDescriptions();
|
||||
ConfigureSubpasses();
|
||||
ConfigureAllSubpasses();
|
||||
ConfigureRenderpasses();
|
||||
ConfigureFramebuffers();
|
||||
ConfigureSubSystems();
|
||||
}
|
||||
|
||||
void SHRenderGraph::Regenerate(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace SHADE
|
|||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void ConfigureAttachmentDescriptions (void) noexcept;
|
||||
void ConfigureSubpasses (void) noexcept;
|
||||
void ConfigureAllSubpasses (void) noexcept;
|
||||
void ConfigureRenderpasses (void) noexcept;
|
||||
void ConfigureSubSystems (void) noexcept;
|
||||
void ConfigureFramebuffers (void) noexcept;
|
||||
|
@ -89,13 +89,52 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (std::string graphName, Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain, SHResourceHub* resourceHub, std::vector<Handle<SHVkCommandPool>>& cmdPools) 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 AddRenderToSwapchainNode (std::string toSwapchainResource, std::string swapchainResource, std::initializer_list<std::string> predecessorNodes, std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> shaderModules) noexcept;
|
||||
void Init
|
||||
(
|
||||
std::string graphName,
|
||||
Handle<SHVkLogicalDevice> logicalDevice,
|
||||
Handle<SHVkSwapchain> swapchain, SHResourceHub* resourceHub,
|
||||
std::vector<Handle<SHVkCommandPool>>& cmdPools
|
||||
) 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 RemoveResource (std::string resourceName) noexcept;
|
||||
|
||||
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 AddRenderToSwapchainNode
|
||||
(
|
||||
std::string toSwapchainResource,
|
||||
std::string swapchainResource,
|
||||
std::initializer_list<std::string> predecessorNodes,
|
||||
std::pair<Handle<SHVkShaderModule>,
|
||||
Handle<SHVkShaderModule>> shaderModules
|
||||
) noexcept;
|
||||
|
||||
void Generate (void) noexcept;
|
||||
void Regenerate (void) noexcept;
|
||||
void CheckForNodeComputes (void) noexcept;
|
||||
void Execute (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void Begin (uint32_t frameIndex) noexcept;
|
||||
|
|
|
@ -26,6 +26,12 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateRenderpass(void) noexcept
|
||||
{
|
||||
if (renderpass)
|
||||
{
|
||||
if (renderpass)
|
||||
renderpass.Free();
|
||||
}
|
||||
|
||||
renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eRenderPass, renderpass->GetVkRenderpass(), "[RenderPass] " + name);
|
||||
}
|
||||
|
@ -40,6 +46,15 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateFramebuffer(void) noexcept
|
||||
{
|
||||
if (!framebuffers.empty())
|
||||
{
|
||||
for (auto fbo : framebuffers)
|
||||
{
|
||||
if (fbo)
|
||||
fbo.Free();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||
{
|
||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||
|
@ -100,6 +115,139 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::ConfigureSubpasses(void) noexcept
|
||||
{
|
||||
// Create subpass description and dependencies based on number of subpasses
|
||||
spDescs.resize(subpasses.size());
|
||||
spDeps.resize(subpasses.size());
|
||||
|
||||
// Now we want to loop through all attachments in all subpasses in the node and query
|
||||
// the resources being used. For each resource we want to query the type and record it
|
||||
// in bit fields (1 bit for each subpass).
|
||||
uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
// For all subpasses (see above description about bit field for this).
|
||||
for (auto& subpass : subpasses)
|
||||
{
|
||||
// Configure subpass description
|
||||
auto& desc = spDescs[i];
|
||||
desc.pColorAttachments = subpass->colorReferences.data();
|
||||
desc.colorAttachmentCount = static_cast<uint32_t>(subpass->colorReferences.size());
|
||||
desc.pInputAttachments = subpass->inputReferences.data();
|
||||
desc.inputAttachmentCount = static_cast<uint32_t>(subpass->inputReferences.size());
|
||||
desc.pDepthStencilAttachment = subpass->depthReferences.data();
|
||||
desc.pipelineBindPoint = vk::PipelineBindPoint::eGraphics; // TODO: Just graphics for now. See if its possible to allow user defined params.
|
||||
|
||||
// Get reference to subpass description
|
||||
auto& dep = spDeps[i];
|
||||
|
||||
// Configure subpass index for dependencies
|
||||
dep.srcSubpass = (i == 0) ? VK_SUBPASS_EXTERNAL : i - 1;
|
||||
dep.dstSubpass = i;
|
||||
|
||||
// First we want to see if the subpass has color, depth or input attachments and set bit field accordingly
|
||||
if (subpass->colorReferences.size())
|
||||
{
|
||||
colorRead |= (1 << i);
|
||||
colorWrite |= (1 << i);
|
||||
}
|
||||
|
||||
// Same thing for depth
|
||||
if (subpass->depthReferences.size())
|
||||
{
|
||||
depthRead |= (1 << i);
|
||||
depthWrite |= (1 << i);
|
||||
}
|
||||
if (subpass->inputReferences.size())
|
||||
inputDependencies |= (1 << i);
|
||||
|
||||
// Input attachments can be any type, so we need to check what type it is
|
||||
for (auto& inputAtt : subpass->inputReferences)
|
||||
{
|
||||
auto resource = attResources[inputAtt.attachment];
|
||||
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT))
|
||||
{
|
||||
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_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL))
|
||||
depthRead |= (1 << i);
|
||||
}
|
||||
else
|
||||
{
|
||||
SHLOG_ERROR("While configuring subpass, an input reference was detected but the resource to be used is not marked as SH_ATT_DESC_TYPE_FLAGS::INPUT. ");
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
// Loop through all subpasses again but this time we use the bit field to initialize
|
||||
// the dependencies.
|
||||
for (i = 0; i < subpasses.size(); ++i)
|
||||
{
|
||||
vk::PipelineStageFlags srcStage;
|
||||
vk::PipelineStageFlags dstStage;
|
||||
vk::AccessFlags srcAccess;
|
||||
vk::AccessFlags dstAccess;
|
||||
auto& dep = spDeps[i];
|
||||
|
||||
if (colorRead & (1 << i))
|
||||
{
|
||||
srcStage |= vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
dstStage |= vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
srcAccess |= vk::AccessFlagBits::eColorAttachmentWrite;
|
||||
dstAccess |= vk::AccessFlagBits::eColorAttachmentRead;
|
||||
}
|
||||
if (colorWrite & (1 << i))
|
||||
{
|
||||
srcStage |= vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
dstStage |= vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
srcAccess |= vk::AccessFlagBits::eColorAttachmentWrite;
|
||||
dstAccess |= vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead;
|
||||
}
|
||||
if (depthRead & (1 << i))
|
||||
{
|
||||
srcStage |= vk::PipelineStageFlagBits::eEarlyFragmentTests;
|
||||
dstStage |= vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests;
|
||||
srcAccess |= vk::AccessFlagBits::eDepthStencilAttachmentWrite;
|
||||
dstAccess |= vk::AccessFlagBits::eDepthStencilAttachmentRead;
|
||||
}
|
||||
if (depthWrite & (1 << i))
|
||||
{
|
||||
srcStage |= vk::PipelineStageFlagBits::eEarlyFragmentTests;
|
||||
dstStage |= vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests;
|
||||
srcAccess |= vk::AccessFlagBits::eDepthStencilAttachmentWrite;
|
||||
dstAccess |= vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
|
||||
}
|
||||
if (inputDependencies & (1 << i))
|
||||
{
|
||||
dstStage |= vk::PipelineStageFlagBits::eFragmentShader;
|
||||
dstAccess |= vk::AccessFlagBits::eInputAttachmentRead;
|
||||
}
|
||||
|
||||
//// If subpass of first renderpass, stage flag should be bottom of pipe
|
||||
//if (&node == &nodes.front() && i == 0)
|
||||
// srcStage = vk::PipelineStageFlagBits::eBottomOfPipe;
|
||||
|
||||
//// If subpass of last renderpass, stage flag should be bottom of pipe
|
||||
//if (&node == &nodes.back() && i == subpasses.size() - 1)
|
||||
// dstStage = vk::PipelineStageFlagBits::eTopOfPipe;
|
||||
|
||||
dep.srcStageMask = srcStage;
|
||||
dep.dstStageMask = dstStage;
|
||||
dep.srcAccessMask = srcAccess;
|
||||
dep.dstAccessMask = dstAccess;
|
||||
|
||||
dep.srcStageMask = srcStage;
|
||||
|
||||
// initialize input descriptors
|
||||
subpasses[i]->CreateInputDescriptors();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -335,6 +483,58 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
For detaching attachments from the node. The node would need to be
|
||||
rebuilt but it won't be done in this function. This function just removes
|
||||
any footprint of the resource in the class.
|
||||
|
||||
\param resourceHandleID
|
||||
The handle ID of the resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
bool SHRenderGraphNode::DetachResource(std::string const& resourceName, uint64_t resourceHandleID) noexcept
|
||||
{
|
||||
if (resourceAttachmentMapping->contains(resourceHandleID))
|
||||
{
|
||||
// Get attachment index in the node's attachment container
|
||||
auto index = resourceAttachmentMapping->at(resourceHandleID);
|
||||
|
||||
// remove attachment from the list of attachments
|
||||
attResources.erase (attResources.begin() + index);
|
||||
|
||||
// remove attachment reference
|
||||
attachmentDescriptions.erase (attachmentDescriptions.begin() + index);
|
||||
|
||||
// Remove footprint of attachment from all subpasses as well
|
||||
for (auto it = subpasses.begin(); it != subpasses.end(); ++it)
|
||||
{
|
||||
// attempt to detach resource from subpass
|
||||
(*it)->DetachResource(resourceName, index);
|
||||
|
||||
// If the subpass ends up having no attachments after, erase it from the node
|
||||
if ((*it)->HasNoAttachments())
|
||||
{
|
||||
// erase from indexing
|
||||
subpassIndexing.erase((*it)->GetName());
|
||||
|
||||
// erase from container of subpasses.
|
||||
it = subpasses.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// give existing subpasses new indices
|
||||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||
subpasses[i]->SetIndex(i);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||
{
|
||||
uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace SHADE
|
|||
//! Vector of subpasses
|
||||
std::vector<Handle<SHSubpass>> subpasses;
|
||||
|
||||
//! Descriptions to pass to renderpass for renderpass creation. We want to keep this here because
|
||||
//! Descriptions to pass to renderpass for renderpass creation.
|
||||
std::vector<vk::SubpassDescription> spDescs;
|
||||
|
||||
//! Subpass dependencies for renderpass creation
|
||||
|
@ -92,6 +92,7 @@ namespace SHADE
|
|||
void CreateRenderpass(void) noexcept;
|
||||
void CreateFramebuffer(void) noexcept;
|
||||
void HandleResize (void) noexcept;
|
||||
void ConfigureSubpasses (void) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -107,6 +108,7 @@ namespace SHADE
|
|||
Handle<SHSubpass> AddSubpass(std::string subpassName, Handle<SHViewport> viewport, Handle<SHRenderer> renderer) noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings = {}, float numWorkGroupScale = 1.0f) noexcept;
|
||||
void AddDummySubpassIfNeeded (void) noexcept;
|
||||
bool DetachResource (std::string const& resourceName, uint64_t resourceHandleID) noexcept;
|
||||
|
||||
// TODO: RemoveSubpass()
|
||||
void Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
|
|
|
@ -68,7 +68,6 @@ namespace SHADE
|
|||
, depthReferences{ std::move(rhs.depthReferences) }
|
||||
, inputReferences{ std::move(rhs.inputReferences) }
|
||||
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
|
||||
, descriptorSetLayout{ rhs.descriptorSetLayout }
|
||||
, exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) }
|
||||
, graphStorage{ rhs.graphStorage }
|
||||
, inputNames{ std::move(rhs.inputNames) }
|
||||
|
@ -105,7 +104,6 @@ namespace SHADE
|
|||
depthReferences = std::move(rhs.depthReferences);
|
||||
inputReferences = std::move(rhs.inputReferences);
|
||||
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
|
||||
descriptorSetLayout = rhs.descriptorSetLayout;
|
||||
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
|
||||
graphStorage = rhs.graphStorage;
|
||||
inputNames = std::move(rhs.inputNames);
|
||||
|
@ -253,6 +251,64 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Removes all footprints of a resource in the subpass.
|
||||
|
||||
\param resourceName
|
||||
Name of resource.
|
||||
|
||||
\param attachmentIndex
|
||||
index of attachment.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHSubpass::DetachResource(std::string const& resourceName, uint32_t attachmentIndex) noexcept
|
||||
{
|
||||
for (uint32_t i = 0; i < colorReferences.size(); ++i)
|
||||
{
|
||||
if (colorReferences[i].attachment == attachmentIndex)
|
||||
{
|
||||
colorReferences.erase (colorReferences.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < depthReferences.size(); ++i)
|
||||
{
|
||||
if (depthReferences[i].attachment == attachmentIndex)
|
||||
{
|
||||
depthReferences.erase(depthReferences.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < inputReferences.size(); ++i)
|
||||
{
|
||||
if (inputReferences[i].attachment == attachmentIndex)
|
||||
{
|
||||
inputReferences.erase(inputReferences.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < inputNames.size(); ++i)
|
||||
{
|
||||
if (inputNames[i] == resourceName)
|
||||
{
|
||||
inputNames.erase(inputNames.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SHSubpass::HasNoAttachments(void) const noexcept
|
||||
{
|
||||
return colorReferences.empty() && depthReferences.empty() && inputReferences.empty();
|
||||
}
|
||||
|
||||
void SHSubpass::AddExteriorDrawCalls(ExteriorDrawCallFunction const& newDrawCall) noexcept
|
||||
{
|
||||
exteriorDrawCalls.push_back(newDrawCall);
|
||||
|
@ -269,6 +325,21 @@ namespace SHADE
|
|||
if (inputNames.empty())
|
||||
return;
|
||||
|
||||
for (auto& set : inputImageDescriptorSets)
|
||||
{
|
||||
if (set)
|
||||
set.Free();
|
||||
}
|
||||
|
||||
if (inputDescriptorLayout)
|
||||
inputDescriptorLayout.Free();
|
||||
|
||||
for (auto& sampler : inputSamplers)
|
||||
{
|
||||
if (sampler)
|
||||
sampler.Free();
|
||||
}
|
||||
|
||||
inputImageDescriptorSets.resize(SHGraphicsConstants::NUM_FRAME_BUFFERS);
|
||||
|
||||
std::vector<SHVkDescriptorSetLayout::Binding> bindings{};
|
||||
|
@ -369,58 +440,23 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
//void SHSubpass::InitComputeBarriers(void) noexcept
|
||||
//{
|
||||
// std::unordered_set <uint64_t> handleBarriers{};
|
||||
|
||||
// // we will have swapchainNumImages vectors of vector of barriers
|
||||
// subpassComputeBarriers.resize(graphStorage->swapchain->GetNumImages());
|
||||
|
||||
// for (auto sbCompute : subpassComputes)
|
||||
// {
|
||||
// // for every resource the subpass compute is using
|
||||
// for (auto resource : sbCompute->resources)
|
||||
// {
|
||||
// // Get the resource handle
|
||||
// uint64_t resourceRaw = resource.GetId().Raw;
|
||||
|
||||
// // if the barrier is not registered
|
||||
// if (!handleBarriers.contains(resourceRaw))
|
||||
// {
|
||||
// // If the resource is a swapchain image
|
||||
// bool isSwapchainImage = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT));
|
||||
// for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
|
||||
// {
|
||||
// // if swapchain image, we want the index of the swapchain image, if not take base image
|
||||
// uint32_t imageIndex = isSwapchainImage ? i : 0;
|
||||
|
||||
// // Prepare image barrier
|
||||
// vk::ImageMemoryBarrier imageBarrier
|
||||
// {
|
||||
// .oldLayout = colorReferences[resourceAttachmentMapping->at(resource.GetId().Raw)].layout,
|
||||
// .newLayout = vk::ImageLayout::eGeneral,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = resource->GetImage(imageIndex)->GetVkImage(),
|
||||
// .subresourceRange =
|
||||
// {
|
||||
// .aspectMask = resource->imageAspectFlags,
|
||||
// .levelCount = resource->GetMipLevels(),
|
||||
// .baseArrayLayer = 0,
|
||||
// .layerCount = 1
|
||||
// }
|
||||
// };
|
||||
|
||||
// // push the barrier
|
||||
// subpassComputeBarriers[i].push_back(imageBarrier);
|
||||
// }
|
||||
|
||||
// // Image transition registered
|
||||
// handleBarriers.emplace(resourceRaw);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
This function is mainly used for the purposes of giving a subpass a new
|
||||
index in the case another subpass in the node gets deleted, and subpasses
|
||||
need to be re-indexed.
|
||||
|
||||
\param index
|
||||
New index of the subpass.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHSubpass::SetIndex(uint32_t index) noexcept
|
||||
{
|
||||
subpassIndex = index;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
|
|
@ -50,9 +50,6 @@ namespace SHADE
|
|||
//!
|
||||
Handle<SHSuperBatch> superBatch;
|
||||
|
||||
//! Descriptor set layout to hold attachments
|
||||
Handle<SHVkDescriptorSetLayout> descriptorSetLayout;
|
||||
|
||||
//! Color attachments
|
||||
std::vector<vk::AttachmentReference> colorReferences;
|
||||
|
||||
|
@ -122,6 +119,8 @@ namespace SHADE
|
|||
void Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
void HandleResize (void) noexcept;
|
||||
void BindInputDescriptorSets (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) const noexcept;
|
||||
void DetachResource (std::string const& resourceName, uint32_t attachmentIndex) noexcept;
|
||||
bool HasNoAttachments (void) const noexcept;
|
||||
|
||||
void Init(SHResourceHub& resourceManager) noexcept;
|
||||
|
||||
|
@ -132,6 +131,10 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* GETTERS AND SETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
private:
|
||||
void SetIndex (uint32_t index) noexcept;
|
||||
|
||||
public:
|
||||
Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept;
|
||||
SHSubPassIndex GetIndex() const noexcept;
|
||||
Handle<SHSuperBatch> GetSuperBatch(void) const noexcept;
|
||||
|
|
Loading…
Reference in New Issue