Implemented Shadow maps (still needs improvement) #314

Merged
Xenosas1337 merged 22 commits from SP3-1-Rendering into main 2023-01-16 15:40:30 +08:00
8 changed files with 241 additions and 195 deletions
Showing only changes of commit 03becd8e47 - Show all commits

View File

@ -259,9 +259,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 shadowMapPass = renderGraph->AddNode("Shadow Map Pass", {}, {});
auto shadowMapPass = renderGraph->AddNode("Shadow Map Pass", {}, {});
/*-----------------------------------------------------------------------*/
/* DEFERRED COMPOSITE NODE */
@ -450,6 +448,7 @@ namespace SHADE
InitMiddleEnd();
InitSubsystems();
InitBuiltInResources();
InitEvents();
}
void SHGraphicsSystem::Exit(void)

View File

@ -106,6 +106,9 @@ namespace SHADE
for (auto& affectedNode : affectedNodes)
nodes[affectedNode]->CreateFramebuffer();
renderGraphStorage->graphResources->at(resourceName).Free();
renderGraphStorage->graphResources->erase (resourceName);
/*
* IMPORTANT NOTES
*
@ -168,12 +171,8 @@ namespace SHADE
{
// key is handle ID, value is final layout.
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
if (node->subpasses.empty())
if (!node->subpasses.empty())
{
SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
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)
@ -218,7 +217,7 @@ namespace SHADE
if (resource->resourceTypeFlags & SHUtilities::ConvertEnum(SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED) &&
renderGraphStorage->nonOwningResourceInitialLayouts.contains(resource.GetId().Raw))
{
att.initialLayout = renderGraphStorage->nonOwningResourceInitialLayouts.at (resource.GetId().Raw);
att.initialLayout = renderGraphStorage->nonOwningResourceInitialLayouts.at(resource.GetId().Raw);
att.loadOp = vk::AttachmentLoadOp::eLoad;
att.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
}
@ -228,6 +227,7 @@ namespace SHADE
att.finalLayout = resourceAttFinalLayouts[j];
resource->GetInfoTracker()->TrackLayout(node, {}, att.finalLayout);
}
}
++i;
}
@ -532,10 +532,6 @@ namespace SHADE
ConfigureSubSystems();
}
void SHRenderGraph::Regenerate(void) noexcept
{
}
/***************************************************************************/
/*!
@ -571,12 +567,15 @@ namespace SHADE
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
for (auto& node : nodes)
{
if (node->renderpass)
{
// bind static global data
SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
node->Execute(cmdBuffer, descPool, frameIndex);
}
}
cmdBuffer->EndLabeledSegment();
}

View File

@ -134,7 +134,6 @@ namespace SHADE
) 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;

View File

@ -32,9 +32,12 @@ namespace SHADE
renderpass.Free();
}
if (!spDescs.empty())
{
renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eRenderPass, renderpass->GetVkRenderpass(), "[RenderPass] " + name);
}
}
/***************************************************************************/
/*!
@ -45,6 +48,8 @@ namespace SHADE
*/
/***************************************************************************/
void SHRenderGraphNode::CreateFramebuffer(void) noexcept
{
if (renderpass)
{
if (!framebuffers.empty())
{
@ -78,8 +83,11 @@ namespace SHADE
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eFramebuffer, framebuffers[i]->GetVkFramebuffer(), "[Framebuffer] " + name + std::to_string(i));
}
}
}
void SHRenderGraphNode::HandleResize(void) noexcept
{
if (renderpass)
{
renderpass->HandleResize();
@ -114,9 +122,13 @@ namespace SHADE
nodeCompute->HandleResize();
}
}
}
void SHRenderGraphNode::ConfigureSubpasses(void) noexcept
{
if (subpasses.empty())
return;
// Create subpass description and dependencies based on number of subpasses
spDescs.resize(subpasses.size());
spDeps.resize(subpasses.size());
@ -512,11 +524,8 @@ namespace SHADE
// 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())
// If the subpass uses the resource, just remove the subpass since the subpass will be invalid
if ((*it)->UsesResource(index))
{
// erase from indexing
subpassIndexing.erase((*it)->GetName());
@ -530,12 +539,32 @@ namespace SHADE
for (uint32_t i = 0; i < subpasses.size(); ++i)
subpasses[i]->SetIndex(i);
// remove node computes using the resource
for (auto it = nodeComputes.begin(); it != nodeComputes.end(); ++it)
{
if ((*it)->UsesResource(resourceHandleID))
{
it = nodeComputes.erase(it);
}
}
// recompute the barriers for the other computes
for (auto it = nodeComputes.begin(); it != nodeComputes.end(); ++it)
{
if (it == nodeComputes.begin())
(*it)->SetFollowingEndRenderpass(true);
(*it)->InitializeBarriers();
}
return true;
}
return false;
}
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
{
if (renderpass)
{
uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
@ -569,6 +598,7 @@ namespace SHADE
for (auto& sbCompute : nodeComputes)
sbCompute->Execute(commandBuffer, frameIndex);
}
}
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
{

View File

@ -14,6 +14,54 @@
namespace SHADE
{
bool SHRenderGraphNodeCompute::UsesResource(uint64_t resourceHandleID) const noexcept
{
for (auto& resource : resources)
{
if (resource.GetId().Raw == resourceHandleID)
return true;
}
return false;
}
void SHRenderGraphNodeCompute::InitializeBarriers(void) noexcept
{
for (uint32_t i = 0; auto & barriers : memoryBarriers)
{
barriers.clear();
for (auto& resource : resources)
{
vk::AccessFlags srcAccessMask = (followingEndRenderpass) ? vk::AccessFlagBits::eInputAttachmentRead : (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite);
barriers.push_back(vk::ImageMemoryBarrier
{
.srcAccessMask = srcAccessMask,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.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,
.baseMipLevel = 0,
.levelCount = resource->mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
}
});
}
++i;
}
}
void SHRenderGraphNodeCompute::SetFollowingEndRenderpass(uint32_t flag) noexcept
{
followingEndRenderpass = flag;
}
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept
: computePipeline{}
, pipelineLayout{}
@ -157,35 +205,7 @@ namespace SHADE
groupSizeX = maxWidth / workGroupSizeX;
groupSizeY = maxHeight / workGroupSizeY;
for (uint32_t i = 0; auto& barriers : memoryBarriers)
{
barriers.clear();
for (auto& resource : resources)
{
vk::AccessFlags srcAccessMask = (followingEndRenderpass) ? vk::AccessFlagBits::eInputAttachmentRead : (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite);
barriers.push_back(vk::ImageMemoryBarrier
{
.srcAccessMask = srcAccessMask,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.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,
.baseMipLevel = 0,
.levelCount = resource->mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
}
});
}
++i;
}
InitializeBarriers();
}
void SHRenderGraphNodeCompute::SetDynamicOffsets(std::span<uint32_t> perFrameSizes) noexcept

