目录
项目介绍
NRD
全名Nvidia Real-time Denoiser ,是英伟达正在研发的一个时空双域降噪库,旨在处理低的RPP(ray per pixel)信号。
该技术的图形 API 环境是:DirectX11、DirectX12 以及 Vulkun。其集成方法有三种,其中一种可以是利用 Nvidia 的 NRI(NVIDIA Rendering Interface)包装上述三个 API,进行集成。
项目目标
在Falcor框架下集成nrd。
当前工作内容
根据官方伪代码设计集成思路
官方伪代码
//====================================================================================================================
// STEP 1 - DECLARATIONS
//====================================================================================================================
#include "NRIDescs.hpp"
#include "Extensions/NRIWrapperD3D12.h"
#include "Extensions/NRIHelper.h"
#include "NRD.h"
NrdIntegration NRD = NrdIntegration(maxNumberOfFramesInFlight);
struct NriInterface
: public nri::CoreInterface
, public nri::HelperInterface
, public nri::WrapperD3D12Interface
{};
NriInterface NRI;
nri::Device* nriDevice = nullptr;
//====================================================================================================================
// STEP 2 - WRAP NATIVE DEVICE
//====================================================================================================================
nri::DeviceCreationD3D12Desc deviceDesc = {};
deviceDesc.d3d12Device = ...;
deviceDesc.d3d12PhysicalAdapter = ...;
deviceDesc.d3d12GraphicsQueue = ...;
deviceDesc.enableNRIValidation = false;
// Wrap the device
nri::Result result = nri::CreateDeviceFromD3D12Device(deviceDesc, nriDevice);
// Get needed functionality
result = nri::GetInterface(*nriDevice, NRI_INTERFACE(nri::CoreInterface), (nri::CoreInterface*)&NRI);
result = nri::GetInterface(*nriDevice, NRI_INTERFACE(nri::HelperInterface), (nri::HelperInterface*)&NRI);
// Get needed "wrapper" extension, XXX - can be D3D11, D3D12 or VULKAN
result = nri::GetInterface(*nriDevice, NRI_INTERFACE(nri::WrapperXXXInterface), (nri::WrapperXXXInterface*)&NRI);
//====================================================================================================================
// STEP 3 - INITIALIZE NRD
//====================================================================================================================
const nrd::MethodDesc methodDescs[] =
{
// put neeeded methods here, like:
{ nrd::Method::REBLUR_DIFFUSE_SPECULAR, renderResolution.x, renderResolution.y },
};
nrd::DenoiserCreationDesc denoiserCreationDesc = {};
denoiserCreationDesc.requestedMethods = methodDescs;
denoiserCreationDesc.requestedMethodNum = methodNum;
bool result = NRD.Initialize(*nriDevice, NRI, NRI, denoiserCreationDesc);
//====================================================================================================================
// STEP 4 - WRAP NATIVE POINTERS
//====================================================================================================================
// Wrap the command buffer
nri::CommandBufferD3D12Desc cmdDesc = {};
cmdDesc.d3d12CommandList = (ID3D12GraphicsCommandList*)&d3d12CommandList;
cmdDesc.d3d12CommandAllocator = nullptr; // Not needed for NRD Integration layer
nri::CommandBuffer* cmdBuffer = nullptr;
NRI.CreateCommandBufferD3D12(*nriDevice, cmdDesc, cmdBuffer);
// Wrap required textures
nri::TextureTransitionBarrierDesc entryDescs[N] = {};
nri::Format entryFormat[N] = {};
for (uint32_t i = 0; i < N; i++)
{
nri::TextureTransitionBarrierDesc& entryDesc = entryDescs[i];
const MyResource& myResource = GetMyResource(i);
nri::TextureD3D12Desc textureDesc = {};
textureDesc.d3d12Resource = myResource->GetNativePointer();
NRI.CreateTextureD3D12(*nriDevice, textureDesc, (nri::Texture*&)entryDesc.texture );
// You need to specify the current state of the resource here, after denoising NRD can modify
// this state. Application must continue state tracking from this point.
// Useful information:
// SRV = nri::AccessBits::SHADER_RESOURCE, nri::TextureLayout::SHADER_RESOURCE
// UAV = nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::TextureLayout::GENERAL
entryDesc.nextAccess = ConvertResourceStateToAccessBits( myResource->GetCurrentState() );
entryDesc.nextLayout = ConvertResourceStateToLayout( myResource->GetCurrentState() );
}
//====================================================================================================================
// STEP 5 - DENOISE
//====================================================================================================================
// Populate common settings
// - for the first time use defaults
// - currently NRD supports only the following view space: X - right, Y - top, Z - forward or backward
nrd::CommonSettings commonSettings = {};
PopulateCommonSettings(commonSettings);
// Set settings for each denoiser
nrd::NrdXxxSettings settings = {};
PopulateDenoiserSettings(settings);
NRD.SetMethodSettings(nrd::Method::NRD_XXX, &settings);
// Fill up the user pool
NrdUserPool userPool =
{{
// Fill the required inputs and outputs in appropriate slots using entryDescs & entryFormat,
// applying remapping if necessary. Unused slots can be {nullptr, nri::Format::UNKNOWN}
}};
NRD.Denoise(*cmdBuffer, commonSettings, userPool);
// !!! IMPORTANT !!!
// NRD integration layer binds its own descriptor pool, don't forget to re-bind back your own descriptor pool (heap)
//====================================================================================================================
// STEP 6 - CLEANUP
//====================================================================================================================
for (uint32_t i = 0; i < N; i++)
NRI.DestroyTexture(entryDescs[i].texture);
NRI.DestroyCommandBuffer(*cmdBuffer);
//====================================================================================================================
// STEP 7 - DESTROY
//====================================================================================================================
NRD.Destroy();