// 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. #pragma once #include "core/contentmanager.h" #include "core/uimanager.h" #include "render/rendermodule.h" #include "shaders/declarations.h" #include "shaders/common_types.h" #include #include #include #include namespace cauldron { class ParameterSet; class PipelineObject; class RenderTarget; class ResourceView; struct RootSignatureDesc; class RootSignature; class Texture; class Sampler; class RasterView; class IndirectWorkload; } // namespace cauldron /// @defgroup FfxHybridReflectionsSample FidelityFX Hybrid Reflections sample /// Sample documentation for FidelityFX Hybrid Reflections /// /// @ingroup SDKEffects /// @defgroup HybridReflectionsRM HybridReflectionsRenderModule /// HybridReflectionsRenderModule Reference Documentation /// /// @ingroup FfxHybridReflectionsSample /// @{ /** * @class HybridReflectionsRenderModule * * HybridReflectionsRenderModule creates reflections effect by using ffx_classifier, ffx_spd ffx_denoiser * techniques. * * There are 3 main passes: * - classification * - intersection * - denoising */ class HybridReflectionsRenderModule : public cauldron::RenderModule, public cauldron::ContentListener { public: /** * @brief Constructor */ HybridReflectionsRenderModule() : RenderModule(L"HybridReflectionsRenderModule") {} /** * @brief Destructor */ virtual ~HybridReflectionsRenderModule(); /** * This function checks hardware suppport, builds user interface, creates GPU resources, sets up * callback functions, create pipeline objects and initializes ffx_classifier, ffx_spd, ffx_denoiser backend. */ void Init(const json& initData) override; /** * Recreate the FFX API context to resize internal resources. Called by the framework when the resolution changes. * @param resInfo New resolution info. */ void OnResize(const cauldron::ResolutionInfo& resInfo) override; /** * Update the Debug Option UI element. */ void UpdateUI(double deltaTime) override; /** * Dispatch all the shaders. */ void Execute(double deltaTime, cauldron::CommandList* pCmdList) override; /** * Prepare shading information for raytracing passes. */ virtual void OnNewContentLoaded(cauldron::ContentBlock* pContentBlock) override; /** * @copydoc ContentListener::OnContentUnloaded() */ virtual void OnContentUnloaded(cauldron::ContentBlock* pContentBlock) override; private: void CreateFfxContexts(); void DestroyFfxContexts(); void ResetBackendContext(); void CreateBackendContext(); /** * This callback function copies color buffer of current frame into HistoryColorBuffer * to be used for next frame. */ void CopyColorBufferCallback(double deltaTime, cauldron::CommandList* pCmdList); void ShowDebugTarget(); void SelectDebugOption(); void ToggleHybridReflection(); void ToggleHalfResGBuffer(); void UpdateReflectionResolution(); int32_t AddTexture(const cauldron::Material* pMaterial, const cauldron::TextureClass textureClass, int32_t& textureSamplerIndex); void RemoveTexture(int32_t index); void CreateResources(); void BuildUI(); void InitApplyReflections(const json& initData); void InitPrepareBlueNoise(const json& initData); void InitPrimaryRayTracing(const json& initData); void InitHybridDeferred(const json& initData); void InitRTDeferred(const json& initData); void InitDeferredShadeRays(const json& initData); void InitPrepareIndirectHybrid(const json& initData); void InitPrepareIndirectHW(const json& initData); void InitCopyDepth(const json& initData); void ExecutePrepareBlueNoise(double deltaTime, cauldron::CommandList* pCmdList); void ExecuteDepthDownsample(double deltaTime, cauldron::CommandList* pCmdList); void ExecutePrimaryRayTracing(double deltaTime, cauldron::CommandList* pCmdList); void ExecuteHybridDeferred(double deltaTime, cauldron::CommandList* pCmdList); void ExecuteRTDeferred(double deltaTime, cauldron::CommandList* pCmdList); void ExecuteDeferredShadeRays(double deltaTime, cauldron::CommandList* pCmdList); void ExecuteClassifier(double deltaTime, cauldron::CommandList* pCmdList); void ExecuteDenoiser(double deltaTime, cauldron::CommandList* pCmdList); void ExecutePrepareIndirectHybrid(double deltaTime, cauldron::CommandList* pCmdList); void ExecutePrepareIndirectHW(double deltaTime, cauldron::CommandList* pCmdList); void ExecuteApplyReflections(double deltaTime, cauldron::CommandList* pCmdList); void UpdatePerFrameConstants(); float m_SceneSpecularIBLFactor; // HSR Context members FfxInterface m_BackendInterface; FfxDenoiserContextDescription m_DenoiserInitializationParameters = {}; FfxDenoiserContext m_DenoiserContext; FfxClassifierContextDescription m_ClassifierInitializationParameters = {}; FfxClassifierContext m_ClassifierContext; FfxSpdContextDescription m_SpdInitializationParameters = {}; FfxSpdContext m_SpdContext; // Debug features bool m_ApplyScreenSpaceReflections = true; bool m_ShowReflectionTarget = false; uint32_t m_FrameIndex = 0; bool m_IsResized = false; // HSR settings float m_SSRConfidenceThreshold = 0.9f; float m_TemporalStabilityFactor = 0.7f; float m_DepthBufferThickness = 0.2f; int32_t m_MostDetailedMip = 0; uint32_t m_SamplesPerQuad = 4; bool m_TemporalVarianceGuidedTracingEnabled = false; float m_ReflectionResolutionMultiplier = 1.f; uint32_t m_ReflectionUpscaleMode = 3; float m_FSRRoughnessThreshold = 0.03f; float m_RoughnessThreshold = 0.22f; float m_RTRoughnessThreshold = 0.22f; bool m_DisableReshading = false; bool m_EnableHybridReflection = true; bool m_IsEnableHybridReflectionChanged = false; bool m_EnableHalfResGBuffer = false; bool m_ShowDebugTarget = false; uint32_t m_ReflectionWidth = 128; uint32_t m_ReflectionHeight = 128; float m_HybridMissWeight = 0.5f; float m_HybridSpawnRate = 0.02f; float m_VRTVarianceThreshold = 0.02f; float m_SSRThicknessLengthFactor = 0.01f; float m_ReflectionsBackfacingThreshold = 1.f; uint32_t m_RandomSamplesPerPixel = 32; float m_MaxRaytracedDistance = 100.f; float m_RayLengthExpFactor = 5.f; uint32_t m_MinTraversalOccupancy = 0; uint32_t m_MaxTraversalIntersections = 128; float m_EmissiveFactor = 30.f; float m_ReflectionFactor = 1.3f; uint32_t m_DebugOption = 0; uint32_t m_Mask = 0; bool m_HalfResGBufferDisabled = true; // HSR resources const cauldron::Texture* m_pColorTarget = nullptr; const cauldron::Texture* m_pHistoryColorTarget = nullptr; const cauldron::Texture* m_pDepthTarget = nullptr; const cauldron::Texture* m_pOutput = nullptr; const cauldron::Texture* m_pMotionVectors = nullptr; const cauldron::Texture* m_pNormal = nullptr; const cauldron::Texture* m_pAlbedo = nullptr; const cauldron::Texture* m_pAoRoughnessMetallic = nullptr; const cauldron::Texture* m_pPrefilteredEnvironmentMap = nullptr; const cauldron::Texture* m_pIrradianceEnvironmentMap = nullptr; const cauldron::Texture* m_pBRDFTexture = nullptr; const cauldron::Texture* m_pDepthHierarchy = nullptr; const cauldron::Texture* m_pExtractedRoughness = nullptr; const cauldron::Texture* m_pRadiance0 = nullptr; const cauldron::Texture* m_pRadiance1 = nullptr; const cauldron::Texture* m_pVariance0 = nullptr; const cauldron::Texture* m_pVariance1 = nullptr; const cauldron::Texture* m_pHitCounter0 = nullptr; const cauldron::Texture* m_pHitCounter1 = nullptr; const cauldron::Texture* m_pBlueNoiseTexture = nullptr; const cauldron::Texture* m_pDebugImage = nullptr; const cauldron::Texture* m_pRadianceA = nullptr; const cauldron::Texture* m_pRadianceB = nullptr; const cauldron::Texture* m_pVarianceA = nullptr; const cauldron::Texture* m_pVarianceB = nullptr; const cauldron::Texture* m_pHitCounterA = nullptr; const cauldron::Texture* m_pHitCounterB = nullptr; const cauldron::Buffer* m_pRayList = nullptr; const cauldron::Buffer* m_pHWRayList = nullptr; const cauldron::Buffer* m_pDenoiserTileList = nullptr; const cauldron::Buffer* m_pRayCounter = nullptr; const cauldron::Buffer* m_pIntersectionPassIndirectArgs = nullptr; const cauldron::Buffer* m_pRayGBufferList = nullptr; const cauldron::Buffer* m_pSobol = nullptr; const cauldron::Buffer* m_pScramblingTile = nullptr; const cauldron::Buffer* m_pRankingTile = nullptr; cauldron::SamplerDesc m_LinearSamplerDesc; cauldron::SamplerDesc m_WrapLinearSamplerDesc; cauldron::SamplerDesc m_EnvironmentSamplerDesc; cauldron::SamplerDesc m_ComparisonSampler; cauldron::SamplerDesc m_SpecularSampler; cauldron::SamplerDesc m_DiffuseSampler; const cauldron::RasterView* m_pColorRasterView = nullptr; cauldron::RootSignature* m_pApplyReflectionsRS = nullptr; cauldron::PipelineObject* m_pApplyReflectionsPipeline = nullptr; cauldron::ParameterSet* m_pParamSet = nullptr; struct RTInfoTables { struct BoundTexture { const cauldron::Texture* pTexture = nullptr; uint32_t count = 1; }; std::vector m_VertexBuffers; std::vector m_IndexBuffers; std::vector m_Textures; std::vector m_Samplers; std::vector m_cpuMaterialBuffer; std::vector m_cpuInstanceBuffer; std::vector m_cpuInstanceTransformBuffer; std::vector m_cpuSurfaceBuffer; std::vector m_cpuSurfaceIDsBuffer; const cauldron::Buffer* m_pMaterialBuffer = NULL; // material_id -> Material buffer const cauldron::Buffer* m_pSurfaceBuffer = NULL; // surface_id -> Surface_Info buffer const cauldron::Buffer* m_pSurfaceIDsBuffer = NULL; // flat array of uint32_t const cauldron::Buffer* m_pInstanceBuffer = NULL; // instance_id -> Instance_Info buffer } m_RTInfoTables; std::mutex m_CriticalSection; cauldron::RootSignature* m_pPrepareBlueNoiseRootSignature = nullptr; cauldron::PipelineObject* m_pPrepareBlueNoisePipelineObj = nullptr; cauldron::ParameterSet* m_pPrepareBlueNoiseParameters = nullptr; cauldron::RootSignature* m_pPrimaryRTRootSignature = nullptr; cauldron::PipelineObject* m_pPrimaryRTPipelineObj = nullptr; cauldron::ParameterSet* m_pPrimaryRTParameters = nullptr; cauldron::RootSignature* m_pHybridDeferredRootSignature = nullptr; cauldron::PipelineObject* m_pHybridDeferredPipelineObj = nullptr; cauldron::ParameterSet* m_pHybridDeferredParameters = nullptr; cauldron::IndirectWorkload* m_pHybridDeferredIndirectWorkload = nullptr; cauldron::RootSignature* m_pRTDeferredRootSignature = nullptr; cauldron::PipelineObject* m_pRTDeferredPipelineObj = nullptr; cauldron::ParameterSet* m_pRTDeferredParameters = nullptr; cauldron::IndirectWorkload* m_pRTDeferredIndirectWorkload = nullptr; cauldron::RootSignature* m_pDeferredShadeRaysRootSignature = nullptr; cauldron::PipelineObject* m_pDeferredShadeRaysPipelineObj = nullptr; cauldron::ParameterSet* m_pDeferredShadeRaysParameters = nullptr; cauldron::IndirectWorkload* m_pDeferredShadeRaysIndirectWorkload = nullptr; cauldron::RootSignature* m_pPrepareIndirectHybridRootSignature = nullptr; cauldron::PipelineObject* m_pPrepareIndirectHybridPipelineObj = nullptr; cauldron::ParameterSet* m_pPrepareIndirectHybridParameters = nullptr; cauldron::RootSignature* m_pPrepareIndirectHWRootSignature = nullptr; cauldron::PipelineObject* m_pPrepareIndirectHWPipelineObj = nullptr; cauldron::ParameterSet* m_pPrepareIndirectHWParameters = nullptr; cauldron::RootSignature* m_pCopyDepthRootSignature = nullptr; cauldron::PipelineObject* m_pCopyDepthPipelineObj = nullptr; cauldron::ParameterSet* m_pCopyDepthParameters = nullptr; FrameInfo m_FrameInfoConstants; cauldron::UICombo* m_UIDebugOption = nullptr; // weak ptr /// @} };