// 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 BuildDebugOptions(bool enable) { std::vector 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 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(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(barriers.size()), barriers.data()); } void HybridReflectionsRenderModule::ShowDebugTarget() { if (m_ShowDebugTarget) { m_Mask |= HSR_FLAGS_SHOW_DEBUG_TARGET; std::vector 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 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 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::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(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(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(m_pScramblingTile)->CopyData((void*)samplercpp::scramblingTile, sizeof(samplercpp::scramblingTile)); } void HybridReflectionsRenderModule::BuildUI() { UISection* uiSection = GetUIManager()->RegisterUIElements("Hybrid Reflections", UISectionType::Sample); std::vector debugOptions; std::function showDebugTargetCallback = [this](bool cur, bool old) { ShowDebugTarget(); }; uiSection->RegisterUIElement("Show Debug Target", m_ShowDebugTarget, showDebugTargetCallback); std::function debugOptionCallback = [this](int32_t cur, int32_t old) { SelectDebugOption(); }; m_UIDebugOption = uiSection->RegisterUIElement("Visualizer", (int32_t&)m_DebugOption, BuildDebugOptions(m_EnableHybridReflection), m_ShowDebugTarget, debugOptionCallback); uiSection->RegisterUIElement>("Global Roughness Threshold", m_RoughnessThreshold, 0.f, 1.f); uiSection->RegisterUIElement>("RT Roughness Threshold", m_RTRoughnessThreshold, 0.f, 1.f); uiSection->RegisterUIElement("Don't reshade", m_DisableReshading); std::function enableHybridReflectionCallback = [this](bool cur, bool old) { ToggleHybridReflection(); }; uiSection->RegisterUIElement("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 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 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 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(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(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(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(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 barriers; barriers.push_back(Barrier::Transition(m_pIntersectionPassIndirectArgs->GetResource(), ResourceState::IndirectArgument, ResourceState::UnorderedAccess)); ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); BufferAddressInfo sceneInfoBufferInfo; sceneInfoBufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast(&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(barriers.size()), barriers.data()); } void HybridReflectionsRenderModule::ExecutePrepareIndirectHW(double deltaTime, cauldron::CommandList* pCmdList) { std::vector barriers; barriers.push_back(Barrier::Transition(m_pIntersectionPassIndirectArgs->GetResource(), ResourceState::IndirectArgument, ResourceState::UnorderedAccess)); ResourceBarrier(pCmdList, static_cast(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(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 barriers; barriers.push_back(Barrier::Transition( m_pColorTarget->GetResource(), ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource, ResourceState::RenderTargetResource)); ResourceBarrier(pCmdList, static_cast(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(barriers.size()), barriers.data()); } void HybridReflectionsRenderModule::ExecutePrepareBlueNoise(double deltaTime, cauldron::CommandList* pCmdList) { std::vector barriers; barriers.push_back(Barrier::Transition( m_pBlueNoiseTexture->GetResource(), ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource, ResourceState::UnorderedAccess)); ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); BufferAddressInfo sceneInfoBufferInfo; sceneInfoBufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast(&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(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 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(barriers.size()), barriers.data()); BufferAddressInfo sceneInfoBufferInfo; sceneInfoBufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(FrameInfo), reinterpret_cast(&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(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 barriers; barriers.push_back(Barrier::Transition( m_pDebugImage->GetResource(), ResourceState::PixelShaderResource | ResourceState::NonPixelShaderResource, ResourceState::UnorderedAccess)); ResourceBarrier(pCmdList, static_cast(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(&m_FrameInfoConstants)); sceneInfoBufferInfo[1] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneInformation), reinterpret_cast(&GetScene()->GetSceneInfo())); sceneInfoBufferInfo[2] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneLightingInformation), reinterpret_cast(&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(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(&m_FrameInfoConstants)); sceneInfoBufferInfo[1] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneInformation), reinterpret_cast(&GetScene()->GetSceneInfo())); sceneInfoBufferInfo[2] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneLightingInformation), reinterpret_cast(&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 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(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(&m_FrameInfoConstants)); sceneInfoBufferInfo[1] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneInformation), reinterpret_cast(&GetScene()->GetSceneInfo())); sceneInfoBufferInfo[2] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneLightingInformation), reinterpret_cast(&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 barriers; barriers.push_back(Barrier::UAV(m_pRayGBufferList->GetResource())); barriers.push_back(Barrier::UAV(m_pDebugImage->GetResource())); ResourceBarrier(pCmdList, static_cast(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(&m_FrameInfoConstants)); sceneInfoBufferInfo[1] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneInformation), reinterpret_cast(&GetScene()->GetSceneInfo())); sceneInfoBufferInfo[2] = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SceneLightingInformation), reinterpret_cast(&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 barriers; barriers.push_back(Barrier::UAV(m_pRadianceA->GetResource())); barriers.push_back(Barrier::UAV(m_pVarianceA->GetResource())); ResourceBarrier(pCmdList, static_cast(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 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(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(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(attribute)).pBuffer) { foundIndex = (int)i; break; } } if (foundIndex < 0) m_RTInfoTables.m_VertexBuffers.push_back(pSurface->GetVertexBuffer(static_cast(attribute)).pBuffer); switch (static_cast(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(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(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(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(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(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; } } }