View File

@ -73,6 +73,18 @@ namespace SHADE
//! Name of this node
std::string name;
private:
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
bool UsesResource (uint64_t resourceHandleID) const noexcept;
void InitializeBarriers (void) noexcept;
/*-----------------------------------------------------------------------*/
/* PRIVATE SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
void SetFollowingEndRenderpass (uint32_t flag) noexcept;
public:
SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept;

View File

@ -265,42 +265,24 @@ namespace SHADE
*/
/***************************************************************************/
void SHSubpass::DetachResource(std::string const& resourceName, uint32_t attachmentIndex) noexcept
bool SHSubpass::UsesResource(uint32_t attachmentIndex) noexcept
{
for (uint32_t i = 0; i < colorReferences.size(); ++i)
{
if (colorReferences[i].attachment == attachmentIndex)
{
colorReferences.erase (colorReferences.begin() + i);
break;
}
return true;
}
for (uint32_t i = 0; i < depthReferences.size(); ++i)
{
if (depthReferences[i].attachment == attachmentIndex)
{
depthReferences.erase(depthReferences.begin() + i);
break;
}
return true;
}
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;
}
return true;
}
}

View File

@ -95,6 +95,12 @@ namespace SHADE
std::string name;
private:
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
bool UsesResource(uint32_t attachmentIndex) noexcept;
public:
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
@ -119,7 +125,6 @@ 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;