2112 lines
119 KiB
C++
2112 lines
119 KiB
C++
|
// This file is part of the FidelityFX SDK.
|
||
|
//
|
||
|
// Copyright (C) 2024 Advanced Micro Devices, Inc.
|
||
|
//
|
||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
// of this software and associated documentation files(the "Software"), to deal
|
||
|
// in the Software without restriction, including without limitation the rights
|
||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
|
||
|
// copies of the Software, and to permit persons to whom the Software is
|
||
|
// furnished to do so, subject to the following conditions :
|
||
|
//
|
||
|
// The above copyright notice and this permission notice shall be included in
|
||
|
// all copies or substantial portions of the Software.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
// THE SOFTWARE.
|
||
|
|
||
|
#include "shaders/surfacerendercommon.h"
|
||
|
|
||
|
#include "hybridreflectionsrendermodule.h"
|
||
|
|
||
|
#include "core/backend_interface.h"
|
||
|
#include "core/components/meshcomponent.h"
|
||
|
#include "core/framework.h"
|
||
|
#include "core/scene.h"
|
||
|
#include "render/dynamicresourcepool.h"
|
||
|
#include "render/dynamicbufferpool.h"
|
||
|
#include "render/parameterset.h"
|
||
|
#include "render/pipelineobject.h"
|
||
|
#include "render/indirectworkload.h"
|
||
|
#include "render/rasterview.h"
|
||
|
#include "render/dynamicresourcepool.h"
|
||
|
#include "render/profiler.h"
|
||
|
#include "shaders/lightingcommon.h"
|
||
|
|
||
|
namespace samplercpp
|
||
|
{
|
||
|
#include "../thirdparty/samplercpp/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_256spp.cpp"
|
||
|
}
|
||
|
|
||
|
using namespace cauldron;
|
||
|
|
||
|
#define FFX_HYBRID_REFLECTIONS_CONTEXT_COUNT (FFX_CLASSIFIER_CONTEXT_COUNT + FFX_DENOISER_CONTEXT_COUNT + FFX_SPD_CONTEXT_COUNT)
|
||
|
|
||
|
static void setFlag(uint32_t& flags, uint32_t bit, bool enable)
|
||
|
{
|
||
|
flags &= ~bit;
|
||
|
flags |= (enable ? bit : 0);
|
||
|
};
|
||
|
|
||
|
static std::vector<const char*> BuildDebugOptions(bool enable)
|
||
|
{
|
||
|
std::vector<const char*> debugOptions;
|
||
|
|
||
|
if (enable)
|
||
|
debugOptions.push_back("Visualize Hit Counter");
|
||
|
debugOptions.push_back("Show Reflection Target");
|
||
|
debugOptions.push_back("Visualize Primary Rays");
|
||
|
|
||
|
return debugOptions;
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::Init(const json& initData)
|
||
|
{
|
||
|
CauldronAssert(ASSERT_CRITICAL, GetFramework()->GetConfig()->RT_1_1, L"Error: Hybrid Reflections requires RT1.1");
|
||
|
CauldronAssert(ASSERT_CRITICAL, GetFramework()->GetConfig()->MinShaderModel >= ShaderModel::SM6_5, L"Error: Hybrid Reflections requires SM6_5 or greater");
|
||
|
CreateResources();
|
||
|
|
||
|
m_RTInfoTables.m_Textures.reserve(MAX_TEXTURES_COUNT);
|
||
|
m_RTInfoTables.m_Samplers.reserve(MAX_SAMPLERS_COUNT);
|
||
|
m_RTInfoTables.m_VertexBuffers.reserve(MAX_BUFFER_COUNT);
|
||
|
m_RTInfoTables.m_IndexBuffers.reserve(MAX_BUFFER_COUNT);
|
||
|
|
||
|
ExecuteCallback callbackCopyColorBuffer = [this](double deltaTime, CommandList* pCmdList) { this->CopyColorBufferCallback(deltaTime, pCmdList); };
|
||
|
ExecutionTuple callbackCopyColorBufferTuple = std::make_pair(L"HybridReflectionsRenderModule::CopyColorBufferCallback", std::make_pair(this, callbackCopyColorBuffer));
|
||
|
GetFramework()->RegisterExecutionCallback(L"ToneMappingRenderModule", true, callbackCopyColorBufferTuple);
|
||
|
|
||
|
// Register a pre-lighting callback to set the specular IBL factor to 0 for the lighting pass.
|
||
|
// We're doing this to avoid applying the IBL specular reflections twice, once in the lighting pass and once in the HSR pass.
|
||
|
ExecuteCallback callbackPreLighting = [this](double deltaTime, CommandList* pCmdList) {
|
||
|
m_SceneSpecularIBLFactor = GetScene()->GetSpecularIBLFactor();
|
||
|
if (m_ApplyScreenSpaceReflections)
|
||
|
{
|
||
|
GetScene()->SetSpecularIBLFactor(0.0f);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
ExecutionTuple callbackPreLightingTuple = std::make_pair(L"HybridReflectionsRenderModule::PreLightingCallback", std::make_pair(this, callbackPreLighting));
|
||
|
GetFramework()->RegisterExecutionCallback(L"LightingRenderModule", true, callbackPreLightingTuple);
|
||
|
|
||
|
// Register a post-lighting callback to reset the IBL factor to what it previously was.
|
||
|
ExecuteCallback callbackPostLighting = [this](double deltaTime, CommandList* pCmdList) { GetScene()->SetSpecularIBLFactor(m_SceneSpecularIBLFactor); };
|
||
|
ExecutionTuple callbackPostLightingTuple =
|
||
|
std::make_pair(L"HybridReflectionsRenderModule::PostLightingCallback", std::make_pair(this, callbackPostLighting));
|
||
|
GetFramework()->RegisterExecutionCallback(L"LightingRenderModule", false, callbackPostLightingTuple);
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
// Final pass resources to apply reflections
|
||
|
|
||
|
m_LinearSamplerDesc.Filter = FilterFunc::MinMagLinearMipPoint;
|
||
|
m_LinearSamplerDesc.MaxAnisotropy = 1u;
|
||
|
|
||
|
m_WrapLinearSamplerDesc.AddressU = AddressMode::Wrap;
|
||
|
m_WrapLinearSamplerDesc.AddressV = AddressMode::Wrap;
|
||
|
m_WrapLinearSamplerDesc.AddressW = AddressMode::Wrap;
|
||
|
|
||
|
m_EnvironmentSamplerDesc.AddressW = AddressMode::Wrap;
|
||
|
|
||
|
m_ComparisonSampler.Comparison = GetConfig()->InvertedDepth ? ComparisonFunc::GreaterEqual : ComparisonFunc::LessEqual;
|
||
|
m_ComparisonSampler.Filter = FilterFunc::ComparisonMinMagLinearMipPoint;
|
||
|
m_ComparisonSampler.MaxAnisotropy = 1;
|
||
|
|
||
|
m_SpecularSampler.AddressW = AddressMode::Wrap;
|
||
|
m_SpecularSampler.Filter = FilterFunc::MinMagMipLinear;
|
||
|
m_SpecularSampler.MaxAnisotropy = 1;
|
||
|
|
||
|
m_DiffuseSampler.Filter = FilterFunc::MinMagMipPoint;
|
||
|
m_DiffuseSampler.AddressW = AddressMode::Wrap;
|
||
|
m_DiffuseSampler.Filter = FilterFunc::MinMagMipPoint;
|
||
|
m_DiffuseSampler.MaxAnisotropy = 1;
|
||
|
|
||
|
InitApplyReflections(initData);
|
||
|
|
||
|
BuildUI();
|
||
|
|
||
|
// Initialize mask
|
||
|
m_Mask = HSR_FLAGS_USE_HIT_COUNTER | HSR_FLAGS_APPLY_REFLECTIONS | HSR_FLAGS_USE_RAY_TRACING |
|
||
|
// HSR_FLAGS_VISUALIZE_HIT_COUNTER |
|
||
|
HSR_FLAGS_USE_SCREEN_SPACE | 0;
|
||
|
|
||
|
// DXR Tier support
|
||
|
if (!GetFramework()->GetDevice()->FeatureSupported(DeviceFeature::RT_1_1))
|
||
|
{
|
||
|
m_Mask &= ~HSR_FLAGS_USE_RAY_TRACING;
|
||
|
}
|
||
|
|
||
|
CreateFfxContexts();
|
||
|
|
||
|
GetFramework()->ConfigureRuntimeShaderRecompiler(
|
||
|
[this](void) {
|
||
|
DestroyFfxContexts();
|
||
|
},
|
||
|
[this](void) {
|
||
|
CreateFfxContexts();
|
||
|
});
|
||
|
|
||
|
InitPrepareBlueNoise(initData);
|
||
|
InitPrimaryRayTracing(initData);
|
||
|
InitHybridDeferred(initData);
|
||
|
InitRTDeferred(initData);
|
||
|
InitDeferredShadeRays(initData);
|
||
|
InitPrepareIndirectHybrid(initData);
|
||
|
InitPrepareIndirectHW(initData);
|
||
|
InitCopyDepth(initData);
|
||
|
|
||
|
// Register for content change updates
|
||
|
GetContentManager()->AddContentListener(this);
|
||
|
|
||
|
// That's all we need for now
|
||
|
SetModuleReady(true);
|
||
|
}
|
||
|
|
||
|
HybridReflectionsRenderModule::~HybridReflectionsRenderModule()
|
||
|
{
|
||
|
// Protection
|
||
|
if (ModuleEnabled())
|
||
|
{
|
||
|
EnableModule(false);
|
||
|
|
||
|
DestroyFfxContexts();
|
||
|
|
||
|
delete m_pParamSet;
|
||
|
delete m_pApplyReflectionsPipeline;
|
||
|
delete m_pApplyReflectionsRS;
|
||
|
m_pColorRasterView = nullptr;
|
||
|
|
||
|
delete m_pPrepareBlueNoiseParameters;
|
||
|
delete m_pPrepareBlueNoisePipelineObj;
|
||
|
delete m_pPrepareBlueNoiseRootSignature;
|
||
|
|
||
|
delete m_pPrimaryRTParameters;
|
||
|
delete m_pPrimaryRTPipelineObj;
|
||
|
delete m_pPrimaryRTRootSignature;
|
||
|
|
||
|
delete m_pHybridDeferredParameters;
|
||
|
delete m_pHybridDeferredPipelineObj;
|
||
|
delete m_pHybridDeferredRootSignature;
|
||
|
delete m_pHybridDeferredIndirectWorkload;
|
||
|
|
||
|
delete m_pRTDeferredParameters;
|
||
|
delete m_pRTDeferredPipelineObj;
|
||
|
delete m_pRTDeferredRootSignature;
|
||
|
delete m_pRTDeferredIndirectWorkload;
|
||
|
|
||
|
delete m_pDeferredShadeRaysParameters;
|
||
|
delete m_pDeferredShadeRaysPipelineObj;
|
||
|
delete m_pDeferredShadeRaysRootSignature;
|
||
|
delete m_pDeferredShadeRaysIndirectWorkload;
|
||
|
|
||
|
delete m_pPrepareIndirectHybridParameters;
|
||
|
delete m_pPrepareIndirectHybridPipelineObj;
|
||
|
delete m_pPrepareIndirectHybridRootSignature;
|
||
|
|
||
|
delete m_pPrepareIndirectHWParameters;
|
||
|
delete m_pPrepareIndirectHWPipelineObj;
|
||
|
delete m_pPrepareIndirectHWRootSignature;
|
||
|
|
||
|
delete m_pCopyDepthParameters;
|
||
|
delete m_pCopyDepthPipelineObj;
|
||
|
delete m_pCopyDepthRootSignature;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::DestroyFfxContexts()
|
||
|
{
|
||
|
// Flush anything out of the pipes before destroying the context
|
||
|
GetDevice()->FlushAllCommandQueues();
|
||
|
|
||
|
ffxClassifierContextDestroy(&m_ClassifierContext);
|
||
|
ffxDenoiserContextDestroy(&m_DenoiserContext);
|
||
|
ffxSpdContextDestroy(&m_SpdContext);
|
||
|
|
||
|
// Destroy the FidelityFX interface memory
|
||
|
if (m_BackendInterface.scratchBuffer)
|
||
|
{
|
||
|
free(m_BackendInterface.scratchBuffer);
|
||
|
m_BackendInterface.scratchBuffer = nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::CreateFfxContexts()
|
||
|
{
|
||
|
// Initialize the FFX backend
|
||
|
const size_t scratchBufferSize = SDKWrapper::ffxGetScratchMemorySize(FFX_HYBRID_REFLECTIONS_CONTEXT_COUNT);
|
||
|
void* scratchBuffer = calloc(scratchBufferSize, 1u);
|
||
|
FfxErrorCode errorCode = SDKWrapper::ffxGetInterface(&m_BackendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_HYBRID_REFLECTIONS_CONTEXT_COUNT);
|
||
|
CAULDRON_ASSERT(errorCode == FFX_OK);
|
||
|
CauldronAssert(ASSERT_CRITICAL, m_BackendInterface.fpGetSDKVersion(&m_BackendInterface) == FFX_SDK_MAKE_VERSION(1, 1, 2),
|
||
|
L"FidelityFX HybridReflections 2.1 sample requires linking with a 1.1.2 version SDK backend");
|
||
|
CauldronAssert(ASSERT_CRITICAL, ffxClassifierGetEffectVersion() == FFX_SDK_MAKE_VERSION(1, 3, 0),
|
||
|
L"FidelityFX HybridReflections 2.1 sample requires linking with a 1.3 version FidelityFX Classifier library");
|
||
|
CauldronAssert(ASSERT_CRITICAL, ffxDenoiserGetEffectVersion() == FFX_SDK_MAKE_VERSION(1, 3, 0),
|
||
|
L"FidelityFX HybridReflections 2.1 sample requires linking with a 1.3 version FidelityFX Denoiser library");
|
||
|
|
||
|
m_BackendInterface.fpRegisterConstantBufferAllocator(&m_BackendInterface, SDKWrapper::ffxAllocateConstantBuffer);
|
||
|
|
||
|
// Init context
|
||
|
CreateBackendContext();
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::CreateBackendContext()
|
||
|
{
|
||
|
const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo();
|
||
|
|
||
|
m_DenoiserInitializationParameters.flags = FfxDenoiserInitializationFlagBits::FFX_DENOISER_REFLECTIONS;
|
||
|
m_DenoiserInitializationParameters.windowSize.width = resInfo.RenderWidth;
|
||
|
m_DenoiserInitializationParameters.windowSize.height = resInfo.RenderHeight;
|
||
|
m_DenoiserInitializationParameters.normalsHistoryBufferFormat = SDKWrapper::GetFfxSurfaceFormat(m_pNormal->GetFormat());
|
||
|
m_DenoiserInitializationParameters.backendInterface = m_BackendInterface;
|
||
|
CAULDRON_ASSERT(ffxDenoiserContextCreate(&m_DenoiserContext, &m_DenoiserInitializationParameters) == FFX_OK);
|
||
|
|
||
|
m_ClassifierInitializationParameters.flags = FfxClassifierInitializationFlagBits::FFX_CLASSIFIER_REFLECTION;
|
||
|
m_ClassifierInitializationParameters.flags |= GetConfig()->InvertedDepth ? FFX_CLASSIFIER_ENABLE_DEPTH_INVERTED : 0;
|
||
|
m_ClassifierInitializationParameters.resolution.width = resInfo.RenderWidth;
|
||
|
m_ClassifierInitializationParameters.resolution.height = resInfo.RenderHeight;
|
||
|
m_ClassifierInitializationParameters.backendInterface = m_BackendInterface;
|
||
|
CAULDRON_ASSERT(ffxClassifierContextCreate(&m_ClassifierContext, &m_ClassifierInitializationParameters) == FFX_OK);
|
||
|
|
||
|
m_SpdInitializationParameters.flags = 0;
|
||
|
m_SpdInitializationParameters.flags |= FFX_SPD_WAVE_INTEROP_WAVE_OPS;
|
||
|
m_SpdInitializationParameters.downsampleFilter = GetConfig()->InvertedDepth ? FFX_SPD_DOWNSAMPLE_FILTER_MAX : FFX_SPD_DOWNSAMPLE_FILTER_MIN;
|
||
|
m_SpdInitializationParameters.backendInterface = m_BackendInterface;
|
||
|
CAULDRON_ASSERT(ffxSpdContextCreate(&m_SpdContext, &m_SpdInitializationParameters) == FFX_OK);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ResetBackendContext()
|
||
|
{
|
||
|
// Destroy the HSR context
|
||
|
CAULDRON_ASSERT(ffxDenoiserContextDestroy(&m_DenoiserContext) == FFX_OK);
|
||
|
CAULDRON_ASSERT(ffxClassifierContextDestroy(&m_ClassifierContext) == FFX_OK);
|
||
|
CAULDRON_ASSERT(ffxSpdContextDestroy(&m_SpdContext) == FFX_OK);
|
||
|
|
||
|
// Re-create the HSR context
|
||
|
CreateBackendContext();
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::CopyColorBufferCallback(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"HSR_CopyColor");
|
||
|
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pColorTarget->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::CopySource));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pHistoryColorTarget->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::CopyDest));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
// Copy the color render target before we apply translucency
|
||
|
TextureCopyDesc copyColor = TextureCopyDesc(m_pColorTarget->GetResource(), m_pHistoryColorTarget->GetResource());
|
||
|
CopyTextureRegion(pCmdList, ©Color);
|
||
|
|
||
|
barriers.clear();
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pColorTarget->GetResource(), ResourceState::CopySource, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pHistoryColorTarget->GetResource(), ResourceState::CopyDest, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ShowDebugTarget()
|
||
|
{
|
||
|
if (m_ShowDebugTarget)
|
||
|
{
|
||
|
m_Mask |= HSR_FLAGS_SHOW_DEBUG_TARGET;
|
||
|
|
||
|
std::vector<int> flagList;
|
||
|
|
||
|
if (m_EnableHybridReflection) flagList.push_back(HSR_FLAGS_VISUALIZE_HIT_COUNTER);
|
||
|
flagList.push_back(HSR_FLAGS_SHOW_REFLECTION_TARGET);
|
||
|
flagList.push_back(HSR_FLAGS_VISUALIZE_PRIMARY_RAYS);
|
||
|
|
||
|
m_Mask |= flagList[m_DebugOption];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_Mask &= ~HSR_FLAGS_SHOW_DEBUG_TARGET;
|
||
|
|
||
|
std::vector<int> flagList;
|
||
|
|
||
|
if (m_EnableHybridReflection) flagList.push_back(HSR_FLAGS_VISUALIZE_HIT_COUNTER);
|
||
|
flagList.push_back(HSR_FLAGS_SHOW_REFLECTION_TARGET);
|
||
|
flagList.push_back(HSR_FLAGS_VISUALIZE_PRIMARY_RAYS);
|
||
|
|
||
|
for (auto flag : flagList)
|
||
|
{
|
||
|
m_Mask &= ~flag;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void HybridReflectionsRenderModule::SelectDebugOption()
|
||
|
{
|
||
|
std::vector<int> flagList;
|
||
|
|
||
|
if (m_EnableHybridReflection) flagList.push_back(HSR_FLAGS_VISUALIZE_HIT_COUNTER);
|
||
|
flagList.push_back(HSR_FLAGS_SHOW_REFLECTION_TARGET);
|
||
|
flagList.push_back(HSR_FLAGS_VISUALIZE_PRIMARY_RAYS);
|
||
|
|
||
|
for (auto flag : flagList)
|
||
|
{
|
||
|
m_Mask &= ~flag;
|
||
|
}
|
||
|
|
||
|
m_Mask |= flagList[m_DebugOption];
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ToggleHybridReflection()
|
||
|
{
|
||
|
m_IsEnableHybridReflectionChanged = true;
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ToggleHalfResGBuffer()
|
||
|
{
|
||
|
UpdateReflectionResolution();
|
||
|
m_HalfResGBufferDisabled = !m_EnableHalfResGBuffer;
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::UpdateReflectionResolution()
|
||
|
{
|
||
|
int width = GetFramework()->GetResolutionInfo().RenderWidth;
|
||
|
int height = GetFramework()->GetResolutionInfo().RenderHeight;
|
||
|
|
||
|
m_ReflectionResolutionMultiplier = m_EnableHalfResGBuffer ? 0.5f : 1.0f;
|
||
|
m_ReflectionWidth = std::max(128u, uint32_t(width * m_ReflectionResolutionMultiplier));
|
||
|
m_ReflectionHeight = std::max(128u, uint32_t(height * m_ReflectionResolutionMultiplier));
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::UpdateUI(double deltaTime)
|
||
|
{
|
||
|
if (m_IsEnableHybridReflectionChanged)
|
||
|
{
|
||
|
m_UIDebugOption->SetOption(BuildDebugOptions(m_EnableHybridReflection));
|
||
|
|
||
|
// Keep current selection
|
||
|
if (m_EnableHybridReflection)
|
||
|
{
|
||
|
// Hit counter inserted in front
|
||
|
m_DebugOption += 1;
|
||
|
}
|
||
|
else if (m_DebugOption > 0)
|
||
|
{
|
||
|
// Hit counter removed from front
|
||
|
m_DebugOption -= 1;
|
||
|
}
|
||
|
|
||
|
if (m_Mask & HSR_FLAGS_SHOW_DEBUG_TARGET)
|
||
|
SelectDebugOption();
|
||
|
|
||
|
m_IsEnableHybridReflectionChanged = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::CreateResources()
|
||
|
{
|
||
|
// Fetch needed resources
|
||
|
m_pColorTarget = GetFramework()->GetColorTargetForCallback(GetName());
|
||
|
// Needed to apply reflections
|
||
|
m_pColorRasterView = GetRasterViewAllocator()->RequestRasterView(m_pColorTarget, ViewDimension::Texture2D);
|
||
|
|
||
|
m_pDepthTarget = GetFramework()->GetRenderTexture(L"DepthTarget");
|
||
|
m_pOutput = GetFramework()->GetRenderTexture(L"HybridReflectionOutput");
|
||
|
|
||
|
// Assumed resources, need to check they are there
|
||
|
m_pMotionVectors = GetFramework()->GetRenderTexture(L"GBufferMotionVectorRT");
|
||
|
m_pNormal = GetFramework()->GetRenderTexture(L"GBufferNormalRT");
|
||
|
m_pAlbedo = GetFramework()->GetRenderTexture(L"GBufferAlbedoRT");
|
||
|
m_pAoRoughnessMetallic = GetFramework()->GetRenderTexture(L"GBufferAoRoughnessMetallicRT");
|
||
|
CauldronAssert(ASSERT_CRITICAL,
|
||
|
m_pMotionVectors && m_pNormal && m_pAoRoughnessMetallic && m_pAlbedo,
|
||
|
L"Could not get one of the needed resources for HSR Rendermodule.");
|
||
|
|
||
|
uint32_t renderWidth = GetFramework()->GetResolutionInfo().RenderWidth;
|
||
|
uint32_t renderHeight = GetFramework()->GetResolutionInfo().RenderHeight;
|
||
|
|
||
|
const uint32_t numPixels = renderWidth * renderHeight;
|
||
|
const uint32_t numTiles = DivideRoundingUp(renderWidth, 8u) * DivideRoundingUp(renderHeight, 8u);
|
||
|
uint32_t depthHierarchyMipCount = (uint32_t)ceil(log2(std::max(renderWidth, renderHeight)));
|
||
|
|
||
|
auto renderSizeFn = [](TextureDesc& desc, uint32_t displayWidth, uint32_t displayHeight, uint32_t renderingWidth, uint32_t renderingHeight) {
|
||
|
desc.Width = renderingWidth;
|
||
|
desc.Height = renderingHeight;
|
||
|
};
|
||
|
|
||
|
auto renderSize64Fn = [](TextureDesc& desc, uint32_t displayWidth, uint32_t displayHeight, uint32_t renderingWidth, uint32_t renderingHeight) {
|
||
|
desc.Width = DivideRoundingUp(renderingWidth, 8u);
|
||
|
desc.Height = DivideRoundingUp(renderingHeight, 8u);
|
||
|
};
|
||
|
|
||
|
auto renderSizeFnBuffer = [](BufferDesc& desc, uint32_t displayWidth, uint32_t displayHeight, uint32_t renderingWidth, uint32_t renderingHeight) {
|
||
|
desc.Size = renderingWidth * renderingHeight * sizeof(uint32_t);
|
||
|
};
|
||
|
|
||
|
auto renderSizeX12FnBuffer = [](BufferDesc& desc, uint32_t displayWidth, uint32_t displayHeight, uint32_t renderingWidth, uint32_t renderingHeight) {
|
||
|
desc.Size = renderingWidth * renderingHeight * 12ull;
|
||
|
};
|
||
|
|
||
|
auto renderSize64FnBuffer = [](BufferDesc& desc, uint32_t displayWidth, uint32_t displayHeight, uint32_t renderingWidth, uint32_t renderingHeight) {
|
||
|
desc.Size = DivideRoundingUp(renderingWidth, 8u) * DivideRoundingUp(renderingHeight, 8u) * sizeof(uint32_t);
|
||
|
};
|
||
|
|
||
|
TextureDesc desc = TextureDesc::Tex2D(
|
||
|
L"HSR_DepthHierarchy", ResourceFormat::R32_FLOAT, renderWidth, renderHeight, 1, depthHierarchyMipCount, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pDepthHierarchy = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSizeFn);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_ExtractedRoughness", ResourceFormat::R8_UNORM, renderWidth, renderHeight, 1, 1, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pExtractedRoughness = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSizeFn);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_HistoryColor", ResourceFormat::RG11B10_FLOAT, renderWidth, renderHeight, 1, 1, ResourceFlags::None);
|
||
|
m_pHistoryColorTarget = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSizeFn);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_Radiance0", ResourceFormat::RGBA16_FLOAT, renderWidth, renderHeight, 1, 1, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pRadiance0 = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSizeFn);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_Radiance1", ResourceFormat::RGBA16_FLOAT, renderWidth, renderHeight, 1, 1, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pRadiance1 = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSizeFn);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_Variance0", ResourceFormat::R16_FLOAT, renderWidth, renderHeight, 1, 1, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pVariance0 = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSizeFn);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_Variance1", ResourceFormat::R16_FLOAT, renderWidth, renderHeight, 1, 1, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pVariance1 = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSizeFn);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_HitCounter0",
|
||
|
ResourceFormat::R32_UINT,
|
||
|
DivideRoundingUp(renderWidth, 8u),
|
||
|
DivideRoundingUp(renderHeight, 8u),
|
||
|
1,
|
||
|
1,
|
||
|
ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pHitCounter0 = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSize64Fn);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_HitCounter1",
|
||
|
ResourceFormat::R32_UINT,
|
||
|
DivideRoundingUp(renderWidth, 8u),
|
||
|
DivideRoundingUp(renderHeight, 8u),
|
||
|
1,
|
||
|
1,
|
||
|
ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pHitCounter1 = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSize64Fn);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_BlueNoiseTexture", ResourceFormat::RG8_UNORM, 128, 128, 1, 1, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pBlueNoiseTexture = GetDynamicResourcePool()->CreateRenderTexture(&desc);
|
||
|
|
||
|
desc = TextureDesc::Tex2D(L"HSR_DebugImage", ResourceFormat::RGBA32_FLOAT, renderWidth, renderHeight, 1, 1, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pDebugImage = GetDynamicResourcePool()->CreateRenderTexture(&desc, renderSizeFn);
|
||
|
|
||
|
BufferDesc bufferDesc = BufferDesc::Data(L"HSR_RayList", numPixels * sizeof(uint32_t), sizeof(uint32_t), 0, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pRayList = GetDynamicResourcePool()->CreateBuffer(&bufferDesc, ResourceState::UnorderedAccess, renderSizeFnBuffer);
|
||
|
|
||
|
bufferDesc = BufferDesc::Data(L"HSR_HWRayList", numPixels * sizeof(uint32_t), sizeof(uint32_t), 0, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pHWRayList = GetDynamicResourcePool()->CreateBuffer(&bufferDesc, ResourceState::UnorderedAccess, renderSizeFnBuffer);
|
||
|
|
||
|
bufferDesc = BufferDesc::Data(L"HSR_DenoiserTileList", numTiles * sizeof(uint32_t), sizeof(uint32_t), 0, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pDenoiserTileList = GetDynamicResourcePool()->CreateBuffer(&bufferDesc, ResourceState::UnorderedAccess, renderSize64FnBuffer);
|
||
|
|
||
|
bufferDesc = BufferDesc::Data(L"HSR_RayCounter", 8ull * sizeof(uint32_t), sizeof(uint32_t), 0, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pRayCounter = GetDynamicResourcePool()->CreateBuffer(&bufferDesc, ResourceState::UnorderedAccess);
|
||
|
|
||
|
bufferDesc = BufferDesc::Data(L"HSR_IntersectionPassIndirectArgs",
|
||
|
12ull * sizeof(uint32_t),
|
||
|
sizeof(uint32_t),
|
||
|
0,
|
||
|
static_cast<ResourceFlags>(ResourceFlags::AllowUnorderedAccess | ResourceFlags::AllowIndirect));
|
||
|
m_pIntersectionPassIndirectArgs = GetDynamicResourcePool()->CreateBuffer(&bufferDesc, ResourceState::IndirectArgument);
|
||
|
|
||
|
bufferDesc = BufferDesc::Data(L"HSR_RayGBufferList", numPixels * 12ull, sizeof(uint32_t), 0, ResourceFlags::AllowUnorderedAccess);
|
||
|
m_pRayGBufferList = GetDynamicResourcePool()->CreateBuffer(&bufferDesc, ResourceState::UnorderedAccess, renderSizeX12FnBuffer);
|
||
|
|
||
|
bufferDesc = BufferDesc::Data(L"HSR_Sobol", sizeof(uint32_t) * 256ull * 256ull, sizeof(uint32_t), 0, ResourceFlags::None);
|
||
|
m_pSobol = GetDynamicResourcePool()->CreateBuffer(&bufferDesc, ResourceState::CopyDest);
|
||
|
const_cast<Buffer*>(m_pSobol)->CopyData((void*)samplercpp::sobol_256spp_256d, sizeof(samplercpp::sobol_256spp_256d));
|
||
|
|
||
|
bufferDesc = BufferDesc::Data(L"HSR_RankingTile", sizeof(uint32_t) * 128ull * 128ull * 8ull, sizeof(uint32_t), 0, ResourceFlags::None);
|
||
|
m_pRankingTile = GetDynamicResourcePool()->CreateBuffer(&bufferDesc, ResourceState::CopyDest);
|
||
|
const_cast<Buffer*>(m_pRankingTile)->CopyData((void*)samplercpp::rankingTile, sizeof(samplercpp::rankingTile));
|
||
|
|
||
|
bufferDesc = BufferDesc::Data(L"HSR_ScramblingTile", sizeof(uint32_t) * 128ull * 128ull * 8ull, sizeof(uint32_t), 0, ResourceFlags::None);
|
||
|
m_pScramblingTile = GetDynamicResourcePool()->CreateBuffer(&bufferDesc, ResourceState::CopyDest);
|
||
|
const_cast<Buffer*>(m_pScramblingTile)->CopyData((void*)samplercpp::scramblingTile, sizeof(samplercpp::scramblingTile));
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::BuildUI()
|
||
|
{
|
||
|
UISection* uiSection = GetUIManager()->RegisterUIElements("Hybrid Reflections", UISectionType::Sample);
|
||
|
|
||
|
std::vector<const char*> debugOptions;
|
||
|
|
||
|
std::function<void(bool, bool)> showDebugTargetCallback = [this](bool cur, bool old) { ShowDebugTarget(); };
|
||
|
uiSection->RegisterUIElement<UICheckBox>("Show Debug Target", m_ShowDebugTarget, showDebugTargetCallback);
|
||
|
std::function<void(int32_t, int32_t)> debugOptionCallback = [this](int32_t cur, int32_t old) { SelectDebugOption(); };
|
||
|
m_UIDebugOption = uiSection->RegisterUIElement<UICombo>("Visualizer", (int32_t&)m_DebugOption, BuildDebugOptions(m_EnableHybridReflection), m_ShowDebugTarget, debugOptionCallback);
|
||
|
|
||
|
uiSection->RegisterUIElement<UISlider<float>>("Global Roughness Threshold", m_RoughnessThreshold, 0.f, 1.f);
|
||
|
uiSection->RegisterUIElement<UISlider<float>>("RT Roughness Threshold", m_RTRoughnessThreshold, 0.f, 1.f);
|
||
|
uiSection->RegisterUIElement<UICheckBox>("Don't reshade", m_DisableReshading);
|
||
|
|
||
|
std::function<void(bool,bool)> enableHybridReflectionCallback = [this](bool cur, bool old) { ToggleHybridReflection(); };
|
||
|
uiSection->RegisterUIElement<UICheckBox>("Enable Hybrid Reflections", m_EnableHybridReflection, enableHybridReflectionCallback);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::InitApplyReflections(const json& initData)
|
||
|
{
|
||
|
RootSignatureDesc applyReflectionsSignatureDesc;
|
||
|
applyReflectionsSignatureDesc.AddConstantBufferView(0, ShaderBindStage::Pixel, 1);
|
||
|
applyReflectionsSignatureDesc.AddTextureSRVSet(0, ShaderBindStage::Pixel, 1);
|
||
|
applyReflectionsSignatureDesc.AddTextureSRVSet(1, ShaderBindStage::Pixel, 1);
|
||
|
applyReflectionsSignatureDesc.AddTextureSRVSet(2, ShaderBindStage::Pixel, 1);
|
||
|
applyReflectionsSignatureDesc.AddTextureSRVSet(3, ShaderBindStage::Pixel, 1);
|
||
|
applyReflectionsSignatureDesc.AddTextureSRVSet(4, ShaderBindStage::Pixel, 1);
|
||
|
applyReflectionsSignatureDesc.AddTextureSRVSet(5, ShaderBindStage::Pixel, 1);
|
||
|
applyReflectionsSignatureDesc.AddTextureSRVSet(6, ShaderBindStage::Pixel, 1);
|
||
|
applyReflectionsSignatureDesc.AddStaticSamplers(0, ShaderBindStage::Pixel, 1, &m_LinearSamplerDesc);
|
||
|
|
||
|
m_pApplyReflectionsRS = RootSignature::CreateRootSignature(L"HSR_ApplyReflections", applyReflectionsSignatureDesc);
|
||
|
|
||
|
BlendDesc blendDesc = {};
|
||
|
blendDesc.BlendEnabled = true;
|
||
|
blendDesc.SourceBlendColor = Blend::One;
|
||
|
blendDesc.ColorOp = BlendOp::Add;
|
||
|
blendDesc.DestBlendColor = Blend::SrcAlpha;
|
||
|
blendDesc.SourceBlendAlpha = Blend::One;
|
||
|
blendDesc.AlphaOp = BlendOp::Add;
|
||
|
blendDesc.DestBlendAlpha = Blend::One;
|
||
|
const std::vector<BlendDesc> blendDescs = {blendDesc};
|
||
|
|
||
|
DefineList defineList;
|
||
|
defineList.insert(std::make_pair(L"HSR_DEBUG", std::to_wstring(1)));
|
||
|
|
||
|
// Setup the pipeline object
|
||
|
PipelineDesc psoDesc;
|
||
|
psoDesc.SetRootSignature(m_pApplyReflectionsRS);
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Vertex(L"fullscreen.hlsl", L"FullscreenVS", ShaderModel::SM6_0, nullptr));
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Pixel(L"apply_reflections.hlsl", L"ps_main", ShaderModel::SM6_0, &defineList));
|
||
|
psoDesc.AddPrimitiveTopology(PrimitiveTopologyType::Triangle);
|
||
|
psoDesc.AddBlendStates(blendDescs, false, false);
|
||
|
psoDesc.AddRasterFormats(m_pColorTarget->GetFormat()); // Use the first raster set, as we just want the format and they are all the same
|
||
|
|
||
|
m_pApplyReflectionsPipeline = PipelineObject::CreatePipelineObject(L"HSR_ApplyReflections", psoDesc);
|
||
|
|
||
|
m_pParamSet = ParameterSet::CreateParameterSet(m_pApplyReflectionsRS);
|
||
|
m_pParamSet->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(FrameInfo), 0);
|
||
|
m_pParamSet->SetTextureSRV(m_pOutput, ViewDimension::Texture2D, 0);
|
||
|
m_pParamSet->SetTextureSRV(m_pNormal, ViewDimension::Texture2D, 1);
|
||
|
m_pParamSet->SetTextureSRV(m_pAoRoughnessMetallic, ViewDimension::Texture2D, 2);
|
||
|
m_pParamSet->SetTextureSRV(m_pDepthTarget, ViewDimension::Texture2D, 4);
|
||
|
m_pParamSet->SetTextureSRV(m_pDebugImage, ViewDimension::Texture2D, 5);
|
||
|
m_pParamSet->SetTextureSRV(m_pAlbedo, ViewDimension::Texture2D, 6);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::InitPrepareBlueNoise(const json& initData)
|
||
|
{
|
||
|
// Root signature
|
||
|
RootSignatureDesc signatureDesc;
|
||
|
signatureDesc.AddConstantBufferView(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureUAVSet(0, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
m_pPrepareBlueNoiseRootSignature = RootSignature::CreateRootSignature(L"PrepareBlueNoise_RootSignature", signatureDesc);
|
||
|
|
||
|
// Setup the pipeline object
|
||
|
PipelineDesc psoDesc;
|
||
|
psoDesc.SetRootSignature(m_pPrepareBlueNoiseRootSignature);
|
||
|
|
||
|
// Setup the shaders to build on the pipeline object
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Compute(L"prepare_blue_noise.hlsl", L"main", ShaderModel::SM6_5, nullptr));
|
||
|
|
||
|
m_pPrepareBlueNoisePipelineObj = PipelineObject::CreatePipelineObject(L"PrepareBlueNoise_PipelineObj", psoDesc);
|
||
|
|
||
|
// Create parameter set to bind constant buffer and texture
|
||
|
m_pPrepareBlueNoiseParameters = ParameterSet::CreateParameterSet(m_pPrepareBlueNoiseRootSignature);
|
||
|
m_pPrepareBlueNoiseParameters->SetBufferSRV(m_pSobol, 0);
|
||
|
m_pPrepareBlueNoiseParameters->SetBufferSRV(m_pScramblingTile, 1);
|
||
|
m_pPrepareBlueNoiseParameters->SetBufferSRV(m_pRankingTile, 2);
|
||
|
m_pPrepareBlueNoiseParameters->SetTextureUAV(m_pBlueNoiseTexture, ViewDimension::Texture2D, 0);
|
||
|
m_pPrepareBlueNoiseParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(FrameInfo), 0);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::InitPrimaryRayTracing(const json& initData)
|
||
|
{
|
||
|
// Root signature
|
||
|
RootSignatureDesc signatureDesc;
|
||
|
signatureDesc.AddConstantBufferView(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(3, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddTextureSRVSet(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddRTAccelerationStructureSet(2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(3, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(4, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(5, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(6, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddTextureSRVSet(SHADOW_MAP_BEGIN_SLOT, ShaderBindStage::Compute, MAX_SHADOW_MAP_TEXTURES_COUNT); // shadow maps
|
||
|
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 3, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddTextureSRVSet(TEXTURE_BEGIN_SLOT, ShaderBindStage::Compute, MAX_TEXTURES_COUNT);
|
||
|
|
||
|
signatureDesc.AddBufferSRVSet(INDEX_BUFFER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_BUFFER_COUNT);
|
||
|
signatureDesc.AddBufferSRVSet(VERTEX_BUFFER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_BUFFER_COUNT);
|
||
|
|
||
|
signatureDesc.AddTextureUAVSet(0, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddStaticSamplers(0, ShaderBindStage::Compute, 1, &m_SpecularSampler);
|
||
|
signatureDesc.AddStaticSamplers(1, ShaderBindStage::Compute, 1, &m_DiffuseSampler);
|
||
|
signatureDesc.AddStaticSamplers(2, ShaderBindStage::Compute, 1, &m_SpecularSampler);
|
||
|
signatureDesc.AddStaticSamplers(3, ShaderBindStage::Compute, 1, &m_ComparisonSampler);
|
||
|
|
||
|
signatureDesc.AddSamplerSet(SAMPLER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_SAMPLERS_COUNT);
|
||
|
|
||
|
m_pPrimaryRTRootSignature = RootSignature::CreateRootSignature(L"PrimaryRayTracing_RootSignature", signatureDesc);
|
||
|
|
||
|
// Setup the pipeline object
|
||
|
PipelineDesc psoDesc;
|
||
|
psoDesc.SetRootSignature(m_pPrimaryRTRootSignature);
|
||
|
|
||
|
// Setup the shaders to build on the pipeline object
|
||
|
//psoDesc.AddShaderDesc(ShaderBuildDesc::Compute(L"intersect.hlsl", L"main", ShaderModel::SM6_5, nullptr));
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Compute(L"primary_ray_tracing.hlsl", L"main", ShaderModel::SM6_5, nullptr));
|
||
|
|
||
|
m_pPrimaryRTPipelineObj = PipelineObject::CreatePipelineObject(L"PrimaryRayTracing_PipelineObj", psoDesc);
|
||
|
|
||
|
// Create parameter set to bind constant buffer and texture
|
||
|
m_pPrimaryRTParameters = ParameterSet::CreateParameterSet(m_pPrimaryRTRootSignature);
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(m_pDepthTarget, ViewDimension::Texture2D, 0);
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(m_pNormal, ViewDimension::Texture2D, 1);
|
||
|
m_pPrimaryRTParameters->SetAccelerationStructure(GetScene()->GetASManager()->GetTLAS(), 2);
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(m_pBlueNoiseTexture, ViewDimension::Texture2D, 6);
|
||
|
m_pPrimaryRTParameters->SetTextureUAV(m_pDebugImage, ViewDimension::Texture2D, 0);
|
||
|
|
||
|
ShadowMapResourcePool* pShadowMapResourcePool = GetFramework()->GetShadowMapResourcePool();
|
||
|
for (uint32_t i = 0; i < pShadowMapResourcePool->GetRenderTargetCount(); ++i)
|
||
|
{
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(pShadowMapResourcePool->GetRenderTarget(i), ViewDimension::Texture2D, SHADOW_MAP_BEGIN_SLOT + i);
|
||
|
}
|
||
|
|
||
|
m_pPrimaryRTParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(FrameInfo), 0);
|
||
|
m_pPrimaryRTParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(SceneInformation), 1);
|
||
|
m_pPrimaryRTParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(SceneLightingInformation), 2);
|
||
|
m_pPrimaryRTParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(LightingCBData), 3);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::InitHybridDeferred(const json& initData)
|
||
|
{
|
||
|
// Root signature
|
||
|
RootSignatureDesc signatureDesc;
|
||
|
signatureDesc.AddConstantBufferView(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(3, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddRTAccelerationStructureSet(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(3, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(4, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(5, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(6, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(7, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(8, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(9, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(10, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(11, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(12, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddTextureSRVSet(SHADOW_MAP_BEGIN_SLOT, ShaderBindStage::Compute, MAX_SHADOW_MAP_TEXTURES_COUNT); // shadow maps
|
||
|
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 3, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddTextureSRVSet(TEXTURE_BEGIN_SLOT, ShaderBindStage::Compute, MAX_TEXTURES_COUNT);
|
||
|
|
||
|
signatureDesc.AddBufferSRVSet(INDEX_BUFFER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_BUFFER_COUNT);
|
||
|
signatureDesc.AddBufferSRVSet(VERTEX_BUFFER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_BUFFER_COUNT);
|
||
|
|
||
|
signatureDesc.AddTextureUAVSet(0, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(2, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(4, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(6, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(7, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(8, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(9, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(10, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddStaticSamplers(0, ShaderBindStage::Compute, 1, &m_LinearSamplerDesc);
|
||
|
signatureDesc.AddStaticSamplers(1, ShaderBindStage::Compute, 1, &m_WrapLinearSamplerDesc);
|
||
|
signatureDesc.AddStaticSamplers(2, ShaderBindStage::Compute, 1, &m_SpecularSampler);
|
||
|
signatureDesc.AddStaticSamplers(3, ShaderBindStage::Compute, 1, &m_DiffuseSampler);
|
||
|
signatureDesc.AddStaticSamplers(4, ShaderBindStage::Compute, 1, &m_SpecularSampler);
|
||
|
signatureDesc.AddStaticSamplers(5, ShaderBindStage::Compute, 1, &m_ComparisonSampler);
|
||
|
|
||
|
signatureDesc.AddSamplerSet(SAMPLER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_SAMPLERS_COUNT);
|
||
|
|
||
|
m_pHybridDeferredRootSignature = RootSignature::CreateRootSignature(L"HybridDeferred_RootSignature", signatureDesc);
|
||
|
|
||
|
// Setup the pipeline object
|
||
|
PipelineDesc psoDesc;
|
||
|
psoDesc.SetRootSignature(m_pHybridDeferredRootSignature);
|
||
|
|
||
|
DefineList defineList;
|
||
|
defineList.insert(std::make_pair(L"USE_SSR", std::to_wstring(1)));
|
||
|
defineList.insert(std::make_pair(L"HSR_DEBUG", std::to_wstring(1)));
|
||
|
|
||
|
if (GetConfig()->InvertedDepth)
|
||
|
defineList.insert(std::make_pair(L"FFX_SSSR_OPTION_INVERTED_DEPTH", std::to_wstring(1)));
|
||
|
// Setup the shaders to build on the pipeline object
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Compute(L"intersect.hlsl", L"main", ShaderModel::SM6_5, &defineList));
|
||
|
|
||
|
m_pHybridDeferredPipelineObj = PipelineObject::CreatePipelineObject(L"HybridDeferred_PipelineObj", psoDesc);
|
||
|
|
||
|
// Create parameter set to bind constant buffer and texture
|
||
|
m_pHybridDeferredParameters = ParameterSet::CreateParameterSet(m_pHybridDeferredRootSignature);
|
||
|
m_pHybridDeferredParameters->SetAccelerationStructure(GetScene()->GetASManager()->GetTLAS(), 0);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pMotionVectors, ViewDimension::Texture2D, 4);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pNormal, ViewDimension::Texture2D, 5);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pDepthTarget, ViewDimension::Texture2D, 6);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pAoRoughnessMetallic, ViewDimension::Texture2D, 7);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pDepthHierarchy, ViewDimension::Texture2D, 8);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pExtractedRoughness, ViewDimension::Texture2D, 9);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pHistoryColorTarget, ViewDimension::Texture2D, 10);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pBlueNoiseTexture, ViewDimension::Texture2D, 11);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pAlbedo, ViewDimension::Texture2D, 12);
|
||
|
|
||
|
m_pHybridDeferredParameters->SetTextureUAV(m_pHitCounter0, ViewDimension::Texture2D, 0);
|
||
|
m_pHybridDeferredParameters->SetTextureUAV(m_pHitCounter1, ViewDimension::Texture2D, 1);
|
||
|
m_pHybridDeferredParameters->SetTextureUAV(m_pRadiance0, ViewDimension::Texture2D, 2);
|
||
|
m_pHybridDeferredParameters->SetTextureUAV(m_pRadiance1, ViewDimension::Texture2D, 3);
|
||
|
m_pHybridDeferredParameters->SetTextureUAV(m_pVariance0, ViewDimension::Texture2D, 4);
|
||
|
m_pHybridDeferredParameters->SetTextureUAV(m_pVariance1, ViewDimension::Texture2D, 5);
|
||
|
m_pHybridDeferredParameters->SetTextureUAV(m_pDebugImage, ViewDimension::Texture2D, 6);
|
||
|
m_pHybridDeferredParameters->SetBufferUAV(m_pHWRayList, 7);
|
||
|
m_pHybridDeferredParameters->SetBufferUAV(m_pRayList, 8);
|
||
|
m_pHybridDeferredParameters->SetBufferUAV(m_pRayCounter, 9);
|
||
|
m_pHybridDeferredParameters->SetBufferUAV(m_pRayGBufferList, 10);
|
||
|
|
||
|
ShadowMapResourcePool* pShadowMapResourcePool = GetFramework()->GetShadowMapResourcePool();
|
||
|
for (uint32_t i = 0; i < pShadowMapResourcePool->GetRenderTargetCount(); ++i)
|
||
|
{
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(pShadowMapResourcePool->GetRenderTarget(i), ViewDimension::Texture2D, SHADOW_MAP_BEGIN_SLOT + i);
|
||
|
}
|
||
|
|
||
|
m_pHybridDeferredParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(FrameInfo), 0);
|
||
|
m_pHybridDeferredParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(SceneInformation), 1);
|
||
|
m_pHybridDeferredParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(SceneLightingInformation), 2);
|
||
|
m_pHybridDeferredParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(LightingCBData), 3);
|
||
|
|
||
|
m_pHybridDeferredIndirectWorkload = IndirectWorkload::CreateIndirectWorkload(IndirectCommandType::Dispatch);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::InitRTDeferred(const json& initData)
|
||
|
{
|
||
|
// Root signature
|
||
|
RootSignatureDesc signatureDesc;
|
||
|
signatureDesc.AddConstantBufferView(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(3, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddRTAccelerationStructureSet(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(3, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(4, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(5, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(6, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(7, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(8, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(9, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(10, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(11, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(12, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddTextureSRVSet(SHADOW_MAP_BEGIN_SLOT, ShaderBindStage::Compute, MAX_SHADOW_MAP_TEXTURES_COUNT); // shadow maps
|
||
|
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 3, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddTextureSRVSet(TEXTURE_BEGIN_SLOT, ShaderBindStage::Compute, MAX_TEXTURES_COUNT);
|
||
|
|
||
|
signatureDesc.AddBufferSRVSet(INDEX_BUFFER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_BUFFER_COUNT);
|
||
|
signatureDesc.AddBufferSRVSet(VERTEX_BUFFER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_BUFFER_COUNT);
|
||
|
|
||
|
signatureDesc.AddTextureUAVSet(0, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(2, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(4, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(6, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(7, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(8, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(9, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(10, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddStaticSamplers(0, ShaderBindStage::Compute, 1, &m_LinearSamplerDesc);
|
||
|
signatureDesc.AddStaticSamplers(1, ShaderBindStage::Compute, 1, &m_WrapLinearSamplerDesc);
|
||
|
signatureDesc.AddStaticSamplers(2, ShaderBindStage::Compute, 1, &m_SpecularSampler);
|
||
|
signatureDesc.AddStaticSamplers(3, ShaderBindStage::Compute, 1, &m_DiffuseSampler);
|
||
|
signatureDesc.AddStaticSamplers(4, ShaderBindStage::Compute, 1, &m_SpecularSampler);
|
||
|
signatureDesc.AddStaticSamplers(5, ShaderBindStage::Compute, 1, &m_ComparisonSampler);
|
||
|
|
||
|
signatureDesc.AddSamplerSet(SAMPLER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_SAMPLERS_COUNT);
|
||
|
|
||
|
m_pRTDeferredRootSignature = RootSignature::CreateRootSignature(L"RTDeferred_RootSignature", signatureDesc);
|
||
|
|
||
|
// Setup the pipeline object
|
||
|
PipelineDesc psoDesc;
|
||
|
psoDesc.SetRootSignature(m_pRTDeferredRootSignature);
|
||
|
|
||
|
DefineList defineList;
|
||
|
defineList.insert(std::make_pair(L"USE_INLINE_RAYTRACING", std::to_wstring(1)));
|
||
|
defineList.insert(std::make_pair(L"HSR_DEBUG", std::to_wstring(1)));
|
||
|
defineList.insert(std::make_pair(L"USE_DEFERRED_RAYTRACING", std::to_wstring(1)));
|
||
|
if (GetConfig()->InvertedDepth)
|
||
|
defineList.insert(std::make_pair(L"FFX_SSSR_OPTION_INVERTED_DEPTH", std::to_wstring(1)));
|
||
|
// Setup the shaders to build on the pipeline object
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Compute(L"intersect.hlsl", L"main", ShaderModel::SM6_5, &defineList));
|
||
|
|
||
|
m_pRTDeferredPipelineObj = PipelineObject::CreatePipelineObject(L"RTDeferred_PipelineObj", psoDesc);
|
||
|
|
||
|
// Create parameter set to bind constant buffer and texture
|
||
|
m_pRTDeferredParameters = ParameterSet::CreateParameterSet(m_pRTDeferredRootSignature);
|
||
|
m_pRTDeferredParameters->SetAccelerationStructure(GetScene()->GetASManager()->GetTLAS(), 0);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pMotionVectors, ViewDimension::Texture2D, 4);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pNormal, ViewDimension::Texture2D, 5);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pDepthTarget, ViewDimension::Texture2D, 6);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pAoRoughnessMetallic, ViewDimension::Texture2D, 7);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pDepthHierarchy, ViewDimension::Texture2D, 8);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pExtractedRoughness, ViewDimension::Texture2D, 9);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pHistoryColorTarget, ViewDimension::Texture2D, 10);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pBlueNoiseTexture, ViewDimension::Texture2D, 11);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pAlbedo, ViewDimension::Texture2D, 12);
|
||
|
|
||
|
m_pRTDeferredParameters->SetTextureUAV(m_pHitCounter0, ViewDimension::Texture2D, 0);
|
||
|
m_pRTDeferredParameters->SetTextureUAV(m_pHitCounter1, ViewDimension::Texture2D, 1);
|
||
|
m_pRTDeferredParameters->SetTextureUAV(m_pRadiance0, ViewDimension::Texture2D, 2);
|
||
|
m_pRTDeferredParameters->SetTextureUAV(m_pRadiance1, ViewDimension::Texture2D, 3);
|
||
|
m_pRTDeferredParameters->SetTextureUAV(m_pVariance0, ViewDimension::Texture2D, 4);
|
||
|
m_pRTDeferredParameters->SetTextureUAV(m_pVariance1, ViewDimension::Texture2D, 5);
|
||
|
m_pRTDeferredParameters->SetTextureUAV(m_pDebugImage, ViewDimension::Texture2D, 6);
|
||
|
m_pRTDeferredParameters->SetBufferUAV(m_pHWRayList, 7);
|
||
|
m_pRTDeferredParameters->SetBufferUAV(m_pRayList, 8);
|
||
|
m_pRTDeferredParameters->SetBufferUAV(m_pRayCounter, 9);
|
||
|
m_pRTDeferredParameters->SetBufferUAV(m_pRayGBufferList, 10);
|
||
|
|
||
|
ShadowMapResourcePool* pShadowMapResourcePool = GetFramework()->GetShadowMapResourcePool();
|
||
|
for (uint32_t i = 0; i < pShadowMapResourcePool->GetRenderTargetCount(); ++i)
|
||
|
{
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(pShadowMapResourcePool->GetRenderTarget(i), ViewDimension::Texture2D, SHADOW_MAP_BEGIN_SLOT + i);
|
||
|
}
|
||
|
|
||
|
m_pRTDeferredParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(FrameInfo), 0);
|
||
|
m_pRTDeferredParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(SceneInformation), 1);
|
||
|
m_pRTDeferredParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(SceneLightingInformation), 2);
|
||
|
m_pRTDeferredParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(LightingCBData), 3);
|
||
|
|
||
|
m_pRTDeferredIndirectWorkload = IndirectWorkload::CreateIndirectWorkload(IndirectCommandType::Dispatch);
|
||
|
}
|
||
|
void HybridReflectionsRenderModule::InitDeferredShadeRays(const json& initData)
|
||
|
{
|
||
|
// Root signature
|
||
|
RootSignatureDesc signatureDesc;
|
||
|
signatureDesc.AddConstantBufferView(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddConstantBufferView(3, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddRTAccelerationStructureSet(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(3, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(4, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(5, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(6, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(7, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(8, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(9, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(10, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(11, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(12, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddTextureSRVSet(SHADOW_MAP_BEGIN_SLOT, ShaderBindStage::Compute, MAX_SHADOW_MAP_TEXTURES_COUNT); // shadow maps
|
||
|
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 2, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferSRVSet(RAYTRACING_INFO_BEGIN_SLOT + 3, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddTextureSRVSet(TEXTURE_BEGIN_SLOT, ShaderBindStage::Compute, MAX_TEXTURES_COUNT);
|
||
|
|
||
|
signatureDesc.AddBufferSRVSet(INDEX_BUFFER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_BUFFER_COUNT);
|
||
|
signatureDesc.AddBufferSRVSet(VERTEX_BUFFER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_BUFFER_COUNT);
|
||
|
|
||
|
signatureDesc.AddTextureUAVSet(0, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(2, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(4, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(6, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(7, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(8, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(9, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(10, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
signatureDesc.AddStaticSamplers(0, ShaderBindStage::Compute, 1, &m_LinearSamplerDesc);
|
||
|
signatureDesc.AddStaticSamplers(1, ShaderBindStage::Compute, 1, &m_WrapLinearSamplerDesc);
|
||
|
signatureDesc.AddStaticSamplers(2, ShaderBindStage::Compute, 1, &m_SpecularSampler);
|
||
|
signatureDesc.AddStaticSamplers(3, ShaderBindStage::Compute, 1, &m_DiffuseSampler);
|
||
|
signatureDesc.AddStaticSamplers(4, ShaderBindStage::Compute, 1, &m_SpecularSampler);
|
||
|
signatureDesc.AddStaticSamplers(5, ShaderBindStage::Compute, 1, &m_ComparisonSampler);
|
||
|
|
||
|
signatureDesc.AddSamplerSet(SAMPLER_BEGIN_SLOT, ShaderBindStage::Compute, MAX_SAMPLERS_COUNT);
|
||
|
|
||
|
m_pDeferredShadeRaysRootSignature = RootSignature::CreateRootSignature(L"DeferredShadeRays_RootSignature", signatureDesc);
|
||
|
|
||
|
// Setup the pipeline object
|
||
|
PipelineDesc psoDesc;
|
||
|
psoDesc.SetRootSignature(m_pDeferredShadeRaysRootSignature);
|
||
|
|
||
|
DefineList defineList;
|
||
|
if (GetConfig()->InvertedDepth)
|
||
|
defineList.insert(std::make_pair(L"FFX_SSSR_OPTION_INVERTED_DEPTH", std::to_wstring(1)));
|
||
|
// Setup the shaders to build on the pipeline object
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Compute(L"intersect.hlsl", L"DeferredShade", ShaderModel::SM6_5, nullptr));
|
||
|
|
||
|
m_pDeferredShadeRaysPipelineObj = PipelineObject::CreatePipelineObject(L"DeferredShadeRays_PipelineObj", psoDesc);
|
||
|
|
||
|
// Create parameter set to bind constant buffer and texture
|
||
|
m_pDeferredShadeRaysParameters = ParameterSet::CreateParameterSet(m_pDeferredShadeRaysRootSignature);
|
||
|
m_pDeferredShadeRaysParameters->SetAccelerationStructure(GetScene()->GetASManager()->GetTLAS(), 0);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pMotionVectors, ViewDimension::Texture2D, 4);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pNormal, ViewDimension::Texture2D, 5);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pDepthTarget, ViewDimension::Texture2D, 6);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pAoRoughnessMetallic, ViewDimension::Texture2D, 7);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pDepthHierarchy, ViewDimension::Texture2D, 8);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pExtractedRoughness, ViewDimension::Texture2D, 9);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pHistoryColorTarget, ViewDimension::Texture2D, 10);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pBlueNoiseTexture, ViewDimension::Texture2D, 11);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pAlbedo, ViewDimension::Texture2D, 12);
|
||
|
|
||
|
m_pDeferredShadeRaysParameters->SetTextureUAV(m_pHitCounter0, ViewDimension::Texture2D, 0);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureUAV(m_pHitCounter1, ViewDimension::Texture2D, 1);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureUAV(m_pRadiance0, ViewDimension::Texture2D, 2);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureUAV(m_pRadiance1, ViewDimension::Texture2D, 3);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureUAV(m_pVariance0, ViewDimension::Texture2D, 4);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureUAV(m_pVariance1, ViewDimension::Texture2D, 5);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureUAV(m_pDebugImage, ViewDimension::Texture2D, 6);
|
||
|
m_pDeferredShadeRaysParameters->SetBufferUAV(m_pHWRayList, 7);
|
||
|
m_pDeferredShadeRaysParameters->SetBufferUAV(m_pRayList, 8);
|
||
|
m_pDeferredShadeRaysParameters->SetBufferUAV(m_pRayCounter, 9);
|
||
|
m_pDeferredShadeRaysParameters->SetBufferUAV(m_pRayGBufferList, 10);
|
||
|
|
||
|
ShadowMapResourcePool* pShadowMapResourcePool = GetFramework()->GetShadowMapResourcePool();
|
||
|
for (uint32_t i = 0; i < pShadowMapResourcePool->GetRenderTargetCount(); ++i)
|
||
|
{
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(pShadowMapResourcePool->GetRenderTarget(i), ViewDimension::Texture2D, SHADOW_MAP_BEGIN_SLOT + i);
|
||
|
}
|
||
|
|
||
|
m_pDeferredShadeRaysParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(FrameInfo), 0);
|
||
|
m_pDeferredShadeRaysParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(SceneInformation), 1);
|
||
|
m_pDeferredShadeRaysParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(SceneLightingInformation), 2);
|
||
|
m_pDeferredShadeRaysParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(LightingCBData), 3);
|
||
|
|
||
|
m_pDeferredShadeRaysIndirectWorkload = IndirectWorkload::CreateIndirectWorkload(IndirectCommandType::Dispatch);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::InitPrepareIndirectHybrid(const json& initData)
|
||
|
{
|
||
|
// Root signature
|
||
|
RootSignatureDesc signatureDesc;
|
||
|
signatureDesc.AddConstantBufferView(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(1, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
m_pPrepareIndirectHybridRootSignature = RootSignature::CreateRootSignature(L"PrepareIndirectHybrid_RootSignature", signatureDesc);
|
||
|
|
||
|
// Setup the pipeline object
|
||
|
PipelineDesc psoDesc;
|
||
|
psoDesc.SetRootSignature(m_pPrepareIndirectHybridRootSignature);
|
||
|
|
||
|
// Setup the shaders to build on the pipeline object
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Compute(L"prepare_indirect_args_hybrid.hlsl", L"main", ShaderModel::SM6_5, nullptr));
|
||
|
|
||
|
m_pPrepareIndirectHybridPipelineObj = PipelineObject::CreatePipelineObject(L"PrepareIndirectHybrid_PipelineObj", psoDesc);
|
||
|
|
||
|
// Create parameter set to bind constant buffer and texture
|
||
|
m_pPrepareIndirectHybridParameters = ParameterSet::CreateParameterSet(m_pPrepareIndirectHybridRootSignature);
|
||
|
m_pPrepareIndirectHybridParameters->SetBufferUAV(m_pRayCounter, 0);
|
||
|
m_pPrepareIndirectHybridParameters->SetBufferUAV(m_pIntersectionPassIndirectArgs, 1);
|
||
|
|
||
|
m_pPrepareIndirectHybridParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(FrameInfo), 0);
|
||
|
}
|
||
|
void HybridReflectionsRenderModule::InitPrepareIndirectHW(const json& initData)
|
||
|
{
|
||
|
// Root signature
|
||
|
RootSignatureDesc signatureDesc;
|
||
|
signatureDesc.AddBufferUAVSet(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddBufferUAVSet(1, ShaderBindStage::Compute, 1);
|
||
|
|
||
|
m_pPrepareIndirectHWRootSignature = RootSignature::CreateRootSignature(L"PrepareIndirectHW_RootSignature", signatureDesc);
|
||
|
|
||
|
// Setup the pipeline object
|
||
|
PipelineDesc psoDesc;
|
||
|
psoDesc.SetRootSignature(m_pPrepareIndirectHWRootSignature);
|
||
|
|
||
|
// Setup the shaders to build on the pipeline object
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Compute(L"prepare_indirect_args_hw.hlsl", L"main", ShaderModel::SM6_5, nullptr));
|
||
|
|
||
|
m_pPrepareIndirectHWPipelineObj = PipelineObject::CreatePipelineObject(L"PrepareIndirectHW_PipelineObj", psoDesc);
|
||
|
|
||
|
// Create parameter set to bind constant buffer and texture
|
||
|
m_pPrepareIndirectHWParameters = ParameterSet::CreateParameterSet(m_pPrepareIndirectHWRootSignature);
|
||
|
m_pPrepareIndirectHWParameters->SetBufferUAV(m_pRayCounter, 0);
|
||
|
m_pPrepareIndirectHWParameters->SetBufferUAV(m_pIntersectionPassIndirectArgs, 1);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::InitCopyDepth(const json& initData)
|
||
|
{
|
||
|
// Root signature
|
||
|
RootSignatureDesc signatureDesc;
|
||
|
signatureDesc.AddConstantBufferView(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureSRVSet(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureUAVSet(0, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureUAVSet(1, ShaderBindStage::Compute, 1);
|
||
|
signatureDesc.AddTextureUAVSet(2, ShaderBindStage::Compute, 2);
|
||
|
signatureDesc.AddTextureUAVSet(4, ShaderBindStage::Compute, 2);
|
||
|
|
||
|
m_pCopyDepthRootSignature = RootSignature::CreateRootSignature(L"CopyDepth_RootSignature", signatureDesc);
|
||
|
|
||
|
// Setup the pipeline object
|
||
|
PipelineDesc psoDesc;
|
||
|
psoDesc.SetRootSignature(m_pCopyDepthRootSignature);
|
||
|
|
||
|
// Setup the shaders to build on the pipeline object
|
||
|
psoDesc.AddShaderDesc(ShaderBuildDesc::Compute(L"copy_depth_and_reset_buffers.hlsl", L"main", ShaderModel::SM6_5, nullptr));
|
||
|
|
||
|
m_pCopyDepthPipelineObj = PipelineObject::CreatePipelineObject(L"CopyDepth_PipelineObj", psoDesc);
|
||
|
|
||
|
// Create parameter set to bind constant buffer and texture
|
||
|
m_pCopyDepthParameters = ParameterSet::CreateParameterSet(m_pCopyDepthRootSignature);
|
||
|
m_pCopyDepthParameters->SetTextureSRV(m_pDepthTarget, ViewDimension::Texture2D, 0);
|
||
|
m_pCopyDepthParameters->SetTextureUAV(m_pDepthHierarchy, ViewDimension::Texture2D, 0);
|
||
|
m_pCopyDepthParameters->SetTextureUAV(m_pDebugImage, ViewDimension::Texture2D, 1);
|
||
|
m_pCopyDepthParameters->SetTextureUAV(m_pVariance0, ViewDimension::Texture2D, 2);
|
||
|
m_pCopyDepthParameters->SetTextureUAV(m_pVariance1, ViewDimension::Texture2D, 3);
|
||
|
m_pCopyDepthParameters->SetTextureUAV(m_pRadiance0, ViewDimension::Texture2D, 4);
|
||
|
m_pCopyDepthParameters->SetTextureUAV(m_pRadiance1, ViewDimension::Texture2D, 5);
|
||
|
|
||
|
m_pCopyDepthParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(FrameInfo), 0);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::OnResize(const ResolutionInfo& resInfo)
|
||
|
{
|
||
|
if (!ModuleEnabled())
|
||
|
return;
|
||
|
|
||
|
int width = GetFramework()->GetResolutionInfo().RenderWidth;
|
||
|
int height = GetFramework()->GetResolutionInfo().RenderHeight;
|
||
|
m_ReflectionWidth = std::max(128u, uint32_t(width * m_ReflectionResolutionMultiplier));
|
||
|
m_ReflectionHeight = std::max(128u, uint32_t(height * m_ReflectionResolutionMultiplier));
|
||
|
m_IsResized = true;
|
||
|
|
||
|
// Need to recreate the HSR context on resource resize
|
||
|
ResetBackendContext();
|
||
|
}
|
||
|
|
||
|
constexpr uint32_t g_NumThreadX = 8;
|
||
|
constexpr uint32_t g_NumThreadY = 8;
|
||
|
|
||
|
void HybridReflectionsRenderModule::Execute(double deltaTime, CommandList* pCmdList)
|
||
|
{
|
||
|
if (!m_pBRDFTexture || !m_pPrefilteredEnvironmentMap || !m_pIrradianceEnvironmentMap)
|
||
|
{
|
||
|
m_pBRDFTexture = GetScene()->GetBRDFLutTexture();
|
||
|
m_pPrefilteredEnvironmentMap = GetScene()->GetIBLTexture(IBLTexture::Prefiltered);
|
||
|
m_pIrradianceEnvironmentMap = GetScene()->GetIBLTexture(IBLTexture::Irradiance);
|
||
|
|
||
|
// These might not yet be loaded
|
||
|
if (m_pBRDFTexture && m_pPrefilteredEnvironmentMap && m_pIrradianceEnvironmentMap)
|
||
|
{
|
||
|
m_pParamSet->SetTextureSRV(m_pBRDFTexture, ViewDimension::Texture2D, 3);
|
||
|
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pBRDFTexture, ViewDimension::Texture2D, 1);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pPrefilteredEnvironmentMap, ViewDimension::TextureCube, 2);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_pIrradianceEnvironmentMap, ViewDimension::TextureCube, 3);
|
||
|
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pBRDFTexture, ViewDimension::Texture2D, 1);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pPrefilteredEnvironmentMap, ViewDimension::TextureCube, 2);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_pIrradianceEnvironmentMap, ViewDimension::TextureCube, 3);
|
||
|
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pBRDFTexture, ViewDimension::Texture2D, 1);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pPrefilteredEnvironmentMap, ViewDimension::TextureCube, 2);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_pIrradianceEnvironmentMap, ViewDimension::TextureCube, 3);
|
||
|
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(m_pBRDFTexture, ViewDimension::Texture2D, 3);
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(m_pPrefilteredEnvironmentMap, ViewDimension::TextureCube, 4);
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(m_pIrradianceEnvironmentMap, ViewDimension::TextureCube, 5);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
std::lock_guard<std::mutex> pipelineLock(m_CriticalSection);
|
||
|
// Content not ready.
|
||
|
if (m_RTInfoTables.m_cpuSurfaceBuffer.size() == 0)
|
||
|
return;
|
||
|
|
||
|
int width = GetFramework()->GetResolutionInfo().RenderWidth;
|
||
|
int height = GetFramework()->GetResolutionInfo().RenderHeight;
|
||
|
m_ReflectionWidth = std::max(128u, uint32_t(width * m_ReflectionResolutionMultiplier));
|
||
|
m_ReflectionHeight = std::max(128u, uint32_t(height * m_ReflectionResolutionMultiplier));
|
||
|
UpdatePerFrameConstants();
|
||
|
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX HSR");
|
||
|
|
||
|
{
|
||
|
const bool isOddFrame = !!(m_FrameIndex & 1);
|
||
|
m_pRadianceA = isOddFrame ? m_pRadiance0 : m_pRadiance1;
|
||
|
m_pRadianceB = isOddFrame ? m_pRadiance1 : m_pRadiance0;
|
||
|
m_pVarianceA = isOddFrame ? m_pVariance0 : m_pVariance1;
|
||
|
m_pVarianceB = isOddFrame ? m_pVariance1 : m_pVariance0;
|
||
|
m_pHitCounterA = isOddFrame ? m_pHitCounter0 : m_pHitCounter1;
|
||
|
m_pHitCounterB = isOddFrame ? m_pHitCounter1 : m_pHitCounter0;
|
||
|
}
|
||
|
|
||
|
ExecutePrepareBlueNoise(deltaTime, pCmdList);
|
||
|
|
||
|
std::vector<Barrier> barriers;
|
||
|
for (uint32_t i = 0; i < m_RTInfoTables.m_IndexBuffers.size(); ++i)
|
||
|
{
|
||
|
barriers.push_back(Barrier::Transition(m_RTInfoTables.m_IndexBuffers[i]->GetResource(),
|
||
|
ResourceState::IndexBufferResource,
|
||
|
ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
}
|
||
|
|
||
|
for (uint32_t i = 0; i < m_RTInfoTables.m_VertexBuffers.size(); ++i)
|
||
|
{
|
||
|
barriers.push_back(Barrier::Transition(m_RTInfoTables.m_VertexBuffers[i]->GetResource(),
|
||
|
ResourceState::VertexBufferResource,
|
||
|
ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
}
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
if (m_ShowDebugTarget && (m_Mask & HSR_FLAGS_VISUALIZE_PRIMARY_RAYS))
|
||
|
{
|
||
|
ExecutePrimaryRayTracing(deltaTime, pCmdList);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ExecuteDepthDownsample(deltaTime, pCmdList);
|
||
|
ExecuteClassifier(deltaTime, pCmdList);
|
||
|
|
||
|
barriers.clear();
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pDebugImage->GetResource(), ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource, ResourceState::UnorderedAccess));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pRadianceA->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::UnorderedAccess));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pVarianceA->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::UnorderedAccess));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pHitCounterA->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::UnorderedAccess));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
ExecutePrepareIndirectHybrid(deltaTime, pCmdList);
|
||
|
|
||
|
if (m_EnableHybridReflection)
|
||
|
{
|
||
|
ExecuteHybridDeferred(deltaTime, pCmdList);
|
||
|
}
|
||
|
|
||
|
if (m_Mask & HSR_FLAGS_USE_RAY_TRACING)
|
||
|
{
|
||
|
ExecutePrepareIndirectHW(deltaTime, pCmdList);
|
||
|
ExecuteRTDeferred(deltaTime, pCmdList);
|
||
|
ExecuteDeferredShadeRays(deltaTime, pCmdList);
|
||
|
}
|
||
|
|
||
|
barriers.clear();
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pDebugImage->GetResource(), ResourceState::UnorderedAccess, ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pRadianceA->GetResource(), ResourceState::UnorderedAccess, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pVarianceA->GetResource(), ResourceState::UnorderedAccess, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pHitCounterA->GetResource(), ResourceState::UnorderedAccess, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
ExecuteDenoiser(deltaTime, pCmdList);
|
||
|
}
|
||
|
|
||
|
barriers.clear();
|
||
|
for (uint32_t i = 0; i < m_RTInfoTables.m_IndexBuffers.size(); ++i)
|
||
|
{
|
||
|
barriers.push_back(Barrier::Transition(m_RTInfoTables.m_IndexBuffers[i]->GetResource(),
|
||
|
ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource,
|
||
|
ResourceState::IndexBufferResource));
|
||
|
}
|
||
|
|
||
|
for (uint32_t i = 0; i < m_RTInfoTables.m_VertexBuffers.size(); ++i)
|
||
|
{
|
||
|
barriers.push_back(Barrier::Transition(m_RTInfoTables.m_VertexBuffers[i]->GetResource(),
|
||
|
ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource,
|
||
|
ResourceState::VertexBufferResource));
|
||
|
}
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
ExecuteApplyReflections(deltaTime, pCmdList);
|
||
|
|
||
|
// We are now done with upscaling
|
||
|
GetFramework()->SetUpscalingState(UpscalerState::PostUpscale);
|
||
|
|
||
|
m_FrameIndex++;
|
||
|
m_IsResized = false;
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::UpdatePerFrameConstants()
|
||
|
{
|
||
|
setFlag(m_Mask, HSR_FLAGS_SHADING_USE_SCREEN, m_DisableReshading);
|
||
|
setFlag(m_Mask, HSR_FLAGS_USE_SCREEN_SPACE, m_EnableHybridReflection);
|
||
|
|
||
|
const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo();
|
||
|
CameraComponent* pCamera = GetScene()->GetCurrentCamera();
|
||
|
|
||
|
memcpy(&m_FrameInfoConstants.inv_view_proj, &pCamera->GetInverseViewProjection(), sizeof(Mat4));
|
||
|
memcpy(&m_FrameInfoConstants.proj, &pCamera->GetProjection(), sizeof(Mat4));
|
||
|
memcpy(&m_FrameInfoConstants.inv_proj, &pCamera->GetInverseProjection(), sizeof(Mat4));
|
||
|
memcpy(&m_FrameInfoConstants.view, &pCamera->GetView(), sizeof(Mat4));
|
||
|
memcpy(&m_FrameInfoConstants.inv_view, &pCamera->GetInverseView(), sizeof(Mat4));
|
||
|
memcpy(&m_FrameInfoConstants.prev_view_proj, &pCamera->GetPreviousViewProjection(), sizeof(Mat4));
|
||
|
memcpy(&m_FrameInfoConstants.prev_view, &pCamera->GetPreviousView(), sizeof(Mat4));
|
||
|
|
||
|
m_FrameInfoConstants.frame_index = m_FrameIndex;
|
||
|
m_FrameInfoConstants.max_traversal_intersections = m_MaxTraversalIntersections;
|
||
|
m_FrameInfoConstants.min_traversal_occupancy = m_MinTraversalOccupancy;
|
||
|
m_FrameInfoConstants.most_detailed_mip = m_MostDetailedMip;
|
||
|
m_FrameInfoConstants.temporal_stability_factor = m_TemporalStabilityFactor;
|
||
|
m_FrameInfoConstants.ssr_confidence_threshold = m_SSRConfidenceThreshold;
|
||
|
m_FrameInfoConstants.depth_buffer_thickness = m_DepthBufferThickness;
|
||
|
m_FrameInfoConstants.roughness_threshold = m_RoughnessThreshold;
|
||
|
m_FrameInfoConstants.samples_per_quad = m_SamplesPerQuad;
|
||
|
m_FrameInfoConstants.temporal_variance_guided_tracing_enabled = m_TemporalVarianceGuidedTracingEnabled;
|
||
|
m_FrameInfoConstants.hsr_mask = m_Mask;
|
||
|
m_FrameInfoConstants.random_samples_per_pixel = m_RandomSamplesPerPixel;
|
||
|
m_FrameInfoConstants.base_width = resInfo.RenderWidth;
|
||
|
m_FrameInfoConstants.base_height = resInfo.RenderHeight;
|
||
|
m_FrameInfoConstants.reflection_width = m_ReflectionWidth;
|
||
|
m_FrameInfoConstants.reflection_height = m_ReflectionHeight;
|
||
|
m_FrameInfoConstants.hybrid_miss_weight = m_HybridMissWeight;
|
||
|
m_FrameInfoConstants.max_raytraced_distance = m_MaxRaytracedDistance;
|
||
|
m_FrameInfoConstants.hybrid_spawn_rate = m_HybridSpawnRate;
|
||
|
m_FrameInfoConstants.reflections_backfacing_threshold = m_ReflectionsBackfacingThreshold;
|
||
|
m_FrameInfoConstants.vrt_variance_threshold = m_VRTVarianceThreshold;
|
||
|
m_FrameInfoConstants.ssr_thickness_length_factor = m_SSRThicknessLengthFactor;
|
||
|
m_FrameInfoConstants.fsr_roughness_threshold = m_FSRRoughnessThreshold;
|
||
|
m_FrameInfoConstants.ray_length_exp_factor = m_RayLengthExpFactor;
|
||
|
m_FrameInfoConstants.rt_roughness_threshold = m_RTRoughnessThreshold;
|
||
|
m_FrameInfoConstants.reflection_factor = m_ReflectionFactor;
|
||
|
m_FrameInfoConstants.ibl_factor = GetScene()->GetIBLFactor();
|
||
|
m_FrameInfoConstants.emissive_factor = m_EmissiveFactor;
|
||
|
m_FrameInfoConstants.reset = m_IsResized;
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecutePrepareIndirectHybrid(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::Transition(m_pIntersectionPassIndirectArgs->GetResource(), ResourceState::IndirectArgument, ResourceState::UnorderedAccess));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
BufferAddressInfo sceneInfoBufferInfo;
|
||
|
sceneInfoBufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast<const void*>(&m_FrameInfoConstants));
|
||
|
m_pPrepareIndirectHybridParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo, 0);
|
||
|
|
||
|
m_pPrepareIndirectHybridParameters->Bind(pCmdList, m_pPrepareIndirectHybridPipelineObj);
|
||
|
|
||
|
SetPipelineState(pCmdList, m_pPrepareIndirectHybridPipelineObj);
|
||
|
|
||
|
Dispatch(pCmdList, 1, 1, 1);
|
||
|
|
||
|
barriers.clear();
|
||
|
barriers.push_back(Barrier::UAV(m_pRayCounter->GetResource()));
|
||
|
barriers.push_back(Barrier::Transition(m_pIntersectionPassIndirectArgs->GetResource(), ResourceState::UnorderedAccess, ResourceState::IndirectArgument));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecutePrepareIndirectHW(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::Transition(m_pIntersectionPassIndirectArgs->GetResource(), ResourceState::IndirectArgument, ResourceState::UnorderedAccess));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
m_pPrepareIndirectHWParameters->Bind(pCmdList, m_pPrepareIndirectHWPipelineObj);
|
||
|
|
||
|
SetPipelineState(pCmdList, m_pPrepareIndirectHWPipelineObj);
|
||
|
|
||
|
Dispatch(pCmdList, 1, 1, 1);
|
||
|
|
||
|
barriers.clear();
|
||
|
barriers.push_back(Barrier::UAV(m_pRayCounter->GetResource()));
|
||
|
barriers.push_back(Barrier::Transition(m_pIntersectionPassIndirectArgs->GetResource(), ResourceState::UnorderedAccess, ResourceState::IndirectArgument));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecuteApplyReflections(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX HSR ApplyReflections");
|
||
|
const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo();
|
||
|
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pColorTarget->GetResource(), ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource, ResourceState::RenderTargetResource));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
BeginRaster(pCmdList, 1, &m_pColorRasterView);
|
||
|
|
||
|
// Allocate a dynamic constant buffer and set
|
||
|
BufferAddressInfo bufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), &m_FrameInfoConstants);
|
||
|
m_pParamSet->UpdateRootConstantBuffer(&bufferInfo, 0);
|
||
|
|
||
|
// Bind all parameters
|
||
|
m_pParamSet->Bind(pCmdList, m_pApplyReflectionsPipeline);
|
||
|
|
||
|
// Set pipeline and draw
|
||
|
Viewport vp = {0.f, 0.f, resInfo.fDisplayWidth(), resInfo.fDisplayHeight(), 0.f, 1.f};
|
||
|
SetViewport(pCmdList, &vp);
|
||
|
Rect scissorRect = {0, 0, resInfo.RenderWidth, resInfo.RenderHeight};
|
||
|
SetScissorRects(pCmdList, 1, &scissorRect);
|
||
|
SetPrimitiveTopology(pCmdList, PrimitiveTopology::TriangleList);
|
||
|
|
||
|
SetPipelineState(pCmdList, m_pApplyReflectionsPipeline);
|
||
|
DrawInstanced(pCmdList, 3, 1, 0, 0);
|
||
|
|
||
|
// End raster into cube map mip face
|
||
|
EndRaster(pCmdList);
|
||
|
|
||
|
barriers.clear();
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pColorTarget->GetResource(), ResourceState::RenderTargetResource, ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecutePrepareBlueNoise(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pBlueNoiseTexture->GetResource(), ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource, ResourceState::UnorderedAccess));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
BufferAddressInfo sceneInfoBufferInfo;
|
||
|
sceneInfoBufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast<const void*>(&m_FrameInfoConstants));
|
||
|
m_pPrepareBlueNoiseParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo, 0);
|
||
|
m_pPrepareBlueNoiseParameters->Bind(pCmdList, m_pPrepareBlueNoisePipelineObj);
|
||
|
|
||
|
SetPipelineState(pCmdList, m_pPrepareBlueNoisePipelineObj);
|
||
|
|
||
|
Dispatch(pCmdList, 128 / 8u, 128 / 8u, 1);
|
||
|
|
||
|
barriers.clear();
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pBlueNoiseTexture->GetResource(), ResourceState::UnorderedAccess, ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecuteDepthDownsample(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"HSR_DepthDownsample");
|
||
|
const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo();
|
||
|
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pDepthHierarchy->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::UnorderedAccess));
|
||
|
if (m_IsResized) {
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pVarianceB->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::UnorderedAccess));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pRadianceB->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::UnorderedAccess));
|
||
|
}
|
||
|
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
BufferAddressInfo sceneInfoBufferInfo;
|
||
|
sceneInfoBufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast<const void*>(&m_FrameInfoConstants));
|
||
|
m_pCopyDepthParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo, 0);
|
||
|
m_pCopyDepthParameters->Bind(pCmdList, m_pCopyDepthPipelineObj);
|
||
|
|
||
|
SetPipelineState(pCmdList, m_pCopyDepthPipelineObj);
|
||
|
|
||
|
Dispatch(pCmdList, DivideRoundingUp(resInfo.RenderWidth, 64u), DivideRoundingUp(resInfo.RenderHeight, 64u), 1);
|
||
|
|
||
|
barriers.clear();
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pDepthHierarchy->GetResource(), ResourceState::UnorderedAccess, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
if (m_IsResized)
|
||
|
{
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pVarianceB->GetResource(), ResourceState::UnorderedAccess, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pRadianceB->GetResource(), ResourceState::UnorderedAccess, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource));
|
||
|
}
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
FfxSpdDispatchDescription dispatchParameters = {};
|
||
|
dispatchParameters.commandList = SDKWrapper::ffxGetCommandList(pCmdList);
|
||
|
dispatchParameters.resource = SDKWrapper::ffxGetResource(m_pDepthHierarchy->GetResource(), L"HSR_DepthHierarchy", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ, FFX_RESOURCE_USAGE_ARRAYVIEW);
|
||
|
|
||
|
// Disabled until remaining things are fixes
|
||
|
FfxErrorCode errorCode = ffxSpdContextDispatch(&m_SpdContext, &dispatchParameters);
|
||
|
CAULDRON_ASSERT(errorCode == FFX_OK);
|
||
|
|
||
|
// FidelityFX contexts modify the set resource view heaps, so set the cauldron one back
|
||
|
SetAllResourceViewHeaps(pCmdList);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecutePrimaryRayTracing(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX HSR PrimaryRayTracing");
|
||
|
|
||
|
//Primary ray tracing
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pDebugImage->GetResource(), ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource, ResourceState::UnorderedAccess));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
|
||
|
// Allocate a dynamic constant buffers and set
|
||
|
LightingCBData lightingConstantData;
|
||
|
lightingConstantData.IBLFactor = GetScene()->GetIBLFactor();
|
||
|
lightingConstantData.SpecularIBLFactor = GetScene()->GetSpecularIBLFactor();
|
||
|
|
||
|
BufferAddressInfo sceneInfoBufferInfo[4];
|
||
|
sceneInfoBufferInfo[0] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast<const void*>(&m_FrameInfoConstants));
|
||
|
sceneInfoBufferInfo[1] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneInformation), reinterpret_cast<const void*>(&GetScene()->GetSceneInfo()));
|
||
|
sceneInfoBufferInfo[2] =
|
||
|
GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneLightingInformation), reinterpret_cast<const void*>(&GetScene()->GetSceneLightInfo()));
|
||
|
sceneInfoBufferInfo[3] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(LightingCBData), &lightingConstantData);
|
||
|
m_pPrimaryRTParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[0], 0);
|
||
|
m_pPrimaryRTParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[1], 1);
|
||
|
m_pPrimaryRTParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[2], 2);
|
||
|
m_pPrimaryRTParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[3], 3);
|
||
|
|
||
|
ShadowMapResourcePool* pShadowMapResourcePool = GetFramework()->GetShadowMapResourcePool();
|
||
|
CauldronAssert(
|
||
|
ASSERT_CRITICAL,
|
||
|
pShadowMapResourcePool->GetRenderTargetCount() <= MAX_SHADOW_MAP_TEXTURES_COUNT,
|
||
|
L"HybridReflectionsRenderModule can only support up to %d shadow maps. There are currently %d shadow maps",
|
||
|
MAX_SHADOW_MAP_TEXTURES_COUNT,
|
||
|
pShadowMapResourcePool->GetRenderTargetCount());
|
||
|
for (uint32_t i = 0; i < pShadowMapResourcePool->GetRenderTargetCount(); ++i)
|
||
|
{
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(pShadowMapResourcePool->GetRenderTarget(i), ViewDimension::Texture2D, SHADOW_MAP_BEGIN_SLOT + i);
|
||
|
}
|
||
|
// Bind all parameters
|
||
|
m_pPrimaryRTParameters->Bind(pCmdList, m_pPrimaryRTPipelineObj);
|
||
|
|
||
|
SetPipelineState(pCmdList, m_pPrimaryRTPipelineObj);
|
||
|
|
||
|
const uint32_t numGroupX = (m_pOutput->GetDesc().Width + g_NumThreadX - 1) / g_NumThreadX;
|
||
|
const uint32_t numGroupY = (m_pOutput->GetDesc().Height + g_NumThreadY - 1) / g_NumThreadY;
|
||
|
Dispatch(pCmdList, numGroupX, numGroupY, 1);
|
||
|
|
||
|
barriers.clear();
|
||
|
barriers.push_back(Barrier::Transition(
|
||
|
m_pDebugImage->GetResource(), ResourceState::UnorderedAccess, ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecuteHybridDeferred(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX HSR HybridDeferred");
|
||
|
|
||
|
// Allocate a dynamic constant buffers and set
|
||
|
LightingCBData lightingConstantData;
|
||
|
lightingConstantData.IBLFactor = GetScene()->GetIBLFactor();
|
||
|
lightingConstantData.SpecularIBLFactor = GetScene()->GetSpecularIBLFactor();
|
||
|
|
||
|
BufferAddressInfo sceneInfoBufferInfo[4];
|
||
|
sceneInfoBufferInfo[0] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast<const void*>(&m_FrameInfoConstants));
|
||
|
sceneInfoBufferInfo[1] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneInformation), reinterpret_cast<const void*>(&GetScene()->GetSceneInfo()));
|
||
|
sceneInfoBufferInfo[2] =
|
||
|
GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneLightingInformation), reinterpret_cast<const void*>(&GetScene()->GetSceneLightInfo()));
|
||
|
sceneInfoBufferInfo[3] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(LightingCBData), &lightingConstantData);
|
||
|
m_pHybridDeferredParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[0], 0);
|
||
|
m_pHybridDeferredParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[1], 1);
|
||
|
m_pHybridDeferredParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[2], 2);
|
||
|
m_pHybridDeferredParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[3], 3);
|
||
|
|
||
|
ShadowMapResourcePool* pShadowMapResourcePool = GetFramework()->GetShadowMapResourcePool();
|
||
|
CauldronAssert(
|
||
|
ASSERT_CRITICAL,
|
||
|
pShadowMapResourcePool->GetRenderTargetCount() <= MAX_SHADOW_MAP_TEXTURES_COUNT,
|
||
|
L"HybridReflectionsRenderModule can only support up to %d shadow maps. There are currently %d shadow maps",
|
||
|
MAX_SHADOW_MAP_TEXTURES_COUNT,
|
||
|
pShadowMapResourcePool->GetRenderTargetCount());
|
||
|
for (uint32_t i = 0; i < pShadowMapResourcePool->GetRenderTargetCount(); ++i)
|
||
|
{
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(pShadowMapResourcePool->GetRenderTarget(i), ViewDimension::Texture2D, SHADOW_MAP_BEGIN_SLOT + i);
|
||
|
}
|
||
|
|
||
|
// Bind all parameters
|
||
|
m_pHybridDeferredParameters->Bind(pCmdList, m_pHybridDeferredPipelineObj);
|
||
|
|
||
|
SetPipelineState(pCmdList, m_pHybridDeferredPipelineObj);
|
||
|
|
||
|
ExecuteIndirect(pCmdList, m_pHybridDeferredIndirectWorkload, m_pIntersectionPassIndirectArgs, 1, INDIRECT_ARGS_SW_OFFSET);
|
||
|
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::UAV(m_pRayCounter->GetResource()));
|
||
|
barriers.push_back(Barrier::UAV(m_pRadianceA->GetResource()));
|
||
|
barriers.push_back(Barrier::UAV(m_pVarianceA->GetResource()));
|
||
|
barriers.push_back(Barrier::UAV(m_pHWRayList->GetResource()));
|
||
|
barriers.push_back(Barrier::UAV(m_pDebugImage->GetResource()));
|
||
|
barriers.push_back(Barrier::UAV(m_pHitCounterA->GetResource()));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecuteRTDeferred(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX HSR RTDeferred");
|
||
|
|
||
|
// Allocate a dynamic constant buffers and set
|
||
|
LightingCBData lightingConstantData;
|
||
|
lightingConstantData.IBLFactor = GetScene()->GetIBLFactor();
|
||
|
lightingConstantData.SpecularIBLFactor = GetScene()->GetSpecularIBLFactor();
|
||
|
|
||
|
BufferAddressInfo sceneInfoBufferInfo[4];
|
||
|
sceneInfoBufferInfo[0] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast<const void*>(&m_FrameInfoConstants));
|
||
|
sceneInfoBufferInfo[1] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneInformation), reinterpret_cast<const void*>(&GetScene()->GetSceneInfo()));
|
||
|
sceneInfoBufferInfo[2] =
|
||
|
GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneLightingInformation), reinterpret_cast<const void*>(&GetScene()->GetSceneLightInfo()));
|
||
|
sceneInfoBufferInfo[3] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(LightingCBData), &lightingConstantData);
|
||
|
m_pRTDeferredParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[0], 0);
|
||
|
m_pRTDeferredParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[1], 1);
|
||
|
m_pRTDeferredParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[2], 2);
|
||
|
m_pRTDeferredParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[3], 3);
|
||
|
|
||
|
ShadowMapResourcePool* pShadowMapResourcePool = GetFramework()->GetShadowMapResourcePool();
|
||
|
CauldronAssert(
|
||
|
ASSERT_CRITICAL,
|
||
|
pShadowMapResourcePool->GetRenderTargetCount() <= MAX_SHADOW_MAP_TEXTURES_COUNT,
|
||
|
L"HybridReflectionsRenderModule can only support up to %d shadow maps. There are currently %d shadow maps",
|
||
|
MAX_SHADOW_MAP_TEXTURES_COUNT,
|
||
|
pShadowMapResourcePool->GetRenderTargetCount());
|
||
|
for (uint32_t i = 0; i < pShadowMapResourcePool->GetRenderTargetCount(); ++i)
|
||
|
{
|
||
|
m_pRTDeferredParameters->SetTextureSRV(pShadowMapResourcePool->GetRenderTarget(i), ViewDimension::Texture2D, SHADOW_MAP_BEGIN_SLOT + i);
|
||
|
}
|
||
|
|
||
|
// Bind all parameters
|
||
|
m_pRTDeferredParameters->Bind(pCmdList, m_pRTDeferredPipelineObj);
|
||
|
|
||
|
SetPipelineState(pCmdList, m_pRTDeferredPipelineObj);
|
||
|
|
||
|
ExecuteIndirect(pCmdList, m_pRTDeferredIndirectWorkload, m_pIntersectionPassIndirectArgs, 1, INDIRECT_ARGS_HW_OFFSET);
|
||
|
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::UAV(m_pRayGBufferList->GetResource()));
|
||
|
barriers.push_back(Barrier::UAV(m_pDebugImage->GetResource()));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecuteDeferredShadeRays(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX HSR DeferredShadeRays");
|
||
|
|
||
|
// Allocate a dynamic constant buffers and set
|
||
|
LightingCBData lightingConstantData;
|
||
|
lightingConstantData.IBLFactor = GetScene()->GetIBLFactor();
|
||
|
lightingConstantData.SpecularIBLFactor = GetScene()->GetSpecularIBLFactor();
|
||
|
|
||
|
BufferAddressInfo sceneInfoBufferInfo[4];
|
||
|
sceneInfoBufferInfo[0] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast<const void*>(&m_FrameInfoConstants));
|
||
|
sceneInfoBufferInfo[1] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneInformation), reinterpret_cast<const void*>(&GetScene()->GetSceneInfo()));
|
||
|
sceneInfoBufferInfo[2] =
|
||
|
GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneLightingInformation), reinterpret_cast<const void*>(&GetScene()->GetSceneLightInfo()));
|
||
|
sceneInfoBufferInfo[3] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(LightingCBData), &lightingConstantData);
|
||
|
m_pDeferredShadeRaysParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[0], 0);
|
||
|
m_pDeferredShadeRaysParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[1], 1);
|
||
|
m_pDeferredShadeRaysParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[2], 2);
|
||
|
m_pDeferredShadeRaysParameters->UpdateRootConstantBuffer(&sceneInfoBufferInfo[3], 3);
|
||
|
|
||
|
ShadowMapResourcePool* pShadowMapResourcePool = GetFramework()->GetShadowMapResourcePool();
|
||
|
CauldronAssert(
|
||
|
ASSERT_CRITICAL,
|
||
|
pShadowMapResourcePool->GetRenderTargetCount() <= MAX_SHADOW_MAP_TEXTURES_COUNT,
|
||
|
L"HybridReflectionsRenderModule can only support up to %d shadow maps. There are currently %d shadow maps",
|
||
|
MAX_SHADOW_MAP_TEXTURES_COUNT,
|
||
|
pShadowMapResourcePool->GetRenderTargetCount());
|
||
|
for (uint32_t i = 0; i < pShadowMapResourcePool->GetRenderTargetCount(); ++i)
|
||
|
{
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(pShadowMapResourcePool->GetRenderTarget(i), ViewDimension::Texture2D, SHADOW_MAP_BEGIN_SLOT + i);
|
||
|
}
|
||
|
// Bind all parameters
|
||
|
m_pDeferredShadeRaysParameters->Bind(pCmdList, m_pDeferredShadeRaysPipelineObj);
|
||
|
|
||
|
SetPipelineState(pCmdList, m_pDeferredShadeRaysPipelineObj);
|
||
|
|
||
|
ExecuteIndirect(pCmdList, m_pDeferredShadeRaysIndirectWorkload, m_pIntersectionPassIndirectArgs, 1, INDIRECT_ARGS_HW_OFFSET);
|
||
|
|
||
|
std::vector<Barrier> barriers;
|
||
|
barriers.push_back(Barrier::UAV(m_pRadianceA->GetResource()));
|
||
|
barriers.push_back(Barrier::UAV(m_pVarianceA->GetResource()));
|
||
|
ResourceBarrier(pCmdList, static_cast<uint32_t>(barriers.size()), barriers.data());
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecuteClassifier(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX HSR Classifier");
|
||
|
const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo();
|
||
|
CameraComponent* pCamera = GetScene()->GetCurrentCamera();
|
||
|
|
||
|
// All cauldron resources come into a render module in a generic read state (ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)
|
||
|
FfxClassifierReflectionDispatchDescription dispatchParameters = {};
|
||
|
dispatchParameters.commandList = SDKWrapper::ffxGetCommandList(pCmdList);
|
||
|
dispatchParameters.depth = SDKWrapper::ffxGetResource(m_pDepthTarget->GetResource(), L"HSR_InputDepth", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.motionVectors = SDKWrapper::ffxGetResource(m_pMotionVectors->GetResource(), L"HSR_InputMotionVectors", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.normal = SDKWrapper::ffxGetResource(m_pNormal->GetResource(), L"HSR_InputNormal", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.materialParameters =
|
||
|
SDKWrapper::ffxGetResource(m_pAoRoughnessMetallic->GetResource(), L"HSR_InputSpecularRoughness", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.environmentMap =
|
||
|
SDKWrapper::ffxGetResource(m_pPrefilteredEnvironmentMap->GetResource(), L"HSR_InputEnvironmentMapTexture", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.radiance = SDKWrapper::ffxGetResource(m_pRadianceA->GetResource(), L"HSR_Radiance", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.varianceHistory = SDKWrapper::ffxGetResource(m_pVarianceB->GetResource(), L"HSR_VarianceHistory", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.hitCounter = SDKWrapper::ffxGetResource(m_pHitCounterA->GetResource(), L"HSR_HitCounter", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.hitCounterHistory = SDKWrapper::ffxGetResource(m_pHitCounterB->GetResource(), L"HSR_HitCounterHistory", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.rayList = SDKWrapper::ffxGetResource(m_pRayList->GetResource(), L"HSR_RayList", FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
||
|
dispatchParameters.rayListHW = SDKWrapper::ffxGetResource(m_pHWRayList->GetResource(), L"HSR_RayListHW", FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
||
|
dispatchParameters.extractedRoughness =
|
||
|
SDKWrapper::ffxGetResource(m_pExtractedRoughness->GetResource(), L"HSR_ExtractedRoughness", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
dispatchParameters.rayCounter = SDKWrapper::ffxGetResource(m_pRayCounter->GetResource(), L"HSR_RayCounter", FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
||
|
dispatchParameters.denoiserTileList = SDKWrapper::ffxGetResource(m_pDenoiserTileList->GetResource(), L"HSR_DenoiserTileList", FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
||
|
dispatchParameters.renderSize.width = resInfo.RenderWidth;
|
||
|
dispatchParameters.renderSize.height = resInfo.RenderHeight;
|
||
|
dispatchParameters.motionVectorScale[0] = -1.f;
|
||
|
dispatchParameters.motionVectorScale[1] = -1.f;
|
||
|
dispatchParameters.normalsUnpackMul = 2.0f; // Cauldron's GBuffer stores normals in the [0, 1] range, SSSR exepects them in the [-1, 1] range.
|
||
|
dispatchParameters.normalsUnpackAdd = -1.0f; // Cauldron's GBuffer stores normals in the [0, 1] range, SSSR exepects them in the [-1, 1] range.
|
||
|
dispatchParameters.roughnessChannel = 1;
|
||
|
dispatchParameters.isRoughnessPerceptual = false;
|
||
|
dispatchParameters.iblFactor = GetScene()->GetIBLFactor();
|
||
|
dispatchParameters.samplesPerQuad = m_SamplesPerQuad;
|
||
|
dispatchParameters.temporalVarianceGuidedTracingEnabled = m_TemporalVarianceGuidedTracingEnabled;
|
||
|
dispatchParameters.globalRoughnessThreshold = m_RoughnessThreshold;
|
||
|
dispatchParameters.rtRoughnessThreshold = m_RTRoughnessThreshold;
|
||
|
dispatchParameters.mask = m_Mask;
|
||
|
dispatchParameters.reflectionWidth = m_ReflectionWidth;
|
||
|
dispatchParameters.reflectionHeight = m_ReflectionHeight;
|
||
|
dispatchParameters.hybridMissWeight = m_HybridMissWeight;
|
||
|
dispatchParameters.hybridSpawnRate = m_HybridSpawnRate;
|
||
|
dispatchParameters.vrtVarianceThreshold = m_VRTVarianceThreshold;
|
||
|
dispatchParameters.reflectionsBackfacingThreshold = m_ReflectionsBackfacingThreshold;
|
||
|
dispatchParameters.randomSamplesPerPixel = m_RandomSamplesPerPixel;
|
||
|
dispatchParameters.frameIndex = m_FrameIndex;
|
||
|
|
||
|
memcpy(&dispatchParameters.invViewProjection, &pCamera->GetInverseViewProjection(), sizeof(Mat4));
|
||
|
memcpy(&dispatchParameters.projection, &pCamera->GetProjection(), sizeof(Mat4));
|
||
|
memcpy(&dispatchParameters.invProjection, &pCamera->GetInverseProjection(), sizeof(Mat4));
|
||
|
memcpy(&dispatchParameters.view, &pCamera->GetView(), sizeof(Mat4));
|
||
|
memcpy(&dispatchParameters.invView, &pCamera->GetInverseView(), sizeof(Mat4));
|
||
|
memcpy(&dispatchParameters.prevViewProjection, &pCamera->GetPreviousViewProjection(), sizeof(Mat4));
|
||
|
|
||
|
FfxErrorCode errorCode = ffxClassifierContextReflectionDispatch(&m_ClassifierContext, &dispatchParameters);
|
||
|
CAULDRON_ASSERT(errorCode == FFX_OK);
|
||
|
|
||
|
// FidelityFX contexts modify the set resource view heaps, so set the cauldron one back
|
||
|
SetAllResourceViewHeaps(pCmdList);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::ExecuteDenoiser(double deltaTime, cauldron::CommandList* pCmdList)
|
||
|
{
|
||
|
GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX HSR Denoiser");
|
||
|
const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo();
|
||
|
CameraComponent* pCamera = GetScene()->GetCurrentCamera();
|
||
|
|
||
|
// Denoise
|
||
|
FfxDenoiserReflectionsDispatchDescription denoiserDispatchParameters = {};
|
||
|
denoiserDispatchParameters.commandList = SDKWrapper::ffxGetCommandList(pCmdList);
|
||
|
denoiserDispatchParameters.depthHierarchy = SDKWrapper::ffxGetResource(m_pDepthHierarchy->GetResource(), L"HSR_DepthHierarchy", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
denoiserDispatchParameters.motionVectors = SDKWrapper::ffxGetResource(m_pMotionVectors->GetResource(), L"HSR_MotionVectors", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
denoiserDispatchParameters.normal = SDKWrapper::ffxGetResource(m_pNormal->GetResource(), L"HSR_InputNormal", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
denoiserDispatchParameters.radianceA = SDKWrapper::ffxGetResource(m_pRadianceA->GetResource(), L"HSR_RadianceA", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
denoiserDispatchParameters.radianceB = SDKWrapper::ffxGetResource(m_pRadianceB->GetResource(), L"HSR_RadianceB", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
denoiserDispatchParameters.varianceA = SDKWrapper::ffxGetResource(m_pVarianceA->GetResource(), L"HSR_VarianceA", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
denoiserDispatchParameters.varianceB = SDKWrapper::ffxGetResource(m_pVarianceB->GetResource(), L"HSR_VarianceB", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
denoiserDispatchParameters.extractedRoughness =
|
||
|
SDKWrapper::ffxGetResource(m_pExtractedRoughness->GetResource(), L"HSR_ExtractedRoughness", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
denoiserDispatchParameters.denoiserTileList =
|
||
|
SDKWrapper::ffxGetResource(m_pDenoiserTileList->GetResource(), L"HSR_DenoiserTileList", FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
||
|
denoiserDispatchParameters.indirectArgumentsBuffer =
|
||
|
SDKWrapper::ffxGetResource(m_pIntersectionPassIndirectArgs->GetResource(), L"HSR_IndirectArgumentsBuffer ", FFX_RESOURCE_STATE_INDIRECT_ARGUMENT);
|
||
|
denoiserDispatchParameters.output = SDKWrapper::ffxGetResource(m_pOutput->GetResource(), L"HSR_Output", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
|
||
|
denoiserDispatchParameters.normalsUnpackMul = 2.0f; // Cauldron's GBuffer stores normals in the [0, 1] range, SSSR exepects them in the [-1, 1] range.
|
||
|
denoiserDispatchParameters.normalsUnpackAdd = -1.0f; // Cauldron's GBuffer stores normals in the [0, 1] range, SSSR exepects them in the [-1, 1] range.
|
||
|
denoiserDispatchParameters.motionVectorScale.x = 1.0f;
|
||
|
denoiserDispatchParameters.motionVectorScale.y = 1.0f;
|
||
|
denoiserDispatchParameters.renderSize.width = resInfo.RenderWidth;
|
||
|
denoiserDispatchParameters.renderSize.height = resInfo.RenderHeight;
|
||
|
denoiserDispatchParameters.roughnessThreshold = m_RoughnessThreshold;
|
||
|
denoiserDispatchParameters.frameIndex = m_FrameIndex;
|
||
|
denoiserDispatchParameters.temporalStabilityFactor = m_TemporalStabilityFactor;
|
||
|
denoiserDispatchParameters.reset = m_IsResized;
|
||
|
|
||
|
memcpy(&denoiserDispatchParameters.invProjection, &pCamera->GetInverseProjection(), sizeof(Mat4));
|
||
|
memcpy(&denoiserDispatchParameters.invView, &pCamera->GetInverseView(), sizeof(Mat4));
|
||
|
memcpy(&denoiserDispatchParameters.prevViewProjection, &pCamera->GetPreviousViewProjection(), sizeof(Mat4));
|
||
|
|
||
|
FfxErrorCode errorCode = ffxDenoiserContextDispatchReflections(&m_DenoiserContext, &denoiserDispatchParameters);
|
||
|
CAULDRON_ASSERT(errorCode == FFX_OK);
|
||
|
|
||
|
// FidelityFX contexts modify the set resource view heaps, so set the cauldron one back
|
||
|
SetAllResourceViewHeaps(pCmdList);
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::OnNewContentLoaded(ContentBlock* pContentBlock)
|
||
|
{
|
||
|
std::lock_guard<std::mutex> pipelineLock(m_CriticalSection);
|
||
|
// Material
|
||
|
uint32_t textureCount = 0;
|
||
|
for (auto* pMat : pContentBlock->Materials)
|
||
|
{
|
||
|
Material_Info materialInfo;
|
||
|
|
||
|
materialInfo.albedo_factor_x = pMat->GetAlbedoColor().getX();
|
||
|
materialInfo.albedo_factor_y = pMat->GetAlbedoColor().getY();
|
||
|
materialInfo.albedo_factor_z = pMat->GetAlbedoColor().getZ();
|
||
|
materialInfo.albedo_factor_w = pMat->GetAlbedoColor().getW();
|
||
|
|
||
|
materialInfo.emission_factor_x = pMat->GetEmissiveColor().getX();
|
||
|
materialInfo.emission_factor_y = pMat->GetEmissiveColor().getY();
|
||
|
materialInfo.emission_factor_z = pMat->GetEmissiveColor().getZ();
|
||
|
|
||
|
materialInfo.arm_factor_x = 1.0f;
|
||
|
materialInfo.arm_factor_y = pMat->GetPBRInfo().getY();
|
||
|
materialInfo.arm_factor_z = pMat->GetPBRInfo().getX();
|
||
|
|
||
|
materialInfo.is_opaque = pMat->GetBlendMode() == MaterialBlend::Opaque;
|
||
|
materialInfo.alpha_cutoff = pMat->GetAlphaCutOff();
|
||
|
|
||
|
int32_t samplerIndex;
|
||
|
if (pMat->HasPBRInfo())
|
||
|
{
|
||
|
materialInfo.albedo_tex_id = AddTexture(pMat, TextureClass::Albedo, samplerIndex);
|
||
|
materialInfo.albedo_tex_sampler_id = samplerIndex;
|
||
|
|
||
|
if (pMat->HasPBRMetalRough())
|
||
|
{
|
||
|
materialInfo.arm_tex_id = AddTexture(pMat, TextureClass::MetalRough, samplerIndex);
|
||
|
materialInfo.arm_tex_sampler_id = samplerIndex;
|
||
|
}
|
||
|
else if (pMat->HasPBRSpecGloss())
|
||
|
{
|
||
|
materialInfo.arm_tex_id = AddTexture(pMat, TextureClass::SpecGloss, samplerIndex);
|
||
|
materialInfo.arm_tex_sampler_id = samplerIndex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
materialInfo.normal_tex_id = AddTexture(pMat, TextureClass::Normal, samplerIndex);
|
||
|
materialInfo.normal_tex_sampler_id = samplerIndex;
|
||
|
materialInfo.emission_tex_id = AddTexture(pMat, TextureClass::Emissive, samplerIndex);
|
||
|
materialInfo.emission_tex_sampler_id = samplerIndex;
|
||
|
|
||
|
m_RTInfoTables.m_cpuMaterialBuffer.push_back(materialInfo);
|
||
|
}
|
||
|
|
||
|
MeshComponentMgr* pMeshComponentManager = MeshComponentMgr::Get();
|
||
|
|
||
|
uint32_t nodeID = 0, surfaceID = 0;
|
||
|
for (auto* pEntityData : pContentBlock->EntityDataBlocks)
|
||
|
{
|
||
|
for (auto* pComponent : pEntityData->Components)
|
||
|
{
|
||
|
if (pComponent->GetManager() == pMeshComponentManager)
|
||
|
{
|
||
|
Instance_Info instance_info{};
|
||
|
instance_info.surface_id_table_offset = (uint32_t)m_RTInfoTables.m_cpuSurfaceIDsBuffer.size();
|
||
|
const Mesh* pMesh = reinterpret_cast<MeshComponent*>(pComponent)->GetData().pMesh;
|
||
|
const size_t numSurfaces = pMesh->GetNumSurfaces();
|
||
|
size_t numOpaqueSurfaces = 0;
|
||
|
|
||
|
for (uint32_t i = 0; i < numSurfaces; ++i)
|
||
|
{
|
||
|
const Surface* pSurface = pMesh->GetSurface(i);
|
||
|
const Material* pMaterial = pSurface->GetMaterial();
|
||
|
|
||
|
m_RTInfoTables.m_cpuSurfaceIDsBuffer.push_back(surfaceID++);
|
||
|
|
||
|
Surface_Info surface_info{};
|
||
|
memset(&surface_info, -1, sizeof(surface_info));
|
||
|
surface_info.num_indices = pSurface->GetIndexBuffer().Count;
|
||
|
surface_info.num_vertices = pSurface->GetVertexBuffer(VertexAttributeType::Position).Count;
|
||
|
|
||
|
int foundIndex = -1;
|
||
|
for (size_t i = 0; i < m_RTInfoTables.m_IndexBuffers.size(); i++)
|
||
|
{
|
||
|
if (m_RTInfoTables.m_IndexBuffers[i] == pSurface->GetIndexBuffer().pBuffer)
|
||
|
{
|
||
|
foundIndex = (int)i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
surface_info.index_offset = foundIndex >= 0 ? foundIndex : (int)m_RTInfoTables.m_IndexBuffers.size();
|
||
|
if (foundIndex < 0) m_RTInfoTables.m_IndexBuffers.push_back(pSurface->GetIndexBuffer().pBuffer);
|
||
|
|
||
|
switch (pSurface->GetIndexBuffer().IndexFormat)
|
||
|
{
|
||
|
case ResourceFormat::R16_UINT:
|
||
|
surface_info.index_type = SURFACE_INFO_INDEX_TYPE_U16;
|
||
|
break;
|
||
|
case ResourceFormat::R32_UINT:
|
||
|
surface_info.index_type = SURFACE_INFO_INDEX_TYPE_U32;
|
||
|
break;
|
||
|
default:
|
||
|
CauldronError(L"Unsupported resource format for ray tracing indices");
|
||
|
}
|
||
|
|
||
|
uint32_t usedAttributes = VertexAttributeFlag_Position | VertexAttributeFlag_Normal | VertexAttributeFlag_Tangent |
|
||
|
VertexAttributeFlag_Texcoord0 | VertexAttributeFlag_Texcoord1;
|
||
|
|
||
|
const uint32_t surfaceAttributes = pSurface->GetVertexAttributes();
|
||
|
usedAttributes = usedAttributes & surfaceAttributes;
|
||
|
|
||
|
for (uint32_t attribute = 0; attribute < static_cast<uint32_t>(VertexAttributeType::Count); ++attribute)
|
||
|
{
|
||
|
// Check if the attribute is present
|
||
|
if (usedAttributes & (0x1 << attribute))
|
||
|
{
|
||
|
int foundIndex = -1;
|
||
|
for (size_t i = 0; i < m_RTInfoTables.m_VertexBuffers.size(); i++)
|
||
|
{
|
||
|
if (m_RTInfoTables.m_VertexBuffers[i] == pSurface->GetVertexBuffer(static_cast<VertexAttributeType>(attribute)).pBuffer)
|
||
|
{
|
||
|
foundIndex = (int)i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (foundIndex < 0) m_RTInfoTables.m_VertexBuffers.push_back(pSurface->GetVertexBuffer(static_cast<VertexAttributeType>(attribute)).pBuffer);
|
||
|
switch (static_cast<VertexAttributeType>(attribute))
|
||
|
{
|
||
|
case cauldron::VertexAttributeType::Position:
|
||
|
surface_info.position_attribute_offset = foundIndex >= 0 ? foundIndex : (int)m_RTInfoTables.m_VertexBuffers.size() - 1;
|
||
|
break;
|
||
|
case cauldron::VertexAttributeType::Normal:
|
||
|
surface_info.normal_attribute_offset = foundIndex >= 0 ? foundIndex : (int)m_RTInfoTables.m_VertexBuffers.size() - 1;
|
||
|
break;
|
||
|
case cauldron::VertexAttributeType::Tangent:
|
||
|
surface_info.tangent_attribute_offset = foundIndex >= 0 ? foundIndex : (int)m_RTInfoTables.m_VertexBuffers.size() - 1;
|
||
|
break;
|
||
|
case cauldron::VertexAttributeType::Texcoord0:
|
||
|
surface_info.texcoord0_attribute_offset = foundIndex >= 0 ? foundIndex : (int)m_RTInfoTables.m_VertexBuffers.size() - 1;
|
||
|
break;
|
||
|
case cauldron::VertexAttributeType::Texcoord1:
|
||
|
surface_info.texcoord1_attribute_offset = foundIndex >= 0 ? foundIndex : (int)m_RTInfoTables.m_VertexBuffers.size() - 1;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (size_t i = 0; i < pContentBlock->Materials.size(); i++)
|
||
|
{
|
||
|
if (pContentBlock->Materials[i] == pMaterial)
|
||
|
{
|
||
|
surface_info.material_id = (uint32_t)i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
m_RTInfoTables.m_cpuSurfaceBuffer.push_back(surface_info);
|
||
|
|
||
|
if (!pSurface->HasTranslucency())
|
||
|
numOpaqueSurfaces++;
|
||
|
}
|
||
|
|
||
|
instance_info.num_surfaces = (uint32_t)(numOpaqueSurfaces);
|
||
|
instance_info.num_opaque_surfaces = (uint32_t)(numSurfaces);
|
||
|
instance_info.node_id = nodeID++;
|
||
|
m_RTInfoTables.m_cpuInstanceBuffer.push_back(instance_info);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_RTInfoTables.m_cpuSurfaceBuffer.size() > 0)
|
||
|
{
|
||
|
// Upload
|
||
|
BufferDesc bufferMaterial = BufferDesc::Data(
|
||
|
L"HSR_MaterialBuffer", uint32_t(m_RTInfoTables.m_cpuMaterialBuffer.size() * sizeof(Material_Info)), sizeof(Material_Info), 0, ResourceFlags::None);
|
||
|
m_RTInfoTables.m_pMaterialBuffer = GetDynamicResourcePool()->CreateBuffer(&bufferMaterial, ResourceState::CopyDest);
|
||
|
const_cast<Buffer*>(m_RTInfoTables.m_pMaterialBuffer)
|
||
|
->CopyData(m_RTInfoTables.m_cpuMaterialBuffer.data(), m_RTInfoTables.m_cpuMaterialBuffer.size() * sizeof(Material_Info));
|
||
|
|
||
|
BufferDesc bufferInstance = BufferDesc::Data(
|
||
|
L"HSR_InstanceBuffer", uint32_t(m_RTInfoTables.m_cpuInstanceBuffer.size() * sizeof(Instance_Info)), sizeof(Instance_Info), 0, ResourceFlags::None);
|
||
|
m_RTInfoTables.m_pInstanceBuffer = GetDynamicResourcePool()->CreateBuffer(&bufferInstance, ResourceState::CopyDest);
|
||
|
const_cast<Buffer*>(m_RTInfoTables.m_pInstanceBuffer)
|
||
|
->CopyData(m_RTInfoTables.m_cpuInstanceBuffer.data(), m_RTInfoTables.m_cpuInstanceBuffer.size() * sizeof(Instance_Info));
|
||
|
|
||
|
BufferDesc bufferSurfaceID = BufferDesc::Data(
|
||
|
L"HSR_SurfaceIDBuffer", uint32_t(m_RTInfoTables.m_cpuSurfaceIDsBuffer.size() * sizeof(uint32_t)), sizeof(uint32_t), 0, ResourceFlags::None);
|
||
|
m_RTInfoTables.m_pSurfaceIDsBuffer = GetDynamicResourcePool()->CreateBuffer(&bufferSurfaceID, ResourceState::CopyDest);
|
||
|
const_cast<Buffer*>(m_RTInfoTables.m_pSurfaceIDsBuffer)
|
||
|
->CopyData(m_RTInfoTables.m_cpuSurfaceIDsBuffer.data(), m_RTInfoTables.m_cpuSurfaceIDsBuffer.size() * sizeof(uint32_t));
|
||
|
|
||
|
BufferDesc bufferSurface = BufferDesc::Data(
|
||
|
L"HSR_SurfaceBuffer", uint32_t(m_RTInfoTables.m_cpuSurfaceBuffer.size() * sizeof(Surface_Info)), sizeof(Surface_Info), 0, ResourceFlags::None);
|
||
|
m_RTInfoTables.m_pSurfaceBuffer = GetDynamicResourcePool()->CreateBuffer(&bufferSurface, ResourceState::CopyDest);
|
||
|
const_cast<Buffer*>(m_RTInfoTables.m_pSurfaceBuffer)
|
||
|
->CopyData(m_RTInfoTables.m_cpuSurfaceBuffer.data(), m_RTInfoTables.m_cpuSurfaceBuffer.size() * sizeof(Surface_Info));
|
||
|
|
||
|
m_pPrimaryRTParameters->SetBufferSRV(m_RTInfoTables.m_pMaterialBuffer, RAYTRACING_INFO_BEGIN_SLOT);
|
||
|
m_pPrimaryRTParameters->SetBufferSRV(m_RTInfoTables.m_pInstanceBuffer, RAYTRACING_INFO_BEGIN_SLOT + 1);
|
||
|
m_pPrimaryRTParameters->SetBufferSRV(m_RTInfoTables.m_pSurfaceIDsBuffer, RAYTRACING_INFO_BEGIN_SLOT + 2);
|
||
|
m_pPrimaryRTParameters->SetBufferSRV(m_RTInfoTables.m_pSurfaceBuffer, RAYTRACING_INFO_BEGIN_SLOT + 3);
|
||
|
|
||
|
m_pHybridDeferredParameters->SetBufferSRV(m_RTInfoTables.m_pMaterialBuffer, RAYTRACING_INFO_BEGIN_SLOT);
|
||
|
m_pHybridDeferredParameters->SetBufferSRV(m_RTInfoTables.m_pInstanceBuffer, RAYTRACING_INFO_BEGIN_SLOT + 1);
|
||
|
m_pHybridDeferredParameters->SetBufferSRV(m_RTInfoTables.m_pSurfaceIDsBuffer, RAYTRACING_INFO_BEGIN_SLOT + 2);
|
||
|
m_pHybridDeferredParameters->SetBufferSRV(m_RTInfoTables.m_pSurfaceBuffer, RAYTRACING_INFO_BEGIN_SLOT + 3);
|
||
|
|
||
|
m_pRTDeferredParameters->SetBufferSRV(m_RTInfoTables.m_pMaterialBuffer, RAYTRACING_INFO_BEGIN_SLOT);
|
||
|
m_pRTDeferredParameters->SetBufferSRV(m_RTInfoTables.m_pInstanceBuffer, RAYTRACING_INFO_BEGIN_SLOT + 1);
|
||
|
m_pRTDeferredParameters->SetBufferSRV(m_RTInfoTables.m_pSurfaceIDsBuffer, RAYTRACING_INFO_BEGIN_SLOT + 2);
|
||
|
m_pRTDeferredParameters->SetBufferSRV(m_RTInfoTables.m_pSurfaceBuffer, RAYTRACING_INFO_BEGIN_SLOT + 3);
|
||
|
|
||
|
m_pDeferredShadeRaysParameters->SetBufferSRV(m_RTInfoTables.m_pMaterialBuffer, RAYTRACING_INFO_BEGIN_SLOT);
|
||
|
m_pDeferredShadeRaysParameters->SetBufferSRV(m_RTInfoTables.m_pInstanceBuffer, RAYTRACING_INFO_BEGIN_SLOT + 1);
|
||
|
m_pDeferredShadeRaysParameters->SetBufferSRV(m_RTInfoTables.m_pSurfaceIDsBuffer, RAYTRACING_INFO_BEGIN_SLOT + 2);
|
||
|
m_pDeferredShadeRaysParameters->SetBufferSRV(m_RTInfoTables.m_pSurfaceBuffer, RAYTRACING_INFO_BEGIN_SLOT + 3);
|
||
|
}
|
||
|
|
||
|
{
|
||
|
// Update the parameter set with loaded texture entries
|
||
|
CauldronAssert(ASSERT_CRITICAL, m_RTInfoTables.m_Textures.size() <= MAX_TEXTURES_COUNT, L"Too many textures.");
|
||
|
for (uint32_t i = 0; i < m_RTInfoTables.m_Textures.size(); ++i)
|
||
|
{
|
||
|
m_pPrimaryRTParameters->SetTextureSRV(m_RTInfoTables.m_Textures[i].pTexture, ViewDimension::Texture2D, i + TEXTURE_BEGIN_SLOT);
|
||
|
m_pHybridDeferredParameters->SetTextureSRV(m_RTInfoTables.m_Textures[i].pTexture, ViewDimension::Texture2D, i + TEXTURE_BEGIN_SLOT);
|
||
|
m_pRTDeferredParameters->SetTextureSRV(m_RTInfoTables.m_Textures[i].pTexture, ViewDimension::Texture2D, i + TEXTURE_BEGIN_SLOT);
|
||
|
m_pDeferredShadeRaysParameters->SetTextureSRV(m_RTInfoTables.m_Textures[i].pTexture, ViewDimension::Texture2D, i + TEXTURE_BEGIN_SLOT);
|
||
|
}
|
||
|
|
||
|
// Update sampler bindings as well
|
||
|
CauldronAssert(ASSERT_CRITICAL, m_RTInfoTables.m_Samplers.size() <= MAX_SAMPLERS_COUNT, L"Too many samplers.");
|
||
|
for (uint32_t i = 0; i < m_RTInfoTables.m_Samplers.size(); ++i)
|
||
|
{
|
||
|
m_pPrimaryRTParameters->SetSampler(m_RTInfoTables.m_Samplers[i], i + SAMPLER_BEGIN_SLOT);
|
||
|
m_pHybridDeferredParameters->SetSampler(m_RTInfoTables.m_Samplers[i], i + SAMPLER_BEGIN_SLOT);
|
||
|
m_pRTDeferredParameters->SetSampler(m_RTInfoTables.m_Samplers[i], i + SAMPLER_BEGIN_SLOT);
|
||
|
m_pDeferredShadeRaysParameters->SetSampler(m_RTInfoTables.m_Samplers[i], i + SAMPLER_BEGIN_SLOT);
|
||
|
}
|
||
|
|
||
|
CauldronAssert(ASSERT_CRITICAL, m_RTInfoTables.m_IndexBuffers.size() <= MAX_BUFFER_COUNT, L"Too many index buffers.");
|
||
|
for (uint32_t i = 0; i < m_RTInfoTables.m_IndexBuffers.size(); ++i)
|
||
|
{
|
||
|
m_pPrimaryRTParameters->SetBufferSRV(m_RTInfoTables.m_IndexBuffers[i], i + INDEX_BUFFER_BEGIN_SLOT);
|
||
|
m_pHybridDeferredParameters->SetBufferSRV(m_RTInfoTables.m_IndexBuffers[i], i + INDEX_BUFFER_BEGIN_SLOT);
|
||
|
m_pRTDeferredParameters->SetBufferSRV(m_RTInfoTables.m_IndexBuffers[i], i + INDEX_BUFFER_BEGIN_SLOT);
|
||
|
m_pDeferredShadeRaysParameters->SetBufferSRV(m_RTInfoTables.m_IndexBuffers[i], i + INDEX_BUFFER_BEGIN_SLOT);
|
||
|
}
|
||
|
|
||
|
CauldronAssert(ASSERT_CRITICAL, m_RTInfoTables.m_VertexBuffers.size() <= MAX_BUFFER_COUNT, L"Too many vertex buffers.");
|
||
|
for (uint32_t i = 0; i < m_RTInfoTables.m_VertexBuffers.size(); ++i)
|
||
|
{
|
||
|
m_pPrimaryRTParameters->SetBufferSRV(m_RTInfoTables.m_VertexBuffers[i], i + VERTEX_BUFFER_BEGIN_SLOT);
|
||
|
m_pHybridDeferredParameters->SetBufferSRV(m_RTInfoTables.m_VertexBuffers[i], i + VERTEX_BUFFER_BEGIN_SLOT);
|
||
|
m_pRTDeferredParameters->SetBufferSRV(m_RTInfoTables.m_VertexBuffers[i], i + VERTEX_BUFFER_BEGIN_SLOT);
|
||
|
m_pDeferredShadeRaysParameters->SetBufferSRV(m_RTInfoTables.m_VertexBuffers[i], i + VERTEX_BUFFER_BEGIN_SLOT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::OnContentUnloaded(ContentBlock* pContentBlock)
|
||
|
{
|
||
|
for (auto materialInfo : m_RTInfoTables.m_cpuMaterialBuffer)
|
||
|
{
|
||
|
if (materialInfo.albedo_tex_id > 0)
|
||
|
RemoveTexture(materialInfo.albedo_tex_id);
|
||
|
if (materialInfo.arm_tex_id > 0)
|
||
|
RemoveTexture(materialInfo.arm_tex_id);
|
||
|
if (materialInfo.emission_tex_id > 0)
|
||
|
RemoveTexture(materialInfo.emission_tex_id);
|
||
|
if (materialInfo.normal_tex_id > 0)
|
||
|
RemoveTexture(materialInfo.normal_tex_id);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add texture index info and return the index to the texture in the texture array
|
||
|
int32_t HybridReflectionsRenderModule::AddTexture(const Material* pMaterial, const TextureClass textureClass, int32_t& textureSamplerIndex)
|
||
|
{
|
||
|
const cauldron::TextureInfo* pTextureInfo = pMaterial->GetTextureInfo(textureClass);
|
||
|
if (pTextureInfo != nullptr)
|
||
|
{
|
||
|
// Check if the texture's sampler is already one we have, and if not add it
|
||
|
for (textureSamplerIndex = 0; textureSamplerIndex < m_RTInfoTables.m_Samplers.size(); ++textureSamplerIndex)
|
||
|
{
|
||
|
if (m_RTInfoTables.m_Samplers[textureSamplerIndex]->GetDesc() == pTextureInfo->TexSamplerDesc)
|
||
|
break; // found
|
||
|
}
|
||
|
|
||
|
// If we didn't find the sampler, add it
|
||
|
if (textureSamplerIndex == m_RTInfoTables.m_Samplers.size())
|
||
|
{
|
||
|
Sampler* pSampler = Sampler::CreateSampler(L"HSRSampler", pTextureInfo->TexSamplerDesc);
|
||
|
CauldronAssert(ASSERT_WARNING, pSampler, L"Could not create sampler for loaded content %s", pTextureInfo->pTexture->GetDesc().Name.c_str());
|
||
|
m_RTInfoTables.m_Samplers.push_back(pSampler);
|
||
|
}
|
||
|
|
||
|
// Find a slot for the texture
|
||
|
int32_t firstFreeIndex = -1;
|
||
|
for (int32_t i = 0; i < m_RTInfoTables.m_Textures.size(); ++i)
|
||
|
{
|
||
|
RTInfoTables::BoundTexture& boundTexture = m_RTInfoTables.m_Textures[i];
|
||
|
|
||
|
// If this texture is already mapped, bump it's reference count
|
||
|
if (pTextureInfo->pTexture == boundTexture.pTexture)
|
||
|
{
|
||
|
boundTexture.count += 1;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
// Try to re-use an existing entry that was released
|
||
|
else if (firstFreeIndex < 0 && boundTexture.count == 0)
|
||
|
{
|
||
|
firstFreeIndex = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Texture wasn't found
|
||
|
RTInfoTables::BoundTexture b = {pTextureInfo->pTexture, 1};
|
||
|
if (firstFreeIndex < 0)
|
||
|
{
|
||
|
m_RTInfoTables.m_Textures.push_back(b);
|
||
|
return static_cast<int32_t>(m_RTInfoTables.m_Textures.size()) - 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_RTInfoTables.m_Textures[firstFreeIndex] = b;
|
||
|
return firstFreeIndex;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
void HybridReflectionsRenderModule::RemoveTexture(int32_t index)
|
||
|
{
|
||
|
if (index >= 0)
|
||
|
{
|
||
|
m_RTInfoTables.m_Textures[index].count -= 1;
|
||
|
if (m_RTInfoTables.m_Textures[index].count == 0)
|
||
|
{
|
||
|
m_RTInfoTables.m_Textures[index].pTexture = nullptr;
|
||
|
}
|
||
|
}
|
||
|
}
|