Added editor functionality for lights to enable shadows
This commit is contained in:
parent
ff4c294313
commit
64e60a5114
|
@ -30,4 +30,5 @@ constexpr SHEventIdentifier SH_BUTTON_RELEASE_EVENT { 21 };
|
|||
constexpr SHEventIdentifier SH_BUTTON_HOVER_ENTER_EVENT { 22 };
|
||||
constexpr SHEventIdentifier SH_BUTTON_HOVER_EXIT_EVENT { 23 };
|
||||
constexpr SHEventIdentifier SH_ASSET_COMPILE_EVENT { 24 };
|
||||
constexpr SHEventIdentifier SH_LIGHT_DELETE_EVENT { 25 };
|
||||
|
||||
|
|
|
@ -6,13 +6,16 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHLightEnableShadowEvent
|
||||
struct SHLightShadowEvent
|
||||
{
|
||||
//! We need to get the light component and initialize the relevant variables.
|
||||
EntityID lightEntity;
|
||||
|
||||
//! Generate a renderer for the light component
|
||||
bool generateRenderer;
|
||||
bool firstEnable;
|
||||
|
||||
//! True when light is set enable shadow
|
||||
bool enableShadow;
|
||||
};
|
||||
|
||||
struct SHWindowResizeEvent
|
||||
|
@ -23,4 +26,10 @@ namespace SHADE
|
|||
// New height when window resizes
|
||||
uint32_t resizeHeight;
|
||||
};
|
||||
|
||||
struct SHDeleteLightEvent
|
||||
{
|
||||
//! Entity of the light we are deleting
|
||||
EntityID lightEntity;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -537,12 +537,21 @@ namespace SHADE
|
|||
ReceiverPtr lightEnableShadowReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightEnableShadowReceiver);
|
||||
SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, lightEnableShadowReceivePtr);
|
||||
|
||||
std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> lightDeleteEvent
|
||||
{
|
||||
std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveLightDeleteEvent)
|
||||
};
|
||||
ReceiverPtr lightDeleteReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightDeleteEvent);
|
||||
SHEventManager::SubscribeTo(SH_ASSET_COMPILE_EVENT, lightDeleteReceivePtr);
|
||||
|
||||
|
||||
std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> compileAssetReceiever
|
||||
{
|
||||
std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveCompileAssetEvent)
|
||||
};
|
||||
ReceiverPtr compileAssetReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(compileAssetReceiever);
|
||||
SHEventManager::SubscribeTo(SH_ASSET_COMPILE_EVENT, compileAssetReceivePtr);
|
||||
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::InitGenericDataAndTexturesDescSet(void) noexcept
|
||||
|
@ -846,10 +855,7 @@ namespace SHADE
|
|||
|
||||
SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr eventPtr) noexcept
|
||||
{
|
||||
// we need to wait for the device to finish using the graph first
|
||||
device->WaitIdle();
|
||||
|
||||
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightEnableShadowEvent>*>(eventPtr.get())->data;
|
||||
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightShadowEvent>*>(eventPtr.get())->data;
|
||||
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
|
||||
std::string depthResourceName = "ShadowMap_Depth " + std::to_string(EVENT_DATA->lightEntity);
|
||||
std::string shadowMapResourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
|
||||
|
@ -857,71 +863,112 @@ namespace SHADE
|
|||
Handle<SHSubpass> gBufferWriteSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS);
|
||||
Handle<SHSubpass> gBufferWriteVfxSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS);
|
||||
|
||||
if (EVENT_DATA->generateRenderer)
|
||||
if (EVENT_DATA->enableShadow)
|
||||
{
|
||||
// Create new renderer for the light component and give it to the light component
|
||||
Handle<SHRenderer> newRenderer = resourceManager.Create<SHRenderer>(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC);
|
||||
lightComp->SetRenderer (newRenderer);
|
||||
// When the light first enables shadow rendering, we need to prepare the relevant objects to render shadows; namely renderpasses and subpasses, pipelines and descriptor sets
|
||||
if (EVENT_DATA->firstEnable)
|
||||
{
|
||||
// we need to wait for the device to finish using the graph first
|
||||
device->WaitIdle();
|
||||
|
||||
// assign shadow map index to light component
|
||||
lightComp->SetShadowMapIndex (lightingSubSystem->GetNumShadowMaps());
|
||||
// Create new renderer for the light component and give it to the light component
|
||||
Handle<SHRenderer> newRenderer = resourceManager.Create<SHRenderer>(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC);
|
||||
lightComp->SetRenderer(newRenderer);
|
||||
|
||||
// assign shadow map index to light component
|
||||
lightComp->SetShadowMapIndex(lightingSubSystem->GetNumShadowMaps());
|
||||
|
||||
|
||||
// Add the shadow map resource to the graph
|
||||
renderGraph->AddResource(depthResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat);
|
||||
renderGraph->AddResource(shadowMapResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource(shadowMapBlurredResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat);
|
||||
|
||||
|
||||
|
||||
// link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer.
|
||||
auto shadowMapNode = renderGraph->AddNodeAfter(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, { depthResourceName.c_str(), shadowMapResourceName.c_str(), shadowMapBlurredResourceName.c_str() }, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data());
|
||||
|
||||
// Add a subpass to render to that shadow map
|
||||
auto shadowMapDrawSubpass = shadowMapNode->RuntimeAddSubpass(shadowMapResourceName + " Subpass", shadowMapViewport, lightComp->GetRenderer());
|
||||
shadowMapDrawSubpass->AddColorOutput(shadowMapResourceName);
|
||||
shadowMapDrawSubpass->AddDepthOutput(depthResourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH);
|
||||
|
||||
// add compute pass to blur shadow ma
|
||||
shadowMapNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, shadowMapBlurCS, { shadowMapResourceName.c_str(), shadowMapBlurredResourceName.c_str() });
|
||||
|
||||
// regenerate the node
|
||||
shadowMapNode->RuntimeStandaloneRegenerate();
|
||||
|
||||
// Create pipeline from new renderpass and subpass if it's not created yet
|
||||
if (!shadowMapPipeline)
|
||||
{
|
||||
SHPipelineLibrary tempLibrary{};
|
||||
Handle<SHRenderGraphNode> rgNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data());
|
||||
|
||||
SHRasterizationState rasterState{};
|
||||
rasterState.cull_mode = vk::CullModeFlagBits::eBack;
|
||||
|
||||
tempLibrary.Init(device);
|
||||
tempLibrary.CreateGraphicsPipelines
|
||||
(
|
||||
{ shadowMapVS, shadowMapFS }, shadowMapNode->GetRenderpass(), shadowMapDrawSubpass,
|
||||
SHGraphicsPredefinedData::SystemType::BATCHING,
|
||||
SHGraphicsPredefinedData::GetShadowMapViState(), rasterState
|
||||
);
|
||||
shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, shadowMapFS, shadowMapDrawSubpass });
|
||||
}
|
||||
shadowMapDrawSubpass->AddCompanionSubpass(gBufferWriteSubpass, shadowMapPipeline); // set companion subpass and pipeline
|
||||
shadowMapDrawSubpass->AddCompanionSubpass(gBufferWriteVfxSubpass, shadowMapPipeline); // set companion subpass and pipeline
|
||||
|
||||
// add the shadow map and the blurred version to the lighting system
|
||||
uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapBlurredResourceName), EVENT_DATA->lightEntity);
|
||||
|
||||
// Get deferred composite node compute and modify descriptor set
|
||||
auto nodeCompute = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data());
|
||||
nodeCompute->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, lightingSubSystem->GetViewSamplerLayout(NEW_SHADOW_MAP_INDEX), NEW_SHADOW_MAP_INDEX);
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the shadow map node
|
||||
renderGraph->GetNode (SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName)->SetDynamicActive(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the shadow map node
|
||||
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName)->SetDynamicActive(false);
|
||||
}
|
||||
|
||||
return eventPtr->handle;
|
||||
}
|
||||
|
||||
// Add the shadow map resource to the graph
|
||||
renderGraph->AddResource(depthResourceName, {SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH}, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat);
|
||||
renderGraph->AddResource(shadowMapResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource(shadowMapBlurredResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat);
|
||||
SHEventHandle SHGraphicsSystem::ReceiveLightDeleteEvent(SHEventPtr eventPtr) noexcept
|
||||
{
|
||||
// we need to wait for the device to finish using the graph first
|
||||
device->WaitIdle();
|
||||
|
||||
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightShadowEvent>*>(eventPtr.get())->data;
|
||||
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
|
||||
|
||||
|
||||
// link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer.
|
||||
auto shadowMapNode = renderGraph->AddNodeAfter(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, {depthResourceName.c_str(), shadowMapResourceName.c_str(), shadowMapBlurredResourceName.c_str()}, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data());
|
||||
|
||||
// Add a subpass to render to that shadow map
|
||||
auto shadowMapDrawSubpass = shadowMapNode->RuntimeAddSubpass(shadowMapResourceName + " Subpass", shadowMapViewport, lightComp->GetRenderer());
|
||||
shadowMapDrawSubpass->AddColorOutput(shadowMapResourceName);
|
||||
shadowMapDrawSubpass->AddDepthOutput(depthResourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH);
|
||||
|
||||
// add dummy subpass to transition the shadow map images for compute shader usage
|
||||
//auto dummySubpass = shadowMapNode->RuntimeAddSubpass(shadowMapResourceName + "Dummy", {}, {});
|
||||
//dummySubpass->AddGeneralColorOutput(shadowMapResourceName);
|
||||
//dummySubpass->AddGeneralColorOutput(shadowMapBlurredResourceName);
|
||||
|
||||
// add compute pass to blur shadow ma
|
||||
shadowMapNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, shadowMapBlurCS, { shadowMapResourceName.c_str(), shadowMapBlurredResourceName.c_str() });
|
||||
//shadowMapNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, shadowMapBlurCS, { shadowMapBlurredResourceName.c_str(), shadowMapResourceName.c_str() });
|
||||
//shadowMapNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, shadowMapBlurCS, { shadowMapResourceName.c_str(), shadowMapBlurredResourceName.c_str() });
|
||||
|
||||
// regenerate the node
|
||||
shadowMapNode->RuntimeStandaloneRegenerate();
|
||||
|
||||
// Create pipeline from new renderpass and subpass if it's not created yet
|
||||
if (!shadowMapPipeline)
|
||||
if (lightComp && lightComp->GetShadowMapIndex())
|
||||
{
|
||||
SHPipelineLibrary tempLibrary{};
|
||||
Handle<SHRenderGraphNode> rgNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data());
|
||||
std::string depthResourceName = "ShadowMap_Depth " + std::to_string(EVENT_DATA->lightEntity);
|
||||
std::string shadowMapResourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
|
||||
std::string shadowMapBlurredResourceName = "ShadowMap Blurred" + std::to_string(EVENT_DATA->lightEntity);
|
||||
|
||||
SHRasterizationState rasterState{};
|
||||
rasterState.cull_mode = vk::CullModeFlagBits::eBack;
|
||||
// Remove render graph node
|
||||
renderGraph->RemoveNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName);
|
||||
|
||||
tempLibrary.Init(device);
|
||||
tempLibrary.CreateGraphicsPipelines
|
||||
(
|
||||
{ shadowMapVS, shadowMapFS }, shadowMapNode->GetRenderpass(), shadowMapDrawSubpass,
|
||||
SHGraphicsPredefinedData::SystemType::BATCHING,
|
||||
SHGraphicsPredefinedData::GetShadowMapViState(), rasterState
|
||||
);
|
||||
shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, shadowMapFS, shadowMapDrawSubpass });
|
||||
// Remove render graph resource
|
||||
renderGraph->RemoveResource(depthResourceName);
|
||||
renderGraph->RemoveResource(shadowMapResourceName);
|
||||
renderGraph->RemoveResource(shadowMapBlurredResourceName);
|
||||
|
||||
// Register light component shadow map index into light system as recyclable
|
||||
lightingSubSystem->RemoveShadowMap (EVENT_DATA->lightEntity);
|
||||
}
|
||||
shadowMapDrawSubpass->AddCompanionSubpass(gBufferWriteSubpass, shadowMapPipeline); // set companion subpass and pipeline
|
||||
shadowMapDrawSubpass->AddCompanionSubpass(gBufferWriteVfxSubpass, shadowMapPipeline); // set companion subpass and pipeline
|
||||
|
||||
// add the shadow map and the blurred version to the lighting system
|
||||
uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapBlurredResourceName), EVENT_DATA->lightEntity);
|
||||
|
||||
auto nodeCompute = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data());
|
||||
nodeCompute->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, lightingSubSystem->GetViewSamplerLayout(NEW_SHADOW_MAP_INDEX), NEW_SHADOW_MAP_INDEX);
|
||||
|
||||
return eventPtr->handle;
|
||||
}
|
||||
|
|
|
@ -182,6 +182,7 @@ namespace SHADE
|
|||
/* Light functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr eventPtr) noexcept;
|
||||
SHEventHandle ReceiveLightDeleteEvent (SHEventPtr eventPtr) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Asset Events */
|
||||
|
|
|
@ -113,15 +113,21 @@ namespace SHADE
|
|||
lightData.castShadows = flag;
|
||||
|
||||
// If the flag is true
|
||||
if (flag && lightData.shadowMapIndex == SHLightData::INVALID_SHADOW_MAP_INDEX)
|
||||
if (flag)
|
||||
{
|
||||
// Create new event and broadcast it
|
||||
SHLightEnableShadowEvent newEvent;
|
||||
SHLightShadowEvent newEvent;
|
||||
newEvent.lightEntity = GetEID();
|
||||
newEvent.generateRenderer = static_cast<bool>(!renderer);
|
||||
|
||||
SHEventManager::BroadcastEvent<SHLightEnableShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT);
|
||||
// If shadow map index is invalid, that means light is enabling shadow for the first time.
|
||||
newEvent.firstEnable = (lightData.shadowMapIndex == SHLightData::INVALID_SHADOW_MAP_INDEX);
|
||||
|
||||
// pass the flag to the event
|
||||
newEvent.enableShadow = flag;
|
||||
|
||||
SHEventManager::BroadcastEvent<SHLightShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SHLightComponent::SetRenderer(Handle<SHRenderer> newRenderer) noexcept
|
||||
|
@ -195,6 +201,11 @@ namespace SHADE
|
|||
return lightData.castShadows;
|
||||
}
|
||||
|
||||
uint32_t SHLightComponent::GetShadowMapIndex(void) const noexcept
|
||||
{
|
||||
return lightData.shadowMapIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RTTR_REGISTRATION
|
||||
|
|
|
@ -70,6 +70,8 @@ namespace SHADE
|
|||
float GetStrength (void) const noexcept;
|
||||
Handle<SHRenderer> GetRenderer (void) const noexcept;
|
||||
bool GetEnableShadow (void) const noexcept;
|
||||
uint32_t GetShadowMapIndex (void) const noexcept;
|
||||
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -599,39 +599,15 @@ namespace SHADE
|
|||
{
|
||||
//Bind descriptor set(We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data).
|
||||
cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::COMPUTE, setIndex, { dynamicOffsets[frameIndex] });
|
||||
|
||||
}
|
||||
|
||||
uint32_t SHLightingSubSystem::AddShadowMap(Handle<SHRenderGraphResource> newShadowMapBlurred, EntityID lightEntity) noexcept
|
||||
{
|
||||
// Add to container of shadow maps
|
||||
shadowMapIndexing.emplace(lightEntity, static_cast<uint32_t> (shadowMaps.size()));
|
||||
shadowMaps.emplace_back(newShadowMapBlurred);
|
||||
uint32_t usedIndex = 0;
|
||||
|
||||
// Just use the image view stored in the resource
|
||||
Handle<SHVkImageView> const NEW_IMAGE_VIEW = newShadowMapBlurred->GetImageView();
|
||||
|
||||
// Prepare to write to descriptor
|
||||
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
// Update descriptor set
|
||||
//static constexpr uint32_t SHADOW_MAP_DESC_SET_INDEX = 0;
|
||||
//uint32_t const SHADOW_MAP_DESC_ARRAY_INDEX = static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
|
||||
//shadowMapDescriptorSet->ModifyWriteDescImage
|
||||
//(
|
||||
// SHADOW_MAP_DESC_SET_INDEX,
|
||||
// SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA,
|
||||
// shadowMapImageSamplers[SHADOW_MAP_DESC_ARRAY_INDEX],
|
||||
// SHADOW_MAP_DESC_ARRAY_INDEX
|
||||
//);
|
||||
|
||||
//// TODO: Definitely can be optimized by writing a function that modifies a specific descriptor in the array
|
||||
//shadowMapDescriptorSet->UpdateDescriptorSetImages
|
||||
//(
|
||||
// SHADOW_MAP_DESC_SET_INDEX,
|
||||
// SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA
|
||||
//);
|
||||
|
||||
// add to barriers
|
||||
shadowMapMemoryBarriers.push_back (vk::ImageMemoryBarrier
|
||||
{
|
||||
|
@ -652,8 +628,68 @@ namespace SHADE
|
|||
}
|
||||
});
|
||||
|
||||
if (recyclableIndices.empty())
|
||||
{
|
||||
shadowMaps.emplace_back(newShadowMapBlurred);
|
||||
|
||||
// Prepare to write to descriptor
|
||||
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
// Add to container of shadow maps
|
||||
shadowMapIndexing.emplace(lightEntity, static_cast<uint32_t> (shadowMaps.size()));
|
||||
|
||||
usedIndex = static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t usedIndex = recyclableIndices.top();
|
||||
recyclableIndices.pop();
|
||||
|
||||
// Recycle the slot in the vector of shadow maps
|
||||
shadowMaps[usedIndex] = newShadowMapBlurred;
|
||||
|
||||
// register indexing for shadow maps
|
||||
shadowMapIndexing.emplace(lightEntity, usedIndex);
|
||||
|
||||
// Recycle the slot in the vector of image view, samplers and layout
|
||||
shadowMapImageSamplers[usedIndex] = std::make_tuple(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
}
|
||||
|
||||
|
||||
// return new index of shadow map
|
||||
return static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
|
||||
return usedIndex;
|
||||
}
|
||||
|
||||
void SHLightingSubSystem::RemoveShadowMap(EntityID lightEntity) noexcept
|
||||
{
|
||||
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(lightEntity);
|
||||
|
||||
if (lightComp && shadowMapIndexing.contains(lightEntity))
|
||||
{
|
||||
uint32_t shadowMapIndex = shadowMapIndexing[lightEntity];
|
||||
|
||||
// Recycle the shadow map index used by the component
|
||||
RecycleShadowMapIndex(lightComp);
|
||||
|
||||
// Not removed from container, can recycle
|
||||
shadowMaps[shadowMapIndex] = {};
|
||||
|
||||
// Not removed from container, can recycle
|
||||
shadowMapImageSamplers[shadowMapIndex] = {};
|
||||
|
||||
// Remove from barriers
|
||||
shadowMapMemoryBarriers.erase(shadowMapMemoryBarriers.begin() + shadowMapIndex);
|
||||
|
||||
// remove from map for indexing
|
||||
shadowMapIndexing.erase(lightEntity);
|
||||
}
|
||||
}
|
||||
|
||||
void SHLightingSubSystem::RecycleShadowMapIndex(SHLightComponent* lightComp) noexcept
|
||||
{
|
||||
// if index is recyclable, recycle it
|
||||
if (lightComp && lightComp->GetShadowMapIndex() != SHLightData::INVALID_SHADOW_MAP_INDEX)
|
||||
recyclableIndices.push (lightComp->GetShadowMapIndex());
|
||||
}
|
||||
|
||||
void SHLightingSubSystem::PrepareShadowMapsForRead(Handle<SHVkCommandBuffer> cmdBuffer) noexcept
|
||||
|
@ -662,28 +698,6 @@ namespace SHADE
|
|||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, shadowMapMemoryBarriers);
|
||||
}
|
||||
|
||||
//void SHLightingSubSystem::HandleResize(Handle<SHRenderGraphNodeCompute> compute) noexcept
|
||||
//{
|
||||
// uint32_t const NUM_SHADOW_MAPS = static_cast<uint32_t>(shadowMaps.size());
|
||||
// for (uint32_t i = 0; i < NUM_SHADOW_MAPS; ++i)
|
||||
// {
|
||||
// // Just use the image view stored in the resource
|
||||
// Handle<SHVkImageView> const NEW_IMAGE_VIEW = shadowMaps[i]->GetImageView();
|
||||
|
||||
// // set new image view
|
||||
// std::get<Handle<SHVkImageView>>(shadowMapImageSamplers[i]) = NEW_IMAGE_VIEW;
|
||||
|
||||
// // Set image for barrier
|
||||
// shadowMapMemoryBarriers[i].image = shadowMaps[i]->GetImage()->GetVkImage();
|
||||
// }
|
||||
|
||||
// if (NUM_SHADOW_MAPS > 0)
|
||||
// {
|
||||
// // modify descriptors in render graph node compute
|
||||
// compute->ModifyWriteDescImageComputeResource (SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, shadowMapImageSamplers);
|
||||
// }
|
||||
//}
|
||||
|
||||
Handle<SHVkDescriptorSetGroup> SHLightingSubSystem::GetLightDataDescriptorSet(void) const noexcept
|
||||
{
|
||||
return lightingDataDescSet;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraphResource.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
#include <stack>
|
||||
|
||||
|
||||
namespace SHADE
|
||||
|
@ -183,10 +184,6 @@ namespace SHADE
|
|||
//! Shadow maps for every light that casts a shadow Order here doesn't matter. We just want to store it
|
||||
std::vector<Handle<SHRenderGraphResource>> shadowMaps;
|
||||
|
||||
//! Descriptor sets required to be given to the compute shader for shadow calculation. This will be a descriptor array.
|
||||
//! It will also be preallocated.
|
||||
//Handle<SHVkDescriptorSetGroup> shadowMapDescriptorSet;
|
||||
|
||||
//! Combined image samplers for the texture descriptors
|
||||
std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> shadowMapImageSamplers;
|
||||
|
||||
|
@ -194,6 +191,9 @@ namespace SHADE
|
|||
//! to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||
std::vector<vk::ImageMemoryBarrier> shadowMapMemoryBarriers;
|
||||
|
||||
//! recycled indices after deleting lights with shadows
|
||||
std::stack<uint32_t> recyclableIndices;
|
||||
|
||||
//! Resource hub from Graphics System
|
||||
SHResourceHub* resourceHub;
|
||||
|
||||
|
@ -212,12 +212,14 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, SHResourceHub* rh, Handle<SHVkSampler> inShadowMapSampler) noexcept;
|
||||
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
|
||||
void Exit (void) noexcept;
|
||||
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept;
|
||||
uint32_t AddShadowMap (Handle<SHRenderGraphResource> newShadowMapBlurred, EntityID lightEntity) noexcept;
|
||||
void PrepareShadowMapsForRead (Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, SHResourceHub* rh, Handle<SHVkSampler> inShadowMapSampler) noexcept;
|
||||
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
|
||||
void Exit (void) noexcept;
|
||||
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept;
|
||||
uint32_t AddShadowMap (Handle<SHRenderGraphResource> newShadowMapBlurred, EntityID lightEntity) noexcept;
|
||||
void RemoveShadowMap (EntityID lightEntity) noexcept;
|
||||
void RecycleShadowMapIndex (SHLightComponent* lightComp) noexcept;
|
||||
void PrepareShadowMapsForRead (Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||
//void HandleResize (Handle<SHRenderGraphNodeCompute> compute) noexcept;
|
||||
//void RemoveShadowMap (uint32_t index) noexcept;
|
||||
|
||||
|
|
|
@ -81,7 +81,8 @@ namespace SHADE
|
|||
|
||||
renderGraphStorage->logicalDevice->WaitIdle();
|
||||
|
||||
uint64_t handleID = renderGraphStorage->graphResources->at (resourceName).GetId().Raw;
|
||||
auto resourceHdl = renderGraphStorage->graphResources->at(resourceName);
|
||||
uint64_t handleID = resourceHdl.GetId().Raw;
|
||||
|
||||
// Record nodes that will be affected
|
||||
std::vector<uint32_t> affectedNodes{};
|
||||
|
@ -89,7 +90,7 @@ namespace SHADE
|
|||
// Detach resource from all nodes if applicable
|
||||
for (uint32_t i = 0; i < nodes.size(); ++i)
|
||||
{
|
||||
if (nodes[i]->DetachResource(resourceName, handleID))
|
||||
if (nodes[i] && nodes[i]->DetachResource(resourceName, handleID))
|
||||
affectedNodes.emplace_back(i);
|
||||
}
|
||||
|
||||
|
@ -109,6 +110,8 @@ namespace SHADE
|
|||
|
||||
renderGraphStorage->graphResources->at(resourceName).Free();
|
||||
renderGraphStorage->graphResources->erase (resourceName);
|
||||
|
||||
resourceHdl.Free ();
|
||||
/*
|
||||
* IMPORTANT NOTES
|
||||
*
|
||||
|
@ -121,6 +124,21 @@ namespace SHADE
|
|||
*/
|
||||
}
|
||||
|
||||
void SHRenderGraph::RemoveNode(std::string nodeName) noexcept
|
||||
{
|
||||
if (nodeIndexing.contains(nodeName))
|
||||
{
|
||||
// wait for device to stop
|
||||
renderGraphStorage->logicalDevice->WaitIdle();
|
||||
|
||||
// Get handle to node since it exists
|
||||
auto nodeHdl = nodes[nodeIndexing[nodeName]];
|
||||
|
||||
nodeHdl.Free();
|
||||
nodeIndexing.erase(nodeName);
|
||||
}
|
||||
}
|
||||
|
||||
void SHRenderGraph::LinkNonOwningResource(Handle<SHRenderGraph> resourceOrigin, std::string resourceName) noexcept
|
||||
{
|
||||
// resource to link
|
||||
|
|
|
@ -112,6 +112,7 @@ namespace SHADE
|
|||
);
|
||||
|
||||
void RemoveResource (std::string resourceName) noexcept;
|
||||
void RemoveNode (std::string nodeName) noexcept;
|
||||
|
||||
void LinkNonOwningResource
|
||||
(
|
||||
|
|
|
@ -405,6 +405,22 @@ namespace SHADE
|
|||
return *this;
|
||||
}
|
||||
|
||||
SHRenderGraphNode::~SHRenderGraphNode(void) noexcept
|
||||
{
|
||||
if (renderpass)
|
||||
renderpass.Free();
|
||||
|
||||
for (auto& framebuffer : framebuffers)
|
||||
framebuffer.Free();
|
||||
|
||||
for (auto& subpass : subpasses)
|
||||
subpass.Free();
|
||||
|
||||
// Too tired to test, its nearing end of milestone 3....
|
||||
//for (auto& nc : nodeComputes)
|
||||
// nc.Free();
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ namespace SHADE
|
|||
SHRenderGraphNode(std::string nodeName, Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, bool inIsDynamic = false) noexcept;
|
||||
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
|
||||
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
|
||||
~SHRenderGraphNode (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
|
@ -132,12 +133,12 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
void SetDynamicActive(bool active) noexcept;
|
||||
|
||||
Handle<SHVkRenderpass> GetRenderpass(void) const noexcept;
|
||||
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
|
||||
Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept;
|
||||
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;
|
||||
Handle<SHRenderGraphNodeCompute> GetNodeCompute (std::string nodeComputeName) const noexcept;
|
||||
bool GetDynamicActive (void) const noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> GetNodeCompute (std::string nodeComputeName) const noexcept;
|
||||
bool GetDynamicActive (void) const noexcept;
|
||||
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
|
|
@ -80,6 +80,14 @@ namespace SHADE
|
|||
, companionSubpasses {std::move (rhs.companionSubpasses)}
|
||||
, dummyPipelineLayout{rhs.dummyPipelineLayout}
|
||||
{
|
||||
superBatch = std::move(rhs.superBatch);
|
||||
rhs.superBatch = {};
|
||||
|
||||
inputDescriptorLayout = std::move(rhs.inputDescriptorLayout);
|
||||
rhs.inputDescriptorLayout = {};
|
||||
|
||||
dummyPipelineLayout = std::move(rhs.dummyPipelineLayout);
|
||||
rhs.dummyPipelineLayout = {};
|
||||
|
||||
}
|
||||
|
||||
|
@ -101,7 +109,6 @@ namespace SHADE
|
|||
|
||||
subpassIndex = std::move(rhs.subpassIndex);
|
||||
parentNode = std::move(rhs.parentNode);
|
||||
superBatch = std::move(rhs.superBatch);
|
||||
colorReferences = std::move(rhs.colorReferences);
|
||||
depthReferences = std::move(rhs.depthReferences);
|
||||
inputReferences = std::move(rhs.inputReferences);
|
||||
|
@ -118,10 +125,36 @@ namespace SHADE
|
|||
companionSubpasses = rhs.companionSubpasses;
|
||||
dummyPipelineLayout = rhs.dummyPipelineLayout;
|
||||
|
||||
superBatch = std::move(rhs.superBatch);
|
||||
rhs.superBatch = {};
|
||||
|
||||
inputDescriptorLayout = std::move(rhs.inputDescriptorLayout);
|
||||
rhs.inputDescriptorLayout = {};
|
||||
|
||||
dummyPipelineLayout = std::move(rhs.dummyPipelineLayout);
|
||||
rhs.dummyPipelineLayout = {};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SHSubpass::~SHSubpass(void) noexcept
|
||||
{
|
||||
graphStorage->logicalDevice->WaitIdle();
|
||||
|
||||
for (auto& set : inputImageDescriptorSets)
|
||||
set.Free();
|
||||
|
||||
if (inputDescriptorLayout)
|
||||
inputDescriptorLayout.Free();
|
||||
|
||||
if (dummyPipelineLayout)
|
||||
dummyPipelineLayout.Free();
|
||||
|
||||
// not working
|
||||
//if (superBatch)
|
||||
// superBatch.Free();
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
|
|
@ -130,6 +130,7 @@ namespace SHADE
|
|||
SHSubpass(const std::string& name, Handle<SHViewport> inViewport, Handle<SHRenderer> inRenderer, Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept;
|
||||
SHSubpass(SHSubpass&& rhs) noexcept;
|
||||
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
|
||||
~SHSubpass(void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
|
|
Loading…
Reference in New Issue