Skip to content

Commit

Permalink
Updated to v2.3.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
SomeNvidiaGuy committed Feb 6, 2025
1 parent ea4c61f commit bcc6327
Show file tree
Hide file tree
Showing 204 changed files with 4,819 additions and 4,154 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*.sublime-workspace
compile-shaders.bat
/tests
/external/dxc
120 changes: 0 additions & 120 deletions .gitlab-ci.yml

This file was deleted.

22 changes: 11 additions & 11 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
[submodule "donut"]
path = donut
url = https://github.com/NVIDIAGameWorks/donut.git
path = External/donut
url = https://github.com/NVIDIA-RTX/Donut.git
[submodule "NRD"]
path = NRD
url = https://github.com/NVIDIAGameWorks/RayTracingDenoiser.git
path = External/NRD
url = https://github.com/NVIDIA-RTX/NRD.git
[submodule "DLSS"]
path = DLSS
path = External/DLSS
url = https://github.com/NVIDIA/DLSS.git
[submodule "rtxdi-runtime"]
path = rtxdi-runtime
url = https://github.com/NVIDIAGameWorks/rtxdi-runtime.git
[submodule "rtxdi-assets"]
path = rtxdi-assets
url = https://github.com/NVIDIAGameWorks/rtxdi-assets.git
path = Libraries/Rtxdi
url = https://github.com/NVIDIA-RTX/RTXDI-Library.git
[submodule "thirdparty/cxxopts"]
path = thirdparty/cxxopts
path = External/cxxopts
url = https://github.com/jarro2783/cxxopts.git
[submodule "Assets/Media"]
path = Assets/Media
url = https://github.com/NVIDIA-RTX/RTXDI-Assets.git
43 changes: 25 additions & 18 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ endfunction()

