270 lines
11 KiB
C
270 lines
11 KiB
C
|
// This file is part of the FidelityFX SDK.
|
||
|
//
|
||
|
// Copyright (C) 2024 Advanced Micro Devices, Inc.
|
||
|
//
|
||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
// of this software and associated documentation files(the "Software"), to deal
|
||
|
// in the Software without restriction, including without limitation the rights
|
||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
|
||
|
// copies of the Software, and to permit persons to whom the Software is
|
||
|
// furnished to do so, subject to the following conditions :
|
||
|
//
|
||
|
// The above copyright notice and this permission notice shall be included in
|
||
|
// all copies or substantial portions of the Software.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
// THE SOFTWARE.
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include "render/rendermodule.h"
|
||
|
#include "render/sampler.h"
|
||
|
#include "render/shaderbuilder.h"
|
||
|
|
||
|
#include <FidelityFX/host/ffx_blur.h>
|
||
|
|
||
|
#include <tuple>
|
||
|
#include <vector>
|
||
|
|
||
|
namespace cauldron
|
||
|
{
|
||
|
class ParameterSet;
|
||
|
class PipelineObject;
|
||
|
class RootSignature;
|
||
|
class Texture;
|
||
|
} // namespace cauldron
|
||
|
|
||
|
/// @defgroup FfxBlurSample FidelityFX Blur sample
|
||
|
/// Sample documentation for FidelityFX Blur
|
||
|
///
|
||
|
/// @ingroup SDKEffects
|
||
|
|
||
|
/// @defgroup BlurRM BlurRenderModule
|
||
|
/// BlurRenderModule reference documentation
|
||
|
///
|
||
|
/// @ingroup FfxBlurSample
|
||
|
/// @{
|
||
|
|
||
|
/**
|
||
|
* @class BlurRenderModule
|
||
|
* BlurRenderModule handles a number of tasks related to Blur.
|
||
|
*
|
||
|
* BlurRenderModule takes care of:
|
||
|
* - creating UI section that enable users to switch between BLUR effect options: kernel size & floating point math type.
|
||
|
* - executes multiple different blur effects, including but not limited to FFX Blur.
|
||
|
* - implements a comparison mode for comparing quality and performance of FFX Blur
|
||
|
* to conventional blur implementations. Comparison mode displays the difference between
|
||
|
* two different blur effects (see blur_compare_filters_cs.hlsl). The magnitude of the
|
||
|
* difference can be amplified via UI configurable "Diff Factor".
|
||
|
*/
|
||
|
class BlurRenderModule : public cauldron::RenderModule
|
||
|
{
|
||
|
public:
|
||
|
/**
|
||
|
* @brief Constructor with default behavior.
|
||
|
*/
|
||
|
BlurRenderModule();
|
||
|
/**
|
||
|
* @brief Tear down the FFX API Context and release all resources.
|
||
|
*/
|
||
|
virtual ~BlurRenderModule();
|
||
|
|
||
|
/**
|
||
|
* @brief Initialize UI, also the FFX API Context and the other "conventional" blur effects.
|
||
|
*/
|
||
|
void Init(const json& initData) override;
|
||
|
|
||
|
/**
|
||
|
* @brief Execute the currently selected blur effect or execute the comparison mode shaders.
|
||
|
*/
|
||
|
void Execute(double deltaTime, cauldron::CommandList* pCmdList) override;
|
||
|
|
||
|
/**
|
||
|
* @brief Called by the framework when resolution changes.
|
||
|
*/
|
||
|
void OnResize(const cauldron::ResolutionInfo& resInfo) override;
|
||
|
|
||
|
private:
|
||
|
|
||
|
enum Algorithm
|
||
|
{
|
||
|
NONE = 0,
|
||
|
FIDELITYFX_BLUR_GAUSSIAN,
|
||
|
SINGLE_PASS_BOX_FILTER, // naive NxN filter
|
||
|
MULTI_PASS_SEPARABLE_FILTER, // Industry-standard 1xN filter, 2 passes, baked kernels
|
||
|
MULTI_PASS_SEPARABLE_FILTER_TRANSPOSE, // 2x horizontal passes, both transposing the output NxM -> MxN
|
||
|
NUM_GAUSSIAN_BLUR_ALGORITHMS,
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @brief Create and initialize m_BackendInterface.
|
||
|
*/
|
||
|
void InitFfxBackend();
|
||
|
/**
|
||
|
* @brief Create and initialize textures required for blur and comparison mode effects.
|
||
|
*/
|
||
|
void InitTextures();
|
||
|
/**
|
||
|
* @brief Create and initialize all of the blur compute pipelines and the comparison mode compute pipeline.
|
||
|
*/
|
||
|
void InitPipelines();
|
||
|
|
||
|
void CreatePassThroughPipeline(const wchar_t* computeShaderFilename);
|
||
|
void CreateSinglePassBoxFilterPipelines(
|
||
|
const wchar_t** ppSigmas, size_t sigmasCount, const wchar_t** ppKernelSizes, size_t kernelSizesCount, const wchar_t* comparisonFiltersComputeShader);
|
||
|
void CreateMultiPassSeparableFilterPipelines(
|
||
|
const wchar_t** ppSigmas, size_t sigmasCount, const wchar_t** ppKernelSizes, size_t kernelSizesCount, const wchar_t* comparisonFiltersComputeShader);
|
||
|
void CreateMultiPassSeparableTransposeFilterPipelines(
|
||
|
const wchar_t** ppSigmas, size_t sigmasCount, const wchar_t** ppKernelSizes, size_t kernelSizesCount, const wchar_t* comparisonFiltersComputeShader);
|
||
|
|
||
|
cauldron::PipelineObject* CreatePipeline(
|
||
|
cauldron::RootSignature* pRootSignature,
|
||
|
const std::wstring& pipelineName,
|
||
|
const std::wstring& shaderFile,
|
||
|
const std::wstring& entryFunc,
|
||
|
cauldron::DefineList& defines);
|
||
|
|
||
|
void CreateBlurContexts();
|
||
|
void DestroyBlurContexts();
|
||
|
|
||
|
size_t m_KernelSizesCount = 0u;
|
||
|
|
||
|
int32_t m_CurrentAlgorithm1 = 1;
|
||
|
int32_t m_CurrentGaussianSigma1 = 2;
|
||
|
int32_t m_CurrentKernelSize1 = 6; // defaults to 17x17
|
||
|
int32_t m_CurrentFpMath1 = 1;
|
||
|
|
||
|
FfxInterface m_BackendInterface = {0};
|
||
|
|
||
|
FfxBlurContext m_BlurContext1 = {};
|
||
|
bool m_BlurContext1Created = false;
|
||
|
FfxBlurContext m_BlurContext2 = {};
|
||
|
bool m_BlurContext2Created = false;
|
||
|
|
||
|
// 2nd Blur context is used for the comparison mode.
|
||
|
int32_t m_CurrentAlgorithm2 = 1;
|
||
|
int32_t m_CurrentGaussianSigma2 = 1;
|
||
|
int32_t m_CurrentKernelSize2 = 2; // defaults to 9x9
|
||
|
int32_t m_CurrentFpMath2 = 1;
|
||
|
|
||
|
cauldron::RootSignature* m_pFilterPipelineRootSig = nullptr;
|
||
|
|
||
|
cauldron::PipelineObject* m_pPassThroughPipeline = nullptr;
|
||
|
std::vector<cauldron::PipelineObject*> m_SinglePassBoxFilterPipelinesFp32;
|
||
|
std::vector<cauldron::PipelineObject*> m_SinglePassBoxFilterPipelinesFp16;
|
||
|
std::vector<cauldron::PipelineObject*> m_MultiPassSeparableFilterPipelinesFp32;
|
||
|
std::vector<cauldron::PipelineObject*> m_MultiPassSeparableFilterPipelinesFp16;
|
||
|
std::vector<cauldron::PipelineObject*> m_MultiPassSeparableTransposeFilterPipelinesFp32;
|
||
|
std::vector<cauldron::PipelineObject*> m_MultiPassSeparableTransposeFilterPipelinesFp16;
|
||
|
|
||
|
struct ParameterSets
|
||
|
{
|
||
|
~ParameterSets();
|
||
|
|
||
|
cauldron::ParameterSet* pNormalModeParams = nullptr;
|
||
|
|
||
|
cauldron::ParameterSet* pComparisonModeParams1 = nullptr;
|
||
|
cauldron::ParameterSet* pComparisonModeParams2 = nullptr;
|
||
|
};
|
||
|
|
||
|
ParameterSets m_SinglePassParams;
|
||
|
|
||
|
struct MultiPassParameterSets
|
||
|
{
|
||
|
~MultiPassParameterSets();
|
||
|
|
||
|
cauldron::ParameterSet* pPass1NormalModeParams = nullptr;
|
||
|
cauldron::ParameterSet* pPass2NormalModeParams = nullptr;
|
||
|
|
||
|
cauldron::ParameterSet* pPass1ComparisonModeParams1 = nullptr;
|
||
|
cauldron::ParameterSet* pPass2ComparisonModeParams1 = nullptr;
|
||
|
|
||
|
cauldron::ParameterSet* pPass1ComparisonModeParams2 = nullptr;
|
||
|
cauldron::ParameterSet* pPass2ComparisonModeParams2 = nullptr;
|
||
|
};
|
||
|
|
||
|
MultiPassParameterSets m_MultiPassParams;
|
||
|
MultiPassParameterSets m_MultiPassTransposeParams;
|
||
|
|
||
|
cauldron::RootSignature* m_pComparisonPipelineRootSig = nullptr;
|
||
|
cauldron::PipelineObject* m_pComparisonPipeline = nullptr;
|
||
|
cauldron::ParameterSet* m_pComparisonPipelineParams = nullptr;
|
||
|
|
||
|
bool m_ComparisonModeEnabled = false;
|
||
|
bool m_EnableFilterOptions1 = true;
|
||
|
bool m_EnableFilterOptions2 = false;
|
||
|
bool m_RebuildShaders = false;
|
||
|
|
||
|
const cauldron::Texture* m_pInput = nullptr;
|
||
|
const cauldron::Texture* m_pPass1Output = nullptr;
|
||
|
const cauldron::Texture* m_pTransposePass1Output = nullptr;
|
||
|
const cauldron::Texture* m_pOutput = nullptr;
|
||
|
|
||
|
const cauldron::Texture* m_pComparisonOutput1 = nullptr;
|
||
|
const cauldron::Texture* m_pComparisonOutput2 = nullptr;
|
||
|
|
||
|
struct Constants
|
||
|
{
|
||
|
uint32_t Width;
|
||
|
uint32_t Height;
|
||
|
};
|
||
|
|
||
|
void ExecutePassThrough(cauldron::CommandList* pCmdList, const wchar_t* pProfile, cauldron::ParameterSet* pParamSet);
|
||
|
|
||
|
void ExecuteSinglePassBoxFilter(cauldron::CommandList* pCmdList,
|
||
|
const wchar_t* pProfile,
|
||
|
cauldron::ParameterSet* pParameterSet,
|
||
|
int32_t kernelPerm,
|
||
|
int32_t kernelSize,
|
||
|
FfxBlurFloatPrecision floatPrecision);
|
||
|
|
||
|
using ParameterSetPair = std::pair<cauldron::ParameterSet*, cauldron::ParameterSet*>;
|
||
|
|
||
|
void ExecuteMultiPassFilter(cauldron::CommandList* pCmdList,
|
||
|
const wchar_t* pProfile,
|
||
|
ParameterSetPair& paramSets,
|
||
|
int32_t kernelPerm,
|
||
|
int32_t kernelSize,
|
||
|
FfxBlurFloatPrecision floatPrecision);
|
||
|
|
||
|
void ExecuteMultiPassTransposeFilter(cauldron::CommandList* pCmdList,
|
||
|
const wchar_t* pProfile,
|
||
|
ParameterSetPair& paramSets,
|
||
|
int32_t kernelPerm,
|
||
|
int32_t kernelSize,
|
||
|
FfxBlurFloatPrecision floatPrecision);
|
||
|
|
||
|
void ExecuteTwoPassFilter(cauldron::CommandList* pCmdList,
|
||
|
cauldron::PipelineObject* pPass1PipelineSet,
|
||
|
cauldron::PipelineObject* pPass2PipelineSet,
|
||
|
ParameterSetPair& paramSets,
|
||
|
const cauldron::Texture* pPass1Output);
|
||
|
|
||
|
using TexturePair = std::pair<const cauldron::Texture*, const cauldron::Texture*>;
|
||
|
|
||
|
void ExecuteBlurEffect(cauldron::CommandList* pCmdList,
|
||
|
const wchar_t* pProfile,
|
||
|
FfxBlurContext& blurContext,
|
||
|
const TexturePair& inputOutputPair,
|
||
|
FfxBlurKernelPermutation kernelPermutation,
|
||
|
FfxBlurKernelSize kernelSize);
|
||
|
|
||
|
void UpdateConstants(uint32_t width, uint32_t height, cauldron::ParameterSet* pParameterSet);
|
||
|
|
||
|
struct ComparisonConstants
|
||
|
{
|
||
|
uint32_t Width;
|
||
|
uint32_t Height;
|
||
|
float DiffFactor;
|
||
|
};
|
||
|
float m_DiffFactor = 1.0f;
|
||
|
void ExecuteComparisonPass(cauldron::CommandList* pCmdList);
|
||
|
|
||
|
/// @}
|
||
|
};
|