Skip to content

Commit

Permalink
v3.9.0:
Browse files Browse the repository at this point in the history
HIGHLIGHTS:
- NRD: added debug visualization (validation) layer
- NRD: added 2.5D MV support (2D screen space motion + delta viewZ)
- NRD: minor fixes
- REBLUR: improved specular tracking

DETAILS:
- NRD: fixed double clears if several denoisers are grouped into a single NRD instance
- NRD: reduced code entropy in denoisers using "history reset"
- NRD: removed unnecessary "nrd::" from C++ code
- REBLUR: fixed regression leading to using "smb" motion in cases where "vmb" motion is fully discarded, but "smb" motion is barely usable
- REBLUR: fixed regression due to migration to new "smb" accumulation speed calculation a few releases ago
- REBLUR: fixed bad interaction of anti-lag and partial split-screen mode
- REBLUR: fixed inconsistent pixel stride progression in HistoryFix pass
- REBLUR: improved specular reconstruction in HistoryFix pass
- REBLUR: "vmb" normal confidence made jitter friendly
- REBLUR: "prev-prev" test made jitter friendly
- updated README and UPDATE
- updated MathLib
  • Loading branch information
dzhdanNV committed Nov 11, 2022
1 parent d08a0e1 commit bb0f733
Show file tree
Hide file tree
Showing 55 changed files with 2,396 additions and 1,655 deletions.
2 changes: 1 addition & 1 deletion External/MathLib
4 changes: 2 additions & 2 deletions Include/NRD.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
#include <cstddef>

#define NRD_VERSION_MAJOR 3
#define NRD_VERSION_MINOR 8
#define NRD_VERSION_MINOR 9
#define NRD_VERSION_BUILD 0
#define NRD_VERSION_DATE "27 October 2022"
#define NRD_VERSION_DATE "11 November 2022"

#if defined(_MSC_VER)
#define NRD_CALL __fastcall
Expand Down
28 changes: 12 additions & 16 deletions Include/NRDDescs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
#pragma once

#define NRD_DESCS_VERSION_MAJOR 3
#define NRD_DESCS_VERSION_MINOR 8
#define NRD_DESCS_VERSION_MINOR 9

static_assert (NRD_VERSION_MAJOR == NRD_DESCS_VERSION_MAJOR && NRD_VERSION_MINOR == NRD_DESCS_VERSION_MINOR, "Please, update all NRD SDK files");

Expand All @@ -28,7 +28,6 @@ namespace nrd
MAX_NUM
};

// DenoiserName_SignalType
enum class Method : uint32_t
{
// =============================================================================================================================
Expand Down Expand Up @@ -140,7 +139,7 @@ namespace nrd
// COMMON INPUTS
//=============================================================================================================================

// 3D world space motion (RGBA16f+) or 2D screen space motion (RG16f+), MVs must be non-jittered, MV = previous - current
// 3D world-space motion (RGBA16f+) or 2D screen-space motion (RG16f+), MVs must be non-jittered, MV = previous - current
IN_MV,

// Data must match encoding in "NRD_FrontEnd_PackNormalAndRoughness" and "NRD_FrontEnd_UnpackNormalAndRoughness" (RGBA8+)
Expand Down Expand Up @@ -193,7 +192,7 @@ namespace nrd
// Noisy signal (R8+)
IN_RADIANCE,

// Primary and secondary world space positions (RGBA16f+)
// Primary and secondary world-space positions (RGBA16f+)
IN_DELTA_PRIMARY_POS,
IN_DELTA_SECONDARY_POS,

Expand Down Expand Up @@ -231,12 +230,16 @@ namespace nrd
// Denoised signal
OUT_RADIANCE,

// 2D screen space specular motion (RG16f+), MV = previous - current
// 2D screen-space specular motion (RG16f+), MV = previous - current
OUT_REFLECTION_MV,

// 2D screen space refraction motion (RG16f+), MV = previous - current
// 2D screen-space refraction motion (RG16f+), MV = previous - current
OUT_DELTA_MV,

// (Optional) Debug output (RGBA8+), .w = transparency
// Written to if "DenoiserCreationDesc::allowValidation = true" and "CommonSettings::enableValidation = true"
OUT_VALIDATION,

//=============================================================================================================================
// POOLS
//=============================================================================================================================
Expand Down Expand Up @@ -312,7 +315,10 @@ namespace nrd

enum class DescriptorType : uint32_t
{
// read-only, SRV
TEXTURE,

// read-write, UAV
STORAGE_TEXTURE,

MAX_NUM
Expand Down Expand Up @@ -400,7 +406,6 @@ namespace nrd
MemoryAllocatorInterface memoryAllocatorInterface;
const MethodDesc* requestedMethods;
uint32_t requestedMethodNum;
bool enableValidation : 1;
};

struct TextureDesc
Expand All @@ -411,15 +416,6 @@ namespace nrd
uint16_t mipNum;
};

/*
Requested descriptor variants:
- shader read:
- a descriptor for all mips
- a descriptor for first mip only
- a descriptor for some mips with a specific offset
- shader write:
- a descriptor for each mip
*/
struct Resource
{
DescriptorType stateNeeded;
Expand Down
15 changes: 9 additions & 6 deletions Include/NRDSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
#pragma once

#define NRD_SETTINGS_VERSION_MAJOR 3
#define NRD_SETTINGS_VERSION_MINOR 8
#define NRD_SETTINGS_VERSION_MINOR 9

static_assert (NRD_VERSION_MAJOR == NRD_SETTINGS_VERSION_MAJOR && NRD_VERSION_MINOR == NRD_SETTINGS_VERSION_MINOR, "Please, update all NRD SDK files");

Expand Down Expand Up @@ -84,7 +84,7 @@ namespace nrd
// If coordinate system moves with the camera, camera delta must be included to reflect camera motion
float worldToViewMatrixPrev[16] = {};

// (Optional) Previous world space to current world space matrix. It is for virtual normals, where a coordinate
// (Optional) Previous world-space to current world-space matrix. It is for virtual normals, where a coordinate
// system of the virtual space changes frame to frame, such as in a case of animated intermediary reflecting
// surfaces when primary surface replacement is used for them.
float worldPrevToWorldMatrix[16] = {
Expand All @@ -94,8 +94,8 @@ namespace nrd
0.0f, 0.0f, 0.0f, 1.0f
};

// If "isMotionVectorInWorldSpace = true" will be used as "MV * motionVectorScale.xyy"
float motionVectorScale[2] = {1.0f, 1.0f};
// used as "IN_MV * motionVectorScale" (use .z = 0 for 2D screen-space motion)
float motionVectorScale[3] = {1.0f, 1.0f, 0.0f};

// [-0.5; 0.5] - sampleUv = pixelUv + cameraJitter
float cameraJitter[2] = {};
Expand Down Expand Up @@ -130,15 +130,18 @@ namespace nrd
// To reset history set to RESTART / CLEAR_AND_RESTART for one frame
AccumulationMode accumulationMode = AccumulationMode::CONTINUE;

// If "true" IN_MV is 3D motion in world space (0 should be everywhere if the scene is static),
// otherwise it's 2D screen-space motion (0 should be everywhere if the camera doesn't move) (recommended value = true)
// If "true" IN_MV is 3D motion in world-space (0 should be everywhere if the scene is static),
// otherwise it's 2D (+ optional Z delta) screen-space motion (0 should be everywhere if the camera doesn't move) (recommended value = true)
bool isMotionVectorInWorldSpace = false;

// If "true" IN_DIFF_CONFIDENCE and IN_SPEC_CONFIDENCE are provided
bool isHistoryConfidenceInputsAvailable = false;

// If "true" IN_DISOCCLUSION_THRESHOLD_MIX is provided
bool isDisocclusionThresholdMixAvailable = false;

// Enables debug overlay in OUT_VALIDATION, requires "DenoiserCreationDesc::allowValidation = true"
bool enableValidation = false;
};

// REBLUR
Expand Down
51 changes: 45 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# NVIDIA Real-time Denoisers v3.8.0 (NRD)
# NVIDIA Real-time Denoisers v3.9.0 (NRD)

## SAMPLE APP

Expand Down Expand Up @@ -309,11 +309,15 @@ Commons inputs:

* **IN\_MV** - non-jittered primary surface motion (`old = new + MV`)

