From 3e01c9e80a18870ddb1411aeae13396a7c5753f0 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Sat, 7 Jan 2023 12:01:09 +0800 Subject: [PATCH] shadows WIP --- .../GlobalData/SHGraphicsPredefinedData.cpp | 14 +++- .../GlobalData/SHGraphicsPredefinedData.h | 6 +- .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 33 +++++---- .../MiddleEnd/Pipeline/SHPipelineLibrary.cpp | 5 +- .../MiddleEnd/Pipeline/SHPipelineLibrary.h | 4 +- .../src/Graphics/Pipeline/SHPipelineState.cpp | 7 +- .../src/Graphics/Pipeline/SHPipelineState.h | 2 +- .../Graphics/RenderGraph/SHRenderGraph.cpp | 70 +++++++++++++++++++ .../src/Graphics/RenderGraph/SHRenderGraph.h | 7 ++ .../RenderGraph/SHRenderGraphNode.cpp | 1 + .../src/Graphics/RenderGraph/SHSubpass.cpp | 3 + 11 files changed, 126 insertions(+), 26 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp index d09ec5b4..4082ba0f 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp @@ -13,6 +13,8 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ std::vector> SHGraphicsPredefinedData::predefinedLayouts; SHVertexInputState SHGraphicsPredefinedData::defaultVertexInputState; + SHVertexInputState SHGraphicsPredefinedData::shadowMapVertexInputState; + std::vector SHGraphicsPredefinedData::perSystemData; //SHGraphicsPredefinedData::PerSystem SHGraphicsPredefinedData::batchingSystemData; @@ -193,7 +195,7 @@ namespace SHADE ); } - void SHGraphicsPredefinedData::InitDefaultVertexInputState(void) noexcept + void SHGraphicsPredefinedData::InitPredefinedVertexInputState(void) noexcept { defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // positions at binding 0 defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_2D) }); // UVs at binding 1 @@ -201,13 +203,16 @@ namespace SHADE defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3 defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots) defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8 + + shadowMapVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D)}); + shadowMapVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }, 4); // Transform at binding 4 - 7 (4 slots) } void SHGraphicsPredefinedData::Init(Handle logicalDevice) noexcept { perSystemData.resize(SHUtilities::ConvertEnum(SystemType::NUM_TYPES)); InitDescSetLayouts(logicalDevice); - InitDefaultVertexInputState(); + InitPredefinedVertexInputState(); InitDescMappings(); InitDummyPipelineLayouts (logicalDevice); } @@ -231,6 +236,11 @@ namespace SHADE } + SHVertexInputState const& SHGraphicsPredefinedData::GetShadowMapViState(void) noexcept + { + return shadowMapVertexInputState; + } + SHGraphicsPredefinedData::PerSystem const& SHGraphicsPredefinedData::GetSystemData(SystemType systemType) noexcept { return perSystemData[static_cast(systemType)]; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h index b4004d5a..9331ed01 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h @@ -58,6 +58,9 @@ namespace SHADE //! Default vertex input state (used by everything). static SHVertexInputState defaultVertexInputState; + //! vertex input state for shadow mapping + static SHVertexInputState shadowMapVertexInputState; + //! Predefined data for each type of system static std::vector perSystemData; @@ -73,7 +76,7 @@ namespace SHADE static void InitDescMappings (void) noexcept; static void InitDummyPipelineLayouts (Handle logicalDevice) noexcept; static void InitDescSetLayouts (Handle logicalDevice) noexcept; - static void InitDefaultVertexInputState (void) noexcept; + static void InitPredefinedVertexInputState (void) noexcept; public: /*-----------------------------------------------------------------------*/ @@ -91,6 +94,7 @@ namespace SHADE /*-----------------------------------------------------------------------*/ static std::vector> GetPredefinedDescSetLayouts (SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes types) noexcept; static SHVertexInputState const& GetDefaultViState (void) noexcept; + static SHVertexInputState const& GetShadowMapViState (void) noexcept; static PerSystem const& GetSystemData (SystemType systemType) noexcept; static SHDescriptorMappings::MapType const& GetMappings (SystemType systemType) noexcept; //static PerSystem const& GetBatchingSystemData(void) noexcept; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index ec592522..e682e0a1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -267,7 +267,7 @@ namespace SHADE /*-----------------------------------------------------------------------*/ // 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 shadowMapPassNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphNodeNames::SHADOW_MAP_PASS.data(), {}, {}); + //auto shadowMapPassNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphNodeNames::SHADOW_MAP_PASS.data(), {}, {}); /*-----------------------------------------------------------------------*/ /* DEFERRED COMPOSITE NODE */ @@ -760,16 +760,6 @@ namespace SHADE auto* lightComp = SHComponentManager::GetComponent(EVENT_DATA->lightEntity); std::string resourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity); Handle companionSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphNodeNames::GBUFFER_PASS.data())->GetSubpass("G-Buffer Write"); - - if (!shadowMapPipeline) - { - SHPipelineLibrary tempLibrary{}; - Handle rgNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphNodeNames::SHADOW_MAP_PASS.data()); - - tempLibrary.Init(device); - tempLibrary.CreateGraphicsPipelines({ shadowMapVS, {} }, rgNode->GetRenderpass(), companionSubpass); - shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, {} }); - } if (EVENT_DATA->generateRenderer) { @@ -782,16 +772,29 @@ namespace SHADE renderGraph->AddResource(resourceName, {SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT}, resizeWidth, resizeHeight, vk::Format::eD24UnormS8Uint); // link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer. - auto shadowMapNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphNodeNames::SHADOW_MAP_PASS.data()); - shadowMapNode->RuntimeLinkResource(resourceName); + //auto shadowMapNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphNodeNames::SHADOW_MAP_PASS.data()); + auto shadowMapNode = renderGraph->AddNodeAfter(SHGraphicsConstants::RenderGraphNodeNames::SHADOW_MAP_PASS.data() + resourceName, {resourceName.c_str()}, SHGraphicsConstants::RenderGraphNodeNames::GBUFFER_PASS.data()); // Add a subpass to render to that shadow map - auto newSubpass = shadowMapNode->RuntimeAddSubpass(resourceName + " Subpass", worldViewport, lightComp->GetRenderer()); + auto newSubpass = shadowMapNode->RuntimeAddSubpass(resourceName + " Subpass", worldViewport, worldRenderer); + //auto newSubpass = shadowMapNode->RuntimeAddSubpass(resourceName + " Subpass", worldViewport, lightComp->GetRenderer()); newSubpass->AddDepthOutput(resourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL); - newSubpass->SetCompanionSubpass(companionSubpass, shadowMapPipeline); // set companion subpass and pipeline // regenerate the node shadowMapNode->RuntimeStandaloneRegenerate(); + + + // Create pipeline from new renderpass and subpass if it's not created yet + if (!shadowMapPipeline) + { + SHPipelineLibrary tempLibrary{}; + Handle rgNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphNodeNames::SHADOW_MAP_PASS.data()); + + tempLibrary.Init(device); + tempLibrary.CreateGraphicsPipelines({ shadowMapVS, {} }, shadowMapNode->GetRenderpass(), newSubpass, SHGraphicsPredefinedData::GetShadowMapViState()); + shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, {} }); + } + newSubpass->SetCompanionSubpass(companionSubpass, shadowMapPipeline); // set companion subpass and pipeline return eventPtr->handle; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp index daa4d154..6d7e6104 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp @@ -1,14 +1,13 @@ #include "SHpch.h" #include "SHPipelineLibrary.h" #include "Graphics/Devices/SHVkLogicalDevice.h" -#include "Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h" #include "Graphics/RenderGraph/SHSubpass.h" #include "Graphics/SHVkUtil.h" namespace SHADE { - Handle SHPipelineLibrary::CreateGraphicsPipelines(std::pair, Handle> const& vsFsPair, Handle renderpass, Handle subpass) noexcept + Handle SHPipelineLibrary::CreateGraphicsPipelines(std::pair, Handle> const& vsFsPair, Handle renderpass, Handle subpass, SHVertexInputState const& viState/* = SHGraphicsPredefinedData::GetDefaultViState()*/) noexcept { std::vector> modules{}; if (vsFsPair.first) @@ -27,7 +26,7 @@ namespace SHADE // Create the pipeline and configure the default vertex input state auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass); - newPipeline->GetPipelineState().SetVertexInputState(SHGraphicsPredefinedData::GetDefaultViState()); + newPipeline->GetPipelineState().SetVertexInputState(viState); SHColorBlendState colorBlendState{}; colorBlendState.logic_op_enable = VK_FALSE; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h index 5085f21f..b7485e50 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h @@ -3,6 +3,7 @@ #include #include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Pipeline/SHVkPipeline.h" +#include "Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h" namespace SHADE { @@ -32,7 +33,8 @@ namespace SHADE Handle CreateGraphicsPipelines ( std::pair, Handle> const& vsFsPair, Handle renderpass, - Handle subpass + Handle subpass, + SHVertexInputState const& viState = SHGraphicsPredefinedData::GetDefaultViState() ) noexcept; Handle GetGraphicsPipeline (std::pair, Handle> const& vsFsPair) noexcept; bool CheckGraphicsPipelineExistence (std::pair, Handle> const& vsFsPair) noexcept; diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp index c7ada11f..49fa9086 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp @@ -195,7 +195,7 @@ namespace SHADE return *this; } - void SHVertexInputState::AddBinding(bool instanced, bool calcOffset, std::initializer_list inAttribs) noexcept + void SHVertexInputState::AddBinding(bool instanced, bool calcOffset, std::initializer_list inAttribs, uint32_t fixedAttributeLocation/* = static_cast(-1)*/) noexcept { // add a binding and get ref to it bindings.emplace_back(); @@ -228,8 +228,9 @@ namespace SHADE // The binding for that attribute description is index of the new binding created earlier in this function vertexAttrib.binding = static_cast(bindings.size() - 1); - // Attribute location. New index is simply + 1 of the previous. Starts from 0 obviously - vertexAttrib.location = static_cast(attributes.size () - 1); + //Attribute location. New index is simply + 1 of the previous. Starts from 0 obviously + vertexAttrib.location = (fixedAttributeLocation != static_cast(-1)) ? fixedAttributeLocation + i : static_cast(attributes.size () - 1); + //vertexAttrib.location = static_cast(attributes.size() - 1); // Get the vkFormat associated with the SHAttribFormat vertexAttrib.format = format; diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h index 4c8d679a..380c726e 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h @@ -34,7 +34,7 @@ namespace SHADE SHVertexInputState& operator= (SHVertexInputState const& rhs) noexcept; SHVertexInputState& operator= (SHVertexInputState&& rhs) noexcept; - void AddBinding(bool instanced, bool calcOffset, std::initializer_list inAttribs) noexcept; + void AddBinding(bool instanced, bool calcOffset, std::initializer_list inAttribs, uint32_t fixedAttributeLocation = static_cast(-1)) noexcept; friend class SHVkPipelineState; friend class SHVkPipeline; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index e6b9ae33..5f8b8624 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -275,6 +275,17 @@ namespace SHADE } } + void SHRenderGraph::ReindexNodes(void) noexcept + { + nodeIndexing.clear(); + uint32_t i = 0; + for (auto& node : nodes) + { + nodeIndexing.emplace (node->name, i); + ++i; + } + } + /***************************************************************************/ /*! @@ -415,6 +426,65 @@ namespace SHADE return node; } + /***************************************************************************/ + /*! + + \brief + This function is purely used for dynamic nodes (if such a thing were to + exist in our architecture). In other words, don't use this function unless + the new node is fully standalone and does not rely or is a prereq of + other nodes. + + \param nodeName + Name of new node + + \param resourceInstruction + Resources for the node + + \param nodeToAddAfter + The node to add the new node after. + + \return + + */ + /***************************************************************************/ + Handle SHRenderGraph::AddNodeAfter(std::string nodeName, std::initializer_list resourceInstruction, std::string nodeToAddAfter) noexcept + { + if (nodeIndexing.contains(nodeName)) + { + SHLOG_ERROR("Node already exists, cannot add node. "); + return {}; + } + + std::vector descInitParams; + for (auto const& instruction : resourceInstruction) + { + // If the resource that the new node is requesting for exists, allow the graph to reference it + if (renderGraphStorage->graphResources->contains(instruction.resourceName)) + { + descInitParams.push_back( + { + .resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName), + .dontClearOnLoad = instruction.dontClearOnLoad, + } + ); + } + else + { + SHLOG_ERROR("Resource doesn't exist in graph yet. Cannot create new node."); + return{}; + } + } + + // get target node + auto targetNode = nodes.begin() + nodeIndexing.at(nodeToAddAfter); + + auto node = nodes.insert(targetNode, renderGraphStorage->resourceHub->Create(nodeName, renderGraphStorage, std::move(descInitParams), std::vector>())); + ReindexNodes (); + return *node; + + } + void SHRenderGraph::AddRenderToSwapchainNode(std::string toSwapchainResource, std::string swapchainResource, std::initializer_list predecessorNodes, std::pair, Handle> shaderModules) noexcept { for (auto& node : predecessorNodes) diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index 6dbc4308..6ee181f8 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -55,6 +55,7 @@ namespace SHADE void ConfigureRenderpasses (void) noexcept; void ConfigureSubSystems (void) noexcept; void ConfigureFramebuffers (void) noexcept; + void ReindexNodes (void) noexcept; /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ @@ -123,6 +124,12 @@ namespace SHADE std::initializer_list resourceInstruction, std::initializer_list predecessorNodes ) noexcept; + Handle AddNodeAfter + ( + std::string nodeName, + std::initializer_list resourceInstruction, + std::string nodeToAddAfter + ) noexcept; void AddRenderToSwapchainNode ( diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index 2f498d5a..fca003aa 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -365,6 +365,7 @@ namespace SHADE , spDeps{ std::move(rhs.spDeps) } , nodeComputes{ std::move(rhs.nodeComputes) } , name { std::move(rhs.name) } + , ISelfHandle{std::move(rhs)} { rhs.renderpass = {}; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index e1277953..c4d645db 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -77,6 +77,7 @@ namespace SHADE , name { rhs.name } , viewport {rhs.viewport} , renderer {rhs.renderer} + , companionSubpass {rhs.companionSubpass} { } @@ -113,6 +114,7 @@ namespace SHADE name = std::move(rhs.name); renderer = rhs.renderer; viewport = rhs.viewport; + companionSubpass = rhs.companionSubpass; return *this; @@ -237,6 +239,7 @@ namespace SHADE } else { + // if not bind pipeline for companion and and execute draw command commandBuffer->BindPipeline(companionSubpass.pipeline); companionSubpass.companion->superBatch->Draw(commandBuffer, frameIndex, false); }