# Download DXC
if (WIN32)
CheckAndDownloadPackage("DXC" "v1.7.2212.1" ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/dxc https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.7.2212.1/dxc_2023_03_01.zip)
set(REDIST_DXC "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/dxc/bin/x64/dxc.exe")
CheckAndDownloadPackage("DXC" "v1.7.2212.1" ${CMAKE_CURRENT_SOURCE_DIR}/External/dxc https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.7.2212.1/dxc_2023_03_01.zip)
set(REDIST_DXC "${CMAKE_CURRENT_SOURCE_DIR}/External/dxc/bin/x64/dxc.exe")
else()
CheckAndDownloadPackage("DXC" "v1.7.2212.1" ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/dxc https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.7.2212.1/linux_dxc_2023_03_01.x86_64.tar.gz)
CheckAndDownloadPackage("DXC" "v1.7.2212.1" ${CMAKE_CURRENT_SOURCE_DIR}/External/dxc https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.7.2212.1/linux_dxc_2023_03_01.x86_64.tar.gz)
# Add execute permissions
file(CHMOD ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/dxc/bin/dxc PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
set(REDIST_DXC "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/dxc/bin/dxc")
file(CHMOD ${CMAKE_CURRENT_SOURCE_DIR}/External/dxc/bin/dxc PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
set(REDIST_DXC "${CMAKE_CURRENT_SOURCE_DIR}/External/dxc/bin/dxc")
endif()
if (EXISTS "${REDIST_DXC}")
if (WIN32 AND NOT DXC_PATH)
Expand All @@ -89,30 +89,37 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
set(DONUT_SHADERS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin/shaders/framework")

add_subdirectory(donut)
set(DONUT_PATH "${CMAKE_CURRENT_LIST_DIR}/donut")
# Put the ShaderMake binary with the other build outputs
set(SHADERMAKE_BIN_OUTPUT_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" CACHE STRING "")

include(NRD.cmake)
include(DLSS.cmake)
include(rtxdi-runtime.cmake)
add_subdirectory(External/donut)
set(DONUT_PATH "${CMAKE_CURRENT_LIST_DIR}/External/donut")

set(RTXDI_RUNTIME_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/rtxdi-runtime/include")
include(External/NRD.cmake)
include(External/DLSS.cmake)

if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/Libraries/Rtxdi/CMakeLists.txt")

add_subdirectory(Libraries/Rtxdi)
set(RTXDI_RUNTIME_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Libraries/Rtxdi/Include")

endif()

set(GLSLANG_PATH "" CACHE STRING "Path to glslangValidator for GLSL header verification (optional)")

if (NOT TARGET cxxopts)
option(CXXOPTS_BUILD_EXAMPLES OFF)
option(CXXOPTS_BUILD_TESTS OFF)
option(CXXOPTS_ENABLE_INSTALL OFF)
add_subdirectory(thirdparty/cxxopts)
add_subdirectory(External/cxxopts)
endif()

add_subdirectory(shaders)
add_subdirectory(src)
add_subdirectory(minimal/src)
add_subdirectory(minimal/shaders)
add_subdirectory(rtxdi-runtime-shader-tests)
add_subdirectory(Samples/FullSample/Shaders)
add_subdirectory(Samples/FullSample/Source)
add_subdirectory(Samples/MinimalSample/Shaders)
add_subdirectory(Samples/MinimalSample/Source)
add_subdirectory(Support/Tests/RtxdiRuntimeShaderTests)

if (MSVC)
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT rtxdi-sample)
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT FullSample)
endif()
17 changes: 17 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# RTXDI SDK Change Log

## 2.3.0

**Release highlights:**

- Better folder organization: The samples now live in `Samples/`, external libraries now live in `External/`, and the test suite lives in `External/Tests/`.
- All folders and files now use the PascalCase naming convention.
- `RtxdiApplicationBridge.hlsli` broken down into constituent files based on functionality.
- `DIResamplingFunctions.hlsli` and `GIResamplingFunctions.hlsli` broken down into constituent files based on functionality.

**Breaking changes:**

- rtxdi-runtime folder moved to Libraries/Rtxdi, which is now organized into folders based on algorithm.
- File breakdowns mentioned above.

**Misc improvements:**

- Donut updated to latest version to include Blackwell support.

## 2.2.0

Expand Down
12 changes: 6 additions & 6 deletions doc/Confidence.md → Doc/Confidence.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ The confidence solution in RTXDI is inspired by the A-SVGF algorithm published i

Notable open source implementations of A-SVGF can be found in the [Q2VKPT](http://brechpunkt.de/q2vkpt) project and its successor, [Quake II RTX](https://github.com/NVIDIA/Q2RTX). Q2VKPT implements the "vanilla" A-SVGF with forward projection of the surfaces from the previous frame into the current frame using the V-buffer; Q2RTX has switched to a different approach that is based on backward projection and G-buffer patching because the forward projection approach doesn't work for objects seen through reflections and refractions.

While A-SVGF worked well in these projects, it is not very practical for more complex renderers due to the fragility that comes from reusing random number sequences. Great care must be taken to avoid computing false positive gradients based on unrelated changes in the scene. For example, a change in the total light _count_ makes the light sampling logic select different lights using the same RNG sequence even though the surface being shaded may be unaffected by the change at all. In the case of RTXDI, reusing the RNG sequence doesn't look sufficient at all because the shading results depend on persistent state that is different from frame to frame, specifically the light reservoirs. Good news is, we can reuse the reservoirs instead of random numbers.
While A-SVGF worked well in these projects, it is not very practical for more complex renderers due to the fragility that comes from reusing random number sequences. Great care must be taken to avoid computing false positive gradients based on unrelated changes in the scene. For example, a change in the total light _count_ makes the light sampling logic select different lights using the same RNG sequence even though the surface being shaded may be unaffected by the change at all. In the case of RTXDI, reusing the RNG sequence doesn't look sufficient at all because the shading results depend on persistent state that is different from frame to frame, specifically the light reservoirs. The good news is that we can reuse the reservoirs instead of random numbers.

## Temporal Gradients in RTXDI

Similar to A-SVGF, we define a temporal gradient as difference between the shading results of the same surface using the same light sample on two consecutive frames. Gradients defined like this capture the changes in the surface's lighting environment, such as lights moving relative to the surface, lights changing their intensity, or lights becoming shadowed or un-shadowed. They may capture the difference in shading results due to the view vector changing because of camera motion, or not capture that, depending on the implementation; when using the NRD denoisers, capturing the view vector changes is not necessary. Gradients should **not** capture any changes due to the subpixel camera jitter that results in slight material variation in the same pixel when the camera is static.
Similar to A-SVGF, we define a temporal gradient as the difference between the shading results of the same surface using the same light sample on two consecutive frames. Gradients defined like this capture the changes in the surface's lighting environment, such as lights moving relative to the surface, lights changing their intensity, or lights becoming shadowed or un-shadowed. They may capture the difference in shading results due to the view vector changing because of camera motion, or not capture that, depending on the implementation; when using the NRD denoisers, capturing the view vector changes is not necessary. Gradients should **not** capture any changes due to the subpixel camera jitter that results in slight material variation in the same pixel when the camera is static.

Temporal gradients are computed using a separate compute or ray tracing pass that runs after final shading, [`ComputeGradients.hlsl`](../shaders/LightingPasses/ComputeGradients.hlsl). As a pre-requisite, the temporal resampling pass or the fused kernel saves the screen-space position of the pixel whose reservoir was used as the temporal light sample. Also, the luminance of the final shading results from the current and the previous frames needs to be available. Luminance can be computed from the diffuse and specular lighting textures if they store unmodified colors, but the RTXDI sample app may add BRDF ray tracing results into the same textures, so the sampled lighting luminance values are stored separately in the textures called `RestirLuminance`.
Temporal gradients are computed using a separate compute or ray tracing pass that runs after final shading, [`ComputeGradients.hlsl`](../shaders/DenoisingPasses/ComputeGradients.hlsl). As a prerequisite, the temporal resampling pass or the fused kernel saves the screen-space position of the pixel whose reservoir was used as the temporal light sample. Also, the luminance of the final shading results from the current and the previous frames need to be available. Luminance can be computed from the diffuse and specular lighting textures if they store unmodified colors, but the RTXDI sample app may add BRDF ray tracing results into the same textures, so the sampled lighting luminance values are stored separately in the textures called `RestirLuminance`.

The gradient pass has two phases of execution:

Expand All @@ -32,15 +32,15 @@ For more details on the gradient pass implementation, please refer to the commen

The gradients pass produces a sparse and low-resolution signal, normally at 1/3 the screen resolution, that stores luminance differences and absolute values. Feeding that signal into the denoiser as confidence just wouldn't work, and the signal needs to be filtered and converted first.

First, the gradients are filtered spatially using a wide blur. The blur size and exact parameters may vary; the RTXDI sample app uses a 4-pass A-trous filter with a 3x3 kernel, which results in a 31 pixel kernel radius (in gradient space). The blur could be bilateral and take surface normals and positions into account, if desired. Our implementation is very straightforward and can be found in [`FilterGradientsPass.hlsl`](../shaders/FilterGradientsPass.hlsl). Note that the luminance differences and absolute values are filtered independently, which means that a small local change in a bright region is unlikely to result in history invalidation.
First, the gradients are filtered spatially using a wide blur. The blur size and exact parameters may vary; the RTXDI sample app uses a 4-pass A-trous filter with a 3x3 kernel, which results in a 31 pixel kernel radius (in gradient space). The blur could be bilateral and take surface normals and positions into account, if desired. Our implementation is very straightforward and can be found in [`FilterGradientsPass.hlsl`](../shaders/DenoisingPasses/FilterGradientsPass.hlsl). Note that the luminance differences and absolute values are filtered independently, which means that a small local change in a bright region is unlikely to result in history invalidation.

Second, the filtered gradients are normalized, i.e. luminance differences are divided by the absolute luminance values, and then converted into (0-1) confidence using a simple function. This signal can already be fed into the confidence input of the denoiser, but there is one extra trick.

The gradients are often noisy even after the spatial filtering, which sometimes results in patchy history invalidation. More importantly, singular events like a light turning on or off only create nonzero gradients on one frame. The spatiotemporal nature of ReSTIR leads to noisy and locally biased lighting on that first frame after a significant change. If the denoiser history is reset momentarily and then accumulation starts from scratch, that local bias has a significant weight in the history, resulting for example in a "black dip" effect around a light that has turned off.

The solution to both noisy confidence and local bias is simple: we can apply a short-history temporal filter to the confidence input of the denoiser. When the temporal filter is tuned right, deoniser history invalidations happen smoothly over a few frames and not abruptly. The temporal filter can be very simple; refer to [`ConfidencePass.hlsl`](../shaders/ConfidencePass.hlsl) for a reference implementation.
The solution to both noisy confidence and local bias is simple: we can apply a short-history temporal filter to the confidence input of the denoiser. When the temporal filter is tuned right, deoniser history invalidations happen smoothly over a few frames and not abruptly. The temporal filter can be very simple; refer to [`ConfidencePass.hlsl`](../shaders/DenoisingPasses/ConfidencePass.hlsl) for a reference implementation.

![Unfiltered and Filtered Confidence](images/Confidence.png)
![Unfiltered and Filtered Confidence](Images/Confidence.png)

The images above illustrate the confidence channel computed from unfiltered gradients (top-left) and after spatial and temporal filtering (top-right) resulting from light coming through a rotating sphere with holes. The confidence is shown using a reverse heat map to highlight the regions where the history should be invalidated.

Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
Loading

0 comments on commit bcc6327

Please sign in to comment.