Supported variants via `ComminSettings::isMotionVectorInWorldSpace`:
- 3D world space motion (recommended) - camera motion should not be included (it's already in the matrices). In other words, if there are no moving objects all motion vectors = 0. The `.w` channel is unused and can be used by the app
- 2D screen space motion - 2D motion doesn't provide information about movement along the view direction, it only allows to "get" the direction. *NRD* can introduce pixels with rejected history on dynamic objects in this case.
Modes:
- *3D world-space motion (recommended)* - camera motion should not be included (it's already in the matrices). In other words, if there are no moving objects, all motion vectors must be `0` even if the camera moves
- *2D screen-space motion* - 2D motion doesn't provide information about movement along the view direction, it only allows to get the direction. *NRD* can introduce pixels with rejected history on dynamic objects in this case
- *2.5D screen-space motion* - similar to the 2D screen-space motion, but `.z = viewZprev - viewZ`.

Motion vector scaling can be provided via `CommonSettings::motionVectorScale`.
Motion vector scaling can be provided via `CommonSettings::motionVectorScale`. *NRD* expectations:
- Use `ComminSettings::isMotionVectorInWorldSpace = true` for 3D world-space motion
- Use `ComminSettings::isMotionVectorInWorldSpace = false` and `ComminSettings::motionVectorScale[2] == 0` for 2D screen-space motion
- Use `ComminSettings::isMotionVectorInWorldSpace = false` and `ComminSettings::motionVectorScale[2] != 0` for 2.5D screen-space motion

* **IN\_NORMAL\_ROUGHNESS** - primary surface world-space normal and *linear* roughness

Expand All @@ -328,7 +332,7 @@ Commons inputs:
Positive and negative values are supported. Z values in all pixels must be in the same space, matching space defined by matrices passed to NRD. If, for example, the protagonist's hands are rendered using special matrices, Z values should be computed as:
- reconstruct world position using special matrices for "hands"
- project on screen using matrices passed to NRD
- `.w` component is positive view Z (or just transform world space position to main view space and take `.z` component)
- `.w` component is positive view Z (or just transform world-space position to main view space and take `.z` component)

**IMPORTANT**: All textures should be *NaN* free at each pixel, even at pixels outside of denoising range.

Expand All @@ -338,6 +342,8 @@ See `NRDDescs.h` for more details and descriptions of other inputs and outputs.

NRD sample is a good start to familiarize yourself with input requirements and best practices, but main requirements can be summarized to:

- Since *NRD* denoisers accumulate signals for a limited number of frames, the input signal must converge *reasonably* well for this number of frames. `REFERENCE` denoiser can be used to estimate temporal signal quality
- Since *NRD* denoisers process signals spatially, high-energy fireflies in the input signal should be avoided. Most of them can be removed by enabling anti-firefly filter in *NRD*, but it will only work if the "background" signal is confident. The worst case is having a single pixel with high energy divided by a very small PDF to represent the lack of energy in neighboring non-representative (black) pixels
- Signal for *NRD* must be separated into diffuse and specular at primary hit
- `hitT` must not include primary hit distance
- Do not pass *sum of lengths of all segments* as `hitT`. A solid baseline is to use hit distance for the 1st bounce only, it works well for diffuse and specular signals
Expand All @@ -354,6 +360,39 @@ NRD sample is a good start to familiarize yourself with input requirements and b

[*Primary Surface Replacement (PSR)*](https://developer.nvidia.com/blog/rendering-perfect-reflections-and-refractions-in-path-traced-games/) can be used with *NRD*. In this case `IN_MV`, `IN_NORMAL_ROUGHNESS` and `IN_VIEWZ` must have data for secondary hits (not primary hits). In case of PSR *NRD* disocclusion logic doesn't take curvature at primary hit into account, because data for primary hits is replaced. This can lead to more intense disocclusions on bumpy surfaces due to significant ray divergence. To mitigate this problem 2x-10x larger `disocclusionThreshold` can be used. This is an applicable solution if the denoiser is used to denoise surfaces with PSR only (glass only, for example). In a general case, when PSR and normal surfaces are mixed on the screen, higher disocclusion thresholds are needed only for pixels with PSR. This can be achieved by using `IN_DISOCCLUSION_THRESHOLD_MIX` input to smoothly mix baseline `disocclusionThreshold` into bigger `disocclusionThresholdAlternate` from `CommonSettings`. Most likely the increased disocclusion threshold is needed only for pixels with normal details at primary hits (local curvature is not zero).

## VALIDATION LAYER

If `CommonSettings::enableValidation = true` *REBLUR* & *RELAX* denoisers render debug information into `OUT_VALIDATION` output. Alpha channel contains layer transparency to allow easy mix with the final image on the application side.

Currently the following viewport layout is used on the screen:

| 0 | 1 | 2 | 3 |
|---|---|---|---|
| 4 | 5 | 6 | 7 |
| 8 | 9 | 10| 11|
| 12| 13| 14| 15|

where:

- Viewport 0 - world-space normals
- Viewport 1 - linear roughness
- Viewport 2 - linear viewZ
- green = `+`
- blue = `-`
- red = `out of denoising range`
- Viewport 3 - difference between MVs, coming from `IN_MV`, and expected MVs, assuming that the scene is static
- blue = `out of screen`
- pixels with moving objects have non-0 values
- Viewport 4 - world-space grid & camera jitter:
- 1 cube = `1 unit`
- the square in the bottom-right corner represents a pixel with accumulated samples
- the red boundary of the square marks jittering outside of the pixel area

*REBLUR* specific:
- Viewport 7 - amount of virtual history
- Viewport 8 - number of accumulated frames for diffuse signal (red = `history reset`)
- Viewport 11 - number of accumulated frames for specular signal (red = `history reset`)

## MEMORY REQUIREMENTS

The *Persistent* column (matches *NRD Permanent pool*) indicates how much of the *Working set* is required to be left intact for subsequent frames of the application. This memory stores the history resources consumed by NRD. The *Aliasable* column (matches *NRD Transient pool*) shows how much of the *Working set* may be aliased by textures or other resources used by the application outside of the operating boundaries of NRD.
Expand Down
2 changes: 1 addition & 1 deletion Resources/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Versioning rules:
*/

#define VERSION_MAJOR 3
#define VERSION_MINOR 8
#define VERSION_MINOR 9
#define VERSION_BUILD 0
#define VERSION_REVISION 0

Expand Down
5 changes: 5 additions & 0 deletions Shaders/Include/Common.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ float GetSpecMagicCurve2( float roughness, float percentOfVolume = 0.987 )
return saturate( angle / almostHalfPi );
}

/*
Produce same results:
ComputeParallax( Xprev - gCameraDelta, gOrthoMode == 0.0 ? pixelUv : smbPixelUv, gWorldToClip, gRectSize, gUnproject, gOrthoMode );
ComputeParallax( Xprev + gCameraDelta, gOrthoMode == 0.0 ? smbPixelUv : pixelUv, gWorldToClipPrev, gRectSize, gUnproject, gOrthoMode );
*/
float ComputeParallax( float3 X, float2 uvForZeroParallax, float4x4 mWorldToClip, float2 rectSize, float unproject, float orthoMode )
{
float3 clip = STL::Geometry::ProjectiveTransform( mWorldToClip, X ).xyw;
Expand Down
4 changes: 2 additions & 2 deletions Shaders/Include/NRD.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ distribution of this software and related documentation without an express
license agreement from NVIDIA CORPORATION is strictly prohibited.
*/

// NRD v3.8
// NRD v3.9

//=================================================================================================================================
// INPUT PARAMETERS
Expand All @@ -30,7 +30,7 @@ float roughness:
- "linear roughness" = sqrt( "m" ), where "m" = "alpha" - GGX roughness
float normal:
- world space normal
- world-space normal
float viewZ:
- linear view space Z for primary rays ( linearized camera depth )
Expand Down
15 changes: 6 additions & 9 deletions Shaders/Include/REBLUR/REBLUR_Common.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,15 @@ float GetFPS( float period = 1.0 )
return gFramerateScale * 30.0 * period;
}

float GetSmbAccumSpeed( float smbSpecAccumSpeedFactor, float vmbPixelsTraveled, float smbParallax, float specAccumSpeed, float roughness )
float GetSmbAccumSpeed( float smbSpecAccumSpeedFactor, float vmbPixelsTraveled, float viewZ, float specAccumSpeed, float maxAngle )
{
float smbSpecAccumSpeed = GetFPS( ) / ( 1.0 + smbSpecAccumSpeedFactor * vmbPixelsTraveled );

// ( Optional ) Accelerate if parallax is high // TODO: migrate to "smbParallaxInPixels"?
float f = 1.0 - roughness * roughness;
f *= smbSpecAccumSpeed / ( 1.0 + smbSpecAccumSpeed );
smbSpecAccumSpeed /= 1.0 + smbParallax * f;
// Tests 142, 148 and 155 ( or anything with very low roughness and curved surfaces )
float ta = PixelRadiusToWorld( gUnproject, gOrthoMode, vmbPixelsTraveled, viewZ ) / viewZ;
float ca = STL::Math::Sqrt01( 1.0 / ( 1.0 + ta * ta ) );
float angle = STL::Math::AcosApprox( ca );
smbSpecAccumSpeed *= STL::Math::SmoothStep( maxAngle * 1.5, maxAngle * 0.5, angle );

return min( smbSpecAccumSpeed, specAccumSpeed );
}
Expand Down Expand Up @@ -364,10 +365,6 @@ float ComputeAntilagScale(
antilag = lerp( 1.0, antilag, stabilizationStrength );
antilag = lerp( 1.0, antilag, GetFadeBasedOnAccumulatedFrames( accumSpeed ) );

#if( REBLUR_DEBUG != 0 )
antilag = 1.0;
#endif

return antilag;
}

Expand Down
12 changes: 6 additions & 6 deletions Shaders/Include/REBLUR/REBLUR_Config.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ distribution of this software and related documentation without an express
license agreement from NVIDIA CORPORATION is strictly prohibited.
*/

#define REBLUR_DEBUG 0 // 0+ ( output can be in radiance, AO or SO )

// Switches ( default 1 )
#define REBLUR_USE_CATROM_FOR_SURFACE_MOTION_IN_TA 1
#define REBLUR_USE_CATROM_FOR_VIRTUAL_MOTION_IN_TA 1
Expand Down Expand Up @@ -68,7 +66,7 @@ static const float3 g_Special8[ 8 ] =
#define REBLUR_POST_BLUR_FRACTION_SCALE 0.5
#define REBLUR_POST_BLUR_RADIUS_SCALE 2.0

#define REBLUR_VIRTUAL_MOTION_NORMAL_WEIGHT_ITERATION_NUM 2
#define REBLUR_VIRTUAL_MOTION_PREV_PREV_WEIGHT_ITERATION_NUM 2
#define REBLUR_COLOR_CLAMPING_SIGMA_SCALE 1.5 // TODO: was 2.0, but we can use even 1.0 because the fast history is noisy, while the main history is denoised
#define REBLUR_HISTORY_FIX_THRESHOLD_1 0.111 // was 0.01
#define REBLUR_HISTORY_FIX_THRESHOLD_2 0.333 // was 0.25
Expand All @@ -84,6 +82,8 @@ static const float3 g_Special8[ 8 ] =
NRD_CONSTANT( float4, gHitDistParams ) \
NRD_CONSTANT( float4, gViewVectorWorld ) \
NRD_CONSTANT( float4, gViewVectorWorldPrev ) \
NRD_CONSTANT( float3, gMvScale ) \
NRD_CONSTANT( float, gDebug ) \
NRD_CONSTANT( float2, gInvScreenSize ) \
NRD_CONSTANT( float2, gScreenSize ) \
NRD_CONSTANT( float2, gInvRectSize ) \
Expand All @@ -96,15 +96,13 @@ static const float3 g_Special8[ 8 ] =
NRD_CONSTANT( float, gReference ) \
NRD_CONSTANT( float, gOrthoMode ) \
NRD_CONSTANT( float, gUnproject ) \
NRD_CONSTANT( float, gDebug ) \
NRD_CONSTANT( float, gDenoisingRange ) \
NRD_CONSTANT( float, gPlaneDistSensitivity ) \
NRD_CONSTANT( float, gFramerateScale ) \
NRD_CONSTANT( float, gBlurRadius ) \
NRD_CONSTANT( float, gMaxAccumulatedFrameNum ) \
NRD_CONSTANT( float, gMaxFastAccumulatedFrameNum ) \
NRD_CONSTANT( float, gAntiFirefly ) \
NRD_CONSTANT( float, unused1 ) \
NRD_CONSTANT( float, gLobeAngleFraction ) \
NRD_CONSTANT( float, gRoughnessFraction ) \
NRD_CONSTANT( float, gResponsiveAccumulationRoughnessThreshold ) \
Expand All @@ -114,7 +112,9 @@ static const float3 g_Special8[ 8 ] =
NRD_CONSTANT( uint, gIsWorldSpaceMotionEnabled ) \
NRD_CONSTANT( uint, gFrameIndex ) \
NRD_CONSTANT( uint, gDiffMaterialMask ) \
NRD_CONSTANT( uint, gSpecMaterialMask )
NRD_CONSTANT( uint, gSpecMaterialMask ) \
NRD_CONSTANT( uint, gResetHistory ) \
NRD_CONSTANT( uint, unused2 )

// PERFORMANCE MODE: x1.25 perf boost by sacrificing IQ ( DIFFUSE_SPECULAR on RTX 3090 @ 1440p 2.05 vs 2.55 ms )
#ifdef REBLUR_PERFORMANCE_MODE
Expand Down
Loading

0 comments on commit bb0f733

Please sign in to comment.