diff --git a/.gitignore b/.gitignore
index dc4bed0..573923e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
*.sublime-workspace
compile-shaders.bat
/tests
+/external/dxc
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index 78a1ab4..0000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,120 +0,0 @@
-stages:
- - build
- - test
-
-variables:
- GIT_SUBMODULE_STRATEGY: none
- TEST_REPO_BRANCH: main
-
-# Variables that should be specified from the project settings:
-# - TEST_REPO_URL : URL of the repository with tests, including the username and token parts if necessary
-# - ENABLE_JOBS : list of jobs to run, such as "build-linux,test-linux"
-
-# The script assumes that the following software is installed on the runner:
-# - GCC or Clang (Linux)
-# - Visual Studio 2019 (Windows)
-# - CMake 3.10+
-# - Ninja build system
-# - Python 3.8+ and scikit-image
-
-
-# Clone the tests repository
-.clone-tests: &clone-tests
- - git clone -b ${TEST_REPO_BRANCH} ${TEST_REPO_URL} tests
-
-
-build-linux:
- stage: build
- tags:
- - linux
- rules:
- - if: '$ENABLE_JOBS =~ /build-linux/'
- before_script:
- - ./update_dependencies.sh
- script:
- - mkdir build && cd build
- - cmake .. -GNinja
- - ninja
- artifacts:
- name: "rtxdi-linux-${CI_COMMIT_SHORT_SHA}"
- paths:
- - build/bin/
-
-build-windows:
- stage: build
- tags:
- - windows
- rules:
- - if: '$ENABLE_JOBS =~ /build-windows/'
- before_script:
- - ./update_dependencies.bat
- script:
- - ./set_vs_vars.ps1
- - mkdir build
- - cd build
- - cmake .. -GNinja -DRTXDI_CONSOLE_APP=ON
- - cmake --build .
- artifacts:
- name: "rtxdi-windows-${CI_COMMIT_SHORT_SHA}"
- paths:
- - build/bin/
-
-test-linux:
- stage: test
- tags:
- - linux
- rules:
- - if: '$ENABLE_JOBS =~ /test-linux/'
- dependencies:
- - build-linux
- before_script:
- - ./update_dependencies.sh
- - *clone-tests
- script:
- - cd tests
- - python test.py
- artifacts:
- name: "rtxdi-linux-test-outputs-${CI_COMMIT_SHORT_SHA}"
- when: on_failure
- paths:
- - tests/outputs/
-
-test-windows-dx12:
- stage: test
- tags:
- - windows
- rules:
- - if: '$ENABLE_JOBS =~ /test-windows-dx12/'
- dependencies:
- - build-windows
- before_script:
- - ./update_dependencies.bat
- - *clone-tests
- script:
- - cd tests
- - python test.py
- artifacts:
- name: "rtxdi-windows-test-outputs-dx12-${CI_COMMIT_SHORT_SHA}"
- when: on_failure
- paths:
- - tests/outputs/
-
-test-windows-vulkan:
- stage: test
- tags:
- - windows
- rules:
- - if: '$ENABLE_JOBS =~ /test-windows-vulkan/'
- dependencies:
- - build-windows
- before_script:
- - ./update_dependencies.bat
- - *clone-tests
- script:
- - cd tests
- - python test.py --vulkan
- artifacts:
- name: "rtxdi-windows-test-outputs-vulkan-${CI_COMMIT_SHORT_SHA}"
- when: on_failure
- paths:
- - tests/outputs/
diff --git a/.gitmodules b/.gitmodules
index fcd5685..851ccab 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -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
diff --git a/rtxdi-assets b/Assets/Media
similarity index 100%
rename from rtxdi-assets
rename to Assets/Media
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8ee30fe..914189c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
@@ -89,14 +89,21 @@ 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)")
@@ -104,15 +111,15 @@ 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()
diff --git a/ChangeLog.md b/ChangeLog.md
index 1ca78ed..9a6e590 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -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
diff --git a/doc/Confidence.md b/Doc/Confidence.md
similarity index 82%
rename from doc/Confidence.md
rename to Doc/Confidence.md
index fed6b50..265dc62 100644
--- a/doc/Confidence.md
+++ b/Doc/Confidence.md
@@ -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:
@@ -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.
-
+
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.
diff --git a/doc/images/BiasCorrection.png b/Doc/Images/BiasCorrection.png
similarity index 100%
rename from doc/images/BiasCorrection.png
rename to Doc/Images/BiasCorrection.png
diff --git a/doc/images/Boiling.gif b/Doc/Images/Boiling.gif
similarity index 100%
rename from doc/images/Boiling.gif
rename to Doc/Images/Boiling.gif
diff --git a/doc/images/Checkerboard.gif b/Doc/Images/Checkerboard.gif
similarity index 100%
rename from doc/images/Checkerboard.gif
rename to Doc/Images/Checkerboard.gif
diff --git a/doc/images/Confidence.png b/Doc/Images/Confidence.png
similarity index 100%
rename from doc/images/Confidence.png
rename to Doc/Images/Confidence.png
diff --git a/doc/images/DataFlow.png b/Doc/Images/DataFlow.png
similarity index 100%
rename from doc/images/DataFlow.png
rename to Doc/Images/DataFlow.png
diff --git a/doc/images/DisocclusionBoost.png b/Doc/Images/DisocclusionBoost.png
similarity index 100%
rename from doc/images/DisocclusionBoost.png
rename to Doc/Images/DisocclusionBoost.png
diff --git a/doc/images/LightBufferLayout.png b/Doc/Images/LightBufferLayout.png
similarity index 100%
rename from doc/images/LightBufferLayout.png
rename to Doc/Images/LightBufferLayout.png
diff --git a/doc/images/LocalLightPdf.png b/Doc/Images/LocalLightPdf.png
similarity index 100%
rename from doc/images/LocalLightPdf.png
rename to Doc/Images/LocalLightPdf.png
diff --git a/doc/images/MeshLightProcessing.png b/Doc/Images/MeshLightProcessing.png
similarity index 100%
rename from doc/images/MeshLightProcessing.png
rename to Doc/Images/MeshLightProcessing.png
diff --git a/doc/images/PipelineFused.png b/Doc/Images/PipelineFused.png
similarity index 100%
rename from doc/images/PipelineFused.png
rename to Doc/Images/PipelineFused.png
diff --git a/doc/images/PipelineSeparated.png b/Doc/Images/PipelineSeparated.png
similarity index 100%
rename from doc/images/PipelineSeparated.png
rename to Doc/Images/PipelineSeparated.png
diff --git a/doc/images/ReGIRCellStructures.png b/Doc/Images/ReGIRCellStructures.png
similarity index 100%
rename from doc/images/ReGIRCellStructures.png
rename to Doc/Images/ReGIRCellStructures.png
diff --git a/doc/images/ReSTIRGI.png b/Doc/Images/ReSTIRGI.png
similarity index 100%
rename from doc/images/ReSTIRGI.png
rename to Doc/Images/ReSTIRGI.png
diff --git a/doc/images/TargetPDF.png b/Doc/Images/TargetPDF.png
similarity index 100%
rename from doc/images/TargetPDF.png
rename to Doc/Images/TargetPDF.png
diff --git a/doc/images/TemporalNoise.gif b/Doc/Images/TemporalNoise.gif
similarity index 100%
rename from doc/images/TemporalNoise.gif
rename to Doc/Images/TemporalNoise.gif
diff --git a/doc/Integration.md b/Doc/Integration.md
similarity index 89%
rename from doc/Integration.md
rename to Doc/Integration.md
index 7f385df..09fd8ff 100644
--- a/doc/Integration.md
+++ b/Doc/Integration.md
@@ -1,12 +1,12 @@
# Three Algorithms in One SDK
-The RTXDI SDK originally contained a single algorithm, ReSTIR DI. Over time, however, the SDK has been expanded to include the ReGIR and ReSTIR GI algorithms. These three algorithms are grouped together because they all deal with importance sampling for path tracing. While something like "RTX IS" might therefore be a clearer name today, RTXDI is kept for historical continuity. Here is a summary of the three algorithms:
+The RTXDI SDK originally contained a single algorithm, ReSTIR DI. Over time, however, the SDK has been expanded to include the ReGIR and ReSTIR GI algorithms. These three algorithms are grouped together because they all deal with importance sampling for path tracing. While something like "RTX IS" might therefore be a clearer name today, RTXDI is kept for historical continuity, and the DI now stands for Dynamic Illumination. Here is a summary of the three algorithms:
- ReSTIR DI, short for **Re**servoir **S**patio**T**emporal **I**mportance **R**esampling for **D**irect **I**llumination, is a screen space light sampling technique used for illuminating primary surfaces during path tracing. It cheaply selects several lights from an initial distribution, such as a uniform or power-based one, then selects one light of that group based on a more expensive distribution, such as one including geometry, BRDF, and visibility terms, and uses that one for illumination. These samples are then resampled over time and across neighboring pixels to increase effective sample count.
- ReGIR, short for Reservoir-based Grid Importance Sampling, is a world space light sampling technique that can be used for illuminating primary or subsequent surfaces. It samples lights from an initial distribution, such as a uniform or power-based one, for each grid cell. Other algorithms, such as ReSTIR DI and ReSTIR GI, can sample lights from this grid if the surface they are illuminating falls in a grid cell.
-- ReSTIR GI, short for **Re**servoir **S**patio**T**emporal **I**mportance **R**esampling for **G**lobal **I**llumination, is a screen space light sampling technique used for illuminating secondary surfaces during path tracing. ReSTIR GI requires an initial light sampling technique be implemented by the path tracer for the secondary surface. In the `rtxdi-sample` project, this method is the initial sampling pass from ReSTIR DI, although any technique may be used. This secondary surface sample is then resampled across other pixels in space and time.
+- ReSTIR GI, short for **Re**servoir **S**patio**T**emporal **I**mportance **R**esampling for **G**lobal **I**llumination, is a screen space light sampling technique used for illuminating secondary surfaces during path tracing. ReSTIR GI requires an initial light sampling technique be implemented by the path tracer for the secondary surface. In the `full-sample` project, this method is the initial sampling pass from ReSTIR DI, although any technique may be used. This secondary surface sample is then resampled across other pixels in space and time.
-The algorithms in the SDK are implemented largely independent from one another, and the C++-side of each is centered around an accordingly named context class (`ReSTIRDIContext`, `ReGIRContext`, and `ReSTIRGIContext`). However, ReSTIR DI has a close integration of ReGIR for initial sampling. Likewise, the `rtxdi-sample` project uses ReSTIR DI's light sampling functions to illuminate secondary surfaces during multi-bounce path tracing.
+The algorithms in the SDK are implemented largely independent from one another, and the C++-side of each is centered around an accordingly named context class (`ReSTIRDIContext`, `ReGIRContext`, and `ReSTIRGIContext`). However, ReSTIR DI has a close integration of ReGIR for initial sampling. Likewise, the `full-sample` project uses ReSTIR DI's light sampling functions to illuminate secondary surfaces during multi-bounce path tracing.
The SDK also provides structs and functions that are shared between multiple algorithms. For example, the `RtxdiParameters.h` header provides structs relating to the light buffer and global runtime parameters. Likewise, the `PresamplingFunctions.hlsli` file provides presampling functions for creating PDF-textures for both local and environment lights, which can, in turn, be sampled from in the initial sampling passes of ReSTIR DI, ReGIR, and ReSTIR GI for improved sampling quality.
@@ -24,7 +24,7 @@ The algorithms in the RTXDI SDK require a deep integration into the renderer. Th
To avoid making overcomplicated abstractions or restrictive requirements, the RTXDI SDK follows an approach where the application is responsible for all of the above functionality, and RTXDI only provides the light sampling and resampling math that ties into pieces of that functionality through shader callback functions. This makes the integration process fairly involved, but the developers have complete control over the lighting system of their engines and do not have to ship any extra closed-source libraries with it.
-The functionality provided by RTXDI can be separated into shader-side and host-side. Shader-side functionality for ReSTIR DI is provided through the [`DIResamplingFunctions.hlsli`](../rtxdi-sdk/include/rtxdi/DIResamplingFunctions.hlsli) include file and documented in [Shader API Reference](ShaderAPI.md). Host-side functionality is provided through the [`ReSTIRDI.h`](../rtxdi-sdk/include/rtxdi/ReSTIRDI.h) include file and the [`ReSTIRDI.cpp`](../rtxdi-sdk/src/ReSTIRDI.cpp) source file, which together form the `ReSTIRDIContext` class. ReGIR's context lives in [`ReGIR.h`](../rtxdi-sdk/include/rtxdi/ReGIR.h), and ReSTIR GI's context lives in [`ReSTIRGI.h`](../rtxdi-sdk/include/rtxdi/ReSTIRGI.h) Functionality that is shared between these algorithms is located in [`RtxdiUtils.h`](../rtxdi-sdk/include/rtxdi/RtxdiUtils.h).
+The functionality provided by RTXDI can be separated into shader-side and host-side. Shader-side functionality for ReSTIR DI is provided through the [`DI/`](../Libraries/Rtxdi/Include/Rtxdi/DI/) include folder and documented in [Shader API Reference](ShaderAPI.md). Host-side functionality is provided through the [`ReSTIRDI.h`](../Libraries/Rtxdi/Include/Rtxdi/DI/ReSTIRDI.h) include file and the [`ReSTIRDI.cpp`](../Libraries/Rtxdi/Source/DI/ReSTIRDI.cpp) source file, which together form the `ReSTIRDIContext` class. ReGIR's context lives in [`ReGIR.h`](../Libraries/Rtxdi/Include/Rtxdi/ReGIR/ReGIR.h), and ReSTIR GI's context lives in [`ReSTIRGI.h`](../Libraries/Rtxdi/Include/Rtxdi/GI/ReSTIRGI.h). Functionality that is shared between these algorithms is located in [`RtxdiUtils.h`](../Libraries/Rtxdi/Include/Rtxdi/RtxdiUtils.h).
The application also needs to provide shader-side and host-side functionality for RTXDI to work. Most importantly, it needs to provide the bridge structures functions, or callbacks, that are used by the RTXDI resampling functions. Those functions' and structures' names start with `RAB_` (for "**R**TXDI-**A**pplication **B**ridge"). For the complete list of functions and structures that need to be implemented, see the [Bridge Reference](RtxdiApplicationBridge.md). Then the application needs to assemble the resampling functions into complete shaders to build the desired pipeline and compile those shaders. Finally, at run time, the application needs to collect the light information, create the necessary buffers, and execute the compiled shaders.
@@ -35,7 +35,7 @@ For additional considerations about the necessary passes and functions, and to l
The data flow of a renderer using RTXDI is shown on the diagram below.
-
+
The rendering process includes the following steps.
@@ -70,7 +70,7 @@ Collect information about all lights in the scene into a buffer. That includes m
The layout of the light buffer used in the sample application is shown here:
-
+
Note that there are two groups of lights here, one for the odd frames and one for the even frames. This ensures that temporal resampling can access light information from the previous frame, which is necessary to compute the correct normalization factors for unbiased resampling. Another necessary thing is the mapping between light indices on the current and previous frames, which is provided through the [`RAB_TranslateLightIndex`](RtxdiApplicationBridge.md#rab_translatelightindex) bridge function.
@@ -82,7 +82,7 @@ In order to use importance sampling for local lights and the environment map, th
The local light PDF texture might look like this image:
-
+
The PDF texture also needs to have a full mip chain, up to 1x1 pixels. Any mipmap generation code can be used, as long as it does exactly 4:1 pixel downsampling in each step using a box filter: *output = sum(inputs) / 4*.
@@ -90,13 +90,13 @@ In the sample application, the first pass of PDF texture build for local lights
### 4. Fill the constant buffer structure
-Each pass of the ReSTIR DI algorithm requires settings from a correspondingly named `ReSTIRDI_*Parameters` struct. Fetch these from the ReSTIRDI context by calling the appropriate `rtxdi::ReSTIRDIContext::get*()` functions and place them into a constant buffer. Additionally, some settings are shared between stages and are stored in the `rtxdi::ReSTIRDIContext::getRuntimeParams()`, `rtxdi::ReSTIRDIContext::getBufferIndices()`, and `rtxdi::ReSTIRDIContext::getReservoirBufferParameters()` functions; these, too, must be stored in the constant buffer for each pass of the algorithm and passed to the shader functions accordingly.
+Each pass of the ReSTIR DI algorithm requires settings from a correspondingly named `ReSTIRDI_*Parameters` struct. Fetch these from the ReSTIRDI context by calling the appropriate `rtxdi::ReSTIRDIContext::get*()` functions and place them into a constant buffer. Additionally, some settings are shared between stages and are stored in the `rtxdi::ReSTIRDIContext::getBufferIndices()`,and `rtxdi::ReSTIRDIContext::getReservoirBufferParameters()` functions; these, too, must be stored in the constant buffer for each pass of the algorithm and passed to the shader functions accordingly.
The ReGIR and ReSTIR GI contexts likewise provide `get*()` functions for data that needs to be placed in the constant buffer for their respective shader passes. Note that ReSTIR DI and ReSTIR GI can both make use of ReGIR, so you should make sure to keep the ReGIR constants set for both the ReSTIR DI shader passes and the ReSTIR GI shader passes.
### 5. Pre-sample local lights and environment map (Optional)
-Local ligths are pre-sampled into the RIS buffer to accelerate the initial sampling pass. This is necessary if local light importance sampling is used. The presampling pass is effectively doing CDF (Cumulative Distribution Function) inversion through mipmap descent and is implemented in the [`RTXDI_PresampleLocalLights`](ShaderAPI.md#rtxdi_presamplelocallights) function.
+Local lights are pre-sampled into the RIS buffer to accelerate the initial sampling pass. This is necessary if local light importance sampling is used. The presampling pass is effectively doing CDF (Cumulative Distribution Function) inversion through mipmap descent and is implemented in the [`RTXDI_PresampleLocalLights`](ShaderAPI.md#rtxdi_presamplelocallights) function.
The environment map is pre-sampled into a different part of the RIS buffer. This is implemented in the [`RTXDI_PresampleEnvironmentMap`](ShaderAPI.md#rtxdi_presampleenvironmentmap) function.
@@ -106,11 +106,11 @@ Build the world-space light sampling structure for [ReGIR](#regir) (Reservoir-ba
### 7. Perform light sampling and resampling
-Perform light sampling and resampling in screen space using shaders that call the following functions: `[RTXDI_SampleLightsForSurface`](ShaderAPI.md#rtxdi_samplelightsforsurface), [`RTXDI_TemporalResampling`](ShaderAPI.md#rtxdi_temporalresampling), [`RTXDI_SpatialResampling`](ShaderAPI.md#rtxdi_spatialresampling), [`RTXDI_SpatioTemporalResampling`](ShaderAPI.md#RTXDI_SpatioTemporalResampling). See e.g. [`GenerateInitialSamples.hlsl`](../shaders/LightingPasses/GenerateInitialSamples.hlsl) for a shader example, and [`LightingPasses.cpp`](../src/LightingPasses.cpp) for host-side code example. Examples of resampled pipelines are provided [below](#examples).
+Perform light sampling and resampling in screen space using shaders that call the following functions: `[RTXDI_SampleLightsForSurface`](ShaderAPI.md#rtxdi_samplelightsforsurface), [`RTXDI_TemporalResampling`](ShaderAPI.md#rtxdi_temporalresampling), [`RTXDI_SpatialResampling`](ShaderAPI.md#rtxdi_spatialresampling), [`RTXDI_SpatioTemporalResampling`](ShaderAPI.md#RTXDI_SpatioTemporalResampling). See e.g. [`GenerateInitialSamples.hlsl`](../shaders/LightingPasses/DI/GenerateInitialSamples.hlsl) for a shader example, and [`LightingPasses.cpp`](../src/LightingPasses.cpp) for host-side code example. Examples of resampled pipelines are provided [below](#examples).
### 8. Shade
-Shade the final selected light samples using your final material BRDF. Load the sample from the reservoir buffer, trace a visibility ray, store the visibility in the reservoir if desired, and evaluate the BRDF. See [`ShadeSamples.hlsl`](../shaders/LightingPasses/ShadeSamples.hlsl) for an example.
+Shade the final selected light samples using your final material BRDF. Load the sample from the reservoir buffer, trace a visibility ray, store the visibility in the reservoir if desired, and evaluate the BRDF. See [`ShadeSamples.hlsl`](../shaders/LightingPasses/DI/ShadeSamples.hlsl) for an example.
### 9. Compute the denoiser confidence inputs (Optional)
@@ -124,11 +124,11 @@ Apply denoising and composite the denoised lighting with other effects.
The resampling functions can be assembled into various pipelines to fit the application's needs. A complete resampling pipeline with two spatial passes is shown on the image below. The sample application uses a pipeline like this, except with one spatial pass instead of two.
-
+
Some applications might find it useful to implement a fused resampling pipeline, one that combines all light sampling passes into one shader, which could be also tracing primary rays. Such fused pipeline is shown below.
-
+
## Mesh light processing
@@ -138,7 +138,7 @@ The sample application implements a basic mesh light processing pipeline with st
The mesh light processing compute shader, [`PrepareLights.hlsl`](../shaders/PrepareLights.hlsl),starts by identifying which mesh and triangle the current thread should be processing. This is done by doing a binary search on the task list and matching the thread index to the index ranges occupied by each mesh instance; those indices are allocated on the host before launching the shader. Then the shader loads the triangle information: vertex positions and texture coordinates. Vertex positions are transformed with the instance matrix, and they become the vertices of the created mesh light. For materials which have an emissive texture, the texture is approximately integrated over the area of the triangle using a single anisotropic texture sample, as shown below.
-
+
In practice, extracting emissive triangle information from meshes can be problematic for a number of reasons. The following discussion assumes that the processing is happening on the GPU, similar to the way the sample application does it.
@@ -159,11 +159,11 @@ The simplest solution for world-space sampling is to apply RIS to a number of sa
RTXDI SDK includes a solution for world-space sampling called ReGIR, for *Reservoir-based Grid Importance Resampling*. ReGIR constructs a spatial structure with cells distributed around a given location, typically around the camera. There are two available structures: `Grid`, which is just a regular 3D grid; and `Onion`, which is a spherical space partitioning that fills the space with cells whose size gradually increases with distance from the center. The type of structure can be selected with the `ReGIRContextParameters::Mode` field when creating the RTXDI context.
-
+
The spatial structure is rebuilt every frame. Every cell is populated with a number of lights, typically on the order of hundreds to thousands. Each light in the cell is selected from the local light pool using RIS, with the target distribution function being average irradiance from the light to any surface within the cell. Therefore, the cells are not very selective, i.e. if there are many lights in or around the cell, the cells will not help choose a relevant light from those. But they will help filter out the lights that are too far away and will therefore significantly reduce the noise in large scenes.
-To build the ReGIR spatial structure, run a compute shader that calls the `RTXDI_PresampleLocalLightsForReGIR` function. That shader should execute between the local light presampling pass (if importance sampling is enabled; it should be) and any uses of the structure. To sample from the structure only, call the `RTXDI_SampleLocalLightsFromReGIR` function that returns a reservoir with the selected light. Shadowing is not evaluated by that function. To combine the ReGIR results with sampling from unordered light pools outside of the ReGIR structure, call `RTXDI_SampleLightsForSurface`.
+To build the ReGIR spatial structure, run a compute shader that calls the `RTXDI_PresampleLocalLightsForReGIR` function. That shader should execute between the local light presampling pass (if importance sampling is enabled; it should be) and any uses of the structure. To sample from the structure only, call the `RTXDI_SampleLocalLights` function that returns a reservoir with the selected light. Shadowing is not evaluated by that function. To combine the ReGIR results with sampling from unordered light pools outside of the ReGIR structure, call `RTXDI_SampleLightsForSurface`.
Note that ReGIR can also be used as the initial sample generator for screen-space resampling, or ReSTIR. This leads to reduced noise in the initial samples, and in case of large and distributed scenes, can make the difference between a usable output signal and an output signal that has a lot of boiling. This "ReGIR feeds ReSTIR" mode is the default behavior of the sample application.
@@ -178,4 +178,4 @@ Checkerboard rendering must be enabled at RTXDI context creation time, through t
An example frame sequence rendered in checkerboard mode is shown below.
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/doc/NoiseAndBias.md b/Doc/NoiseAndBias.md
similarity index 97%
rename from doc/NoiseAndBias.md
rename to Doc/NoiseAndBias.md
index 6d347e5..37a9a78 100644
--- a/doc/NoiseAndBias.md
+++ b/Doc/NoiseAndBias.md
@@ -1,6 +1,6 @@
# Dealing with Noise and Bias
-Reducing the noise that comes with sampled lighting is the entire point of ReSTIR and RTXDI. There are many parameters in the resampling passes that affect the noise levels and performance, and there are a few critical pieces of functionality that must be implemented right in order to ensure adequate ReSTIR performance.
+Reducing the noise that comes with sampled lighting is the entire point of ReSTIR and RTXDI. There are many parameters in the resampling passes that affect the noise levels and performance, and there are a few critical pieces of functionality that must be implemented correctly in order to ensure adequate ReSTIR performance.
## Target PDF
@@ -10,7 +10,7 @@ The target PDF is defined as `RAB_GetLightSampleTargetPdfForSurface` in the brid
An illustration for the effect that the target PDF makes on the final sampled image is shown below.
-
+
Image (a) shows a rendering of the Bistro scene with the correct target PDF proportional to the actual BRDF. Image (b) shows the same scene with a PDF that is constant 1.0, meaning it is equally likely to select the sun light as it is to select a tiny emissive triangle far away. Image (c) shows the scene with a PDF that assumes that every material is fully metallic and has a roughness of 0.2, which makes the renderer prefer lights that are somewhere around the reflected direction, instead of anywhere around a diffuse surface. Image (d) shows the scene that actually has all materials replaced by metals with a roughness of 0.2, to illustrate what ReSTIR is trying to render on image (c).
@@ -24,13 +24,13 @@ The two main use cases for importance resampling in RTXDI are when the *target P
The initial sampling pass has a straightforward way to control the output noise: specify the number of samples taken from each strategy. There are separate sample counts for local lights (either importance sampled or not), for infinite lights, for the environment map, and for ReGIR where it's available. The more samples are taken, the better the results, but the noise reduction is linear, which means the initial sampling pass alone won't produce a good enough picture for a large number of lights in real-time constraints. It's important, however, to have enough initial samples to avoid boiling that appears when spatiotemporal reuse is applied to a very noisy, sparse signal. Using ReGIR can help with the boiling situation in large scenes with multiple rooms or similarly separated locations. An example of this boiling is shown on the animation below, which was rendered by applying uniform sampling to an environment map with a very bright sun.
-
+
The temporal and spatial resampling passes, or a combined version of those - the spatiotemporal pass, are crucial to noise reduction. Using temporal resampling makes the number of light samples evaluated per pixel increase linearly over time, and adding spatial resampling on top changes that sample count function to an exponential one. The more spatial samples you use, the higher is the base of the exponent, and the faster the noise will fade. But increasing the number of spatial samples also results in reduced performance, and using many samples is not necessary in converged areas - typically, 1-3 samples are sufficient. Many spatial samples are useful mostly in areas of disocclusion, and the process of increasing their count is called "disocclusion boost". The `numDisocclusionBoostSamples` parameter of the spatial and spatiotemporal resampling passes controls how many samples to take in areas that do not have sufficient history length, to help those areas converge faster.
The effectiveness of disocclusion boost is illustrated on the image below. It shows the same scene location captured when the camera is strafing from right to left, making a portion of the ground appear from behind the pole on every frame.
-
+
## Denoiser friendliness
@@ -38,7 +38,7 @@ Modern spatiotemporal denoisers expect the input noisy signal to have certain pr
If a single temporal resampling pass is applied, the output noisy signal will appear fairly stable. Too stable, in fact, and a temporal denoiser will not have enough temporal variation to operate effectively. The denoiser will see that the signal in each pixel has low temporal variance, and decide that it doesn't need to be blurred, so the result will be blotchy. The blotches will also fade in and out slowly, together with the noisy signal. Using a shorter history in ReSTIR helps increase temporal variation, but also increases noise. Another problem with using a single temporal pass is that in motion, the light samples tend to stick together and form clusters of bright pixels, which is even more confusing for the denoiser. These situations are illustrated on the animation below.
-
+
Adding a spatial resampling pass after temporal resampling improves the noise patterns significantly. One spatial sample helps break up the stable patterns and bright clusters, add enough variation for the denoiser to be effective. Two spatial samples improve the signal even more and reduce noise.
@@ -58,7 +58,7 @@ One important aspect of bias correction is using correct temporal data. Since th
The other two sources of bias - discarding invisible samples and visibility reuse - cannot be corrected, but these features are still useful when completely unbiased results are not necessary, for example, in games. Discarding invisible samples after the final shading pass is useful because it can significantly reduce noise in areas that are near the edge of the shadow cast by a powerful light. Note that a similar effect can be achieved by using ray traced bias correction, which is unbiased but more expensive. See the image below for a comparison of these techniques.
-
+
Final visibility reuse is an optimization that significantly reduces the number of rays traced for final shading. The renderer stores the final visibility as color in the reservoir, and that visibility is copied around when the reservoir is reused. When the final visibility is copied, the reservoir tracks the distance between the original location of the surface that generated the visibility term and the reservoir's current location, and the age of the visibility term, in frames. During final shading, the renderer can query if the reservoir has stored visibility and if it hasn't moved too far, and if everything is good, the stored visibility can be used instead of tracing a new ray. In our tests, this type of reuse has been shown to reduce the number of final visibility rays to 30% of its original value, with negligible visual difference.
diff --git a/doc/RestirGI.md b/Doc/RestirGI.md
similarity index 81%
rename from doc/RestirGI.md
rename to Doc/RestirGI.md
index 09f919b..e1c79fb 100644
--- a/doc/RestirGI.md
+++ b/Doc/RestirGI.md
@@ -4,13 +4,13 @@
ReSTIR GI is a spatiotemporal resampling algorithm that is applied to samples of surfaces that produce indirect lighting. For comparison, regular ReSTIR DI operates on samples of lights that affect primary surfaces; ReSTIR GI converts every surface found by tracing BRDF-sampled rays from the primary surface into a light sample.
-
+
## Integration model
The RTXDI SDK's implementation of ReSTIR GI follows the same integration model as ReSTIR DI, with the resampling math encapsulated in a number of high-level functions that call various functions in the bridge for application interoperability. The application is expected to call these high-level functions from its own shaders.
-The functions and structures necessary for ReSTIR GI implementation are defined in two header files: [`GIResamplingFunctions.hlsli`](../rtxdi-sdk/include/RTXDI/GIResamplingFunctions.hlsli) and [`GIReservoir.hlsli`](../rtxdi-sdk/include/RTXDI/GIReservoir.hlsli). See the [API reference](ShaderAPI-RestirGI.md) for more information on the ReSTIR GI functions and structures.
+The functions and structures necessary for ReSTIR GI implementation are defined in the header files stored in the [`GI/`](../Libraries/Rtxdi/Include/RTXDI/GI/): See the [API reference](ShaderAPI-RestirGI.md) for more information on the ReSTIR GI functions and structures.
The application needs to implement the various bridge functions necessary for ReSTIR GI in order to compile the shaders. ReSTIR GI and DI share the same bridge interface, and the sets of functions necessary for them intersect. The following shared bridge structures and functions are needed for ReSTIR GI and must be implemented:
@@ -49,12 +49,12 @@ Note that the radiance of secondary surfaces is non-directional, which means tha
Once the secondary surfaces or paths have been traced and shaded, the application should create a ReSTIR GI reservoir from it using the `RTXDI_MakeGIReservoir` function. That reservoir can be stored in a reservoir buffer for further resampling, or passed directly into a temporal or a spatiotemporal resampling function. See [ShadeSecondarySurfaces.hlsl](../shaders/LightingPasses/ShadeSecondarySurfaces.hlsl) for an example.
-GI reservoirs created after path tracing can be immediately used for shading, without any resampling. This is a useful mode to verify that the math is correct, that no throughput or visibility term is left behind when ReSTIR GI is inserted into the pipeline. In the basic version (no MIS), the application should take the final GI reservoir for the current pixel and shade the primary surface using that reservoir as a regular emissive surface sample, multiplying the results with `weightSum` from the reservoir. The shading result replaces the original radiance produced by the path tracer. See [GIFinalShading.hlsl](../shaders/LightingPasses/GIFinalShading.hlsl) for an example.
+GI reservoirs created after path tracing can be immediately used for shading, without any resampling. This is a useful mode to verify that the math is correct, that no throughput or visibility term is left behind when ReSTIR GI is inserted into the pipeline. In the basic version (no MIS), the application should take the final GI reservoir for the current pixel and shade the primary surface using that reservoir as a regular emissive surface sample, multiplying the results with `weightSum` from the reservoir. The shading result replaces the original radiance produced by the path tracer. See [FinalShading.hlsl](../shaders/LightingPasses/GI/FinalShading.hlsl) for an example.
LightVector = normalize(reservoir.position - primarySurface.position)
PrimaryReflectedIndirectRadiance = primarySurface.BRDF(LightVector, ViewVector) * reservoir.radiance * reservoir.weightSum
-Once the GI reservoir creation and shading are working correctly, resampling passes can be inserted between these two stages. It can be a combination of temporal and spatial passes, or a fused spatiotemporal pass. In the former case, the [temporal pass](../shaders/LightingPasses/GITemporalResampling.hlsl) can be performed in the same shader that does path tracing and/or initial shading, and the [spatial pass](../shaders/LightingPasses/GISpatialResampling.hlsl) can be performed in the same shader that does final shading - or they can be separate shaders, whichever works faster. The sample application uses the separate approach. In the case of fused [spatiotemporal resampling](../shaders/LightingPasses/GIFusedResampling.hlsl), all passes can be done in the same shader, which is probably the easiest way to integrate ReSTIR GI into a path tracer, but it's likely not great for performance.
+Once the GI reservoir creation and shading are working correctly, resampling passes can be inserted between these two stages. It can be a combination of temporal and spatial passes, or a fused spatiotemporal pass. In the former case, the [temporal pass](../shaders/LightingPasses/GI/TemporalResampling.hlsl) can be performed in the same shader that does path tracing and/or initial shading, and the [spatial pass](../shaders/LightingPasses/GI/SpatialResampling.hlsl) can be performed in the same shader that does final shading - or they can be separate shaders, whichever works faster. The sample application uses the separate approach. In the case of fused [spatiotemporal resampling](../shaders/LightingPasses/GI/FusedResampling.hlsl), all passes can be done in the same shader, which is probably the easiest way to integrate ReSTIR GI into a path tracer, but it's likely not great for performance.
-In the final shading pass, multiple importance sampling (MIS) can be applied to recover some image quality lost on shiny surfaces. ReSTIR doesn't work well on specular surfaces with low roughness: the results may look like a more stable, but sparser noise pattern than the original signal, and that's bad for denoising. It's better to combine the ReSTIR GI output with its input in a MIS fashion and use the input signal on surfaces with low roughness. An example of such MIS scheme can be found in the sample application, in the [GIFinalShading.hlsl](../shaders/LightingPasses/GIFinalShading.hlsl) file - see the `GetMISWeight` function and its uses.
\ No newline at end of file
+In the final shading pass, multiple importance sampling (MIS) can be applied to recover some image quality lost on shiny surfaces. ReSTIR doesn't work well on specular surfaces with low roughness: the results may look like a more stable, but sparser noise pattern than the original signal, and that's bad for denoising. It's better to combine the ReSTIR GI output with its input in a MIS fashion and use the input signal on surfaces with low roughness. An example of such MIS scheme can be found in the sample application, in the [FinalShading.hlsl](../shaders/LightingPasses/GI/FinalShading.hlsl) file - see the `GetMISWeight` function and its uses.
\ No newline at end of file
diff --git a/doc/RtxdiApplicationBridge.md b/Doc/RtxdiApplicationBridge.md
similarity index 91%
rename from doc/RtxdiApplicationBridge.md
rename to Doc/RtxdiApplicationBridge.md
index 3e38933..229c9d6 100644
--- a/doc/RtxdiApplicationBridge.md
+++ b/Doc/RtxdiApplicationBridge.md
@@ -1,9 +1,9 @@
# RTXDI Application Bridge
-The application must implement a number of structures and functions on the shader side that are necessary for the RTXDI resampling functions to operate. These structures and functions must be declared before including the main RTXDI header file, [`DIResamplingFunctions.hlsli`](../rtxdi-sdk/include/rtxdi/DIResamplingFunctions.hlsli).
+The application must implement a number of structures and functions on the shader side that are necessary for the RTXDI resampling functions to operate. These structures and functions must be declared before including the main RTXDI header files.
-A reference implementation of the bridge functions and structures with support for multiple light types and fractional visibility (translucency) can be found in [`RtxdiApplicationBridge.hlsli`](../shaders/LightingPasses/RtxdiApplicationBridge.hlsli). This implementation uses some functionality defined in other header files, most notably, polymorphic lights are implemented in [`PolymorphicLight.hlsli`](../shaders/PolymorphicLight.hlsli).
+A reference implementation of the bridge functions and structures with support for multiple light types and fractional visibility (translucency) can be found in [`RtxdiApplicationBridge.hlsli`](../shaders/LightingPasses/RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli). This implementation uses some functionality defined in other header files, most notably, polymorphic lights are implemented in [`PolymorphicLight.hlsli`](../shaders/PolymorphicLight.hlsli). The main application bridge file is itself a list of includes of other files, each of which handles a specific piece of the implementation.
Below is a list of structures and functions that need to be implemented by the application, by category.
@@ -13,10 +13,14 @@ All these structures are opaque, i.e. the library code makes no assumption about
### `RAB_Surface`
-Stores information about a surface, including its position, orientation, and material parameters. In addition to that, a view direction should also be a part of the `RAB_Surface` structure. This structure must contain everything that is necessary to compute a material BRDF using the `RAB_GetLightSampleTargetPdfForSurface` function.
+Stores information about a surface, including its position, orientation, and material parameters, the last of which must be accessible as an `RAB_Material` via the `RAB_GetMaterial` function. Additionally, a view direction should also be a part of the `RAB_Surface` structure. This structure must contain everything that is necessary to compute a material BRDF using the `RAB_GetLightSampleTargetPdfForSurface` function.
Instances of `RAB_Surface` are constructed in the `RAB_GetGBufferSurface` function, which loads the surface information from either the current or the previous G-buffer given a pixel position, and is called from the temporal and spatial resampling functions. Alternatively, these instances can be produced directly in the primary rays shader, for example, and passed into the resampling functions as the current surface being shaded.
+### `RAB_Material`
+
+Stores the material information for a surface.
+
### `RAB_LightInfo`
Stores information about a polymorphic light, i.e. a light of any type. Typically, this structure would contain a field encoding the light type, another field storing the light radiance, and other fields like position and orientation, whose interpretation depends on the specific light type. It's not a requirement however, and an implementation could choose to store lights of different types in different arrays, and keep only the light type and array index in the `RAB_LightInfo` structure, loading the specific light information only when sampling or weighing the light is performed.
@@ -56,6 +60,11 @@ Returns an empty `RAB_LightInfo` object.
Returns an empty `RAB_LightSample` object.
+### `RAB_EmptyMaterial`
+
+`RAB_Material RAB_EmptyMaterial()`
+
+Returns an empty `RAB_Material` object.
## G-buffer Input and Accessor Functions
@@ -63,7 +72,13 @@ Returns an empty `RAB_LightSample` object.
`RAB_Surface RAB_GetGBufferSurface(int2 pixelPosition, bool previousFrame)`
-Loads a surface from the current or previous G-buffer at the specified pixel position. Pixel positions may be out-of-bounds or negative, in which case the function is supposed to return an invalid surface. Invalid surfaces are identified by `RAB_IsSurfaceValid` returning `false`.
+Loads a surface from the current or previous G-buffer at the specified pixel position. Pixel positions may be out-of-bounds or negative, in which case the function is supposed to return an invalid surface. Invalid surfaces are identified by `RAB_IsSurfaceValid` returning `false`. Should call RAB_GetGBufferMaterial to fill in its RAB_Material data.
+
+### `RAB_GetGBufferMaterial`
+
+`RAB_Material RAB_GetGBufferMaterial(int2 pixelPosition, bool previousFrame)`
+
+Loads the material data from the current or previous G-buffer at the specified pixel position. Pixel positions may be out-of-bounds or negative, in which case the function is supposed to return an invalid surface.
### `RAB_IsSurfaceValid`
@@ -101,11 +116,7 @@ This function is called in the spatial resampling passes to make sure that the s
`RAB_LightInfo RAB_LoadLightInfo(uint index, bool previousFrame)`
-Loads the information about a polymorphic light based on its index, on the current or previous frame. See [`RAB_LightInfo`](#rab_lightinfo) for the description of what information is required. The indices passed to this function will be in one of the three ranges provided to `rtxdi::Context::FillRuntimeParameters(...)`:
-
-- `firstLocalLight` ... `firstLocalLight + numLocalLights - 1`: local lights;
-- `firstInfiniteLight` ... `firstInfiniteLight + numInfiniteLights - 1` : infinite lights;
-- `environmentLightIndex`: importance sampled environment light, if `environmentLightPresent` is `true`.
+Loads the information about a polymorphic light based on its index, on the current or previous frame. See [`RAB_LightInfo`](#rab_lightinfo) for the description of what information is required. The indices passed to this function will be in one of the three ranges provided to `RTXDI_LightBufferParameters`.
These ranges do not have to be continuously packed in one buffer or start at zero. The application can choose to use some higher bits in the light index to store information. The lower 31 bit of the light index are available; the highest bit is reserved for internal use.
diff --git a/doc/ShaderAPI-RestirGI.md b/Doc/ShaderAPI-RestirGI.md
similarity index 100%
rename from doc/ShaderAPI-RestirGI.md
rename to Doc/ShaderAPI-RestirGI.md
diff --git a/doc/ShaderAPI.md b/Doc/ShaderAPI.md
similarity index 98%
rename from doc/ShaderAPI.md
rename to Doc/ShaderAPI.md
index 1d58d7c..a94fb16 100644
--- a/doc/ShaderAPI.md
+++ b/Doc/ShaderAPI.md
@@ -1,6 +1,6 @@
# RTXDI Shader API
-Most of the RTXDI functionality is implemented in shaders. To use this functionality, include the [`DIResamplingFunctions.hlsli`](../rtxdi-sdk/include/rtxdi/DIResamplingFunctions.hlsli) file into your shader source code, after defining (or at least declaring) the [bridge functions](RtxdiApplicationBridge.md).
+Most of the RTXDI functionality is implemented in shaders. To use this functionality, include the appropriate header file(s) from the [`DI/`](../Libaries/Rtxdi/Include/Rtxdi/DI/) folder into your shader source code, after defining (or at least declaring) the [bridge functions](RtxdiApplicationBridge.md).
Below is the list of shader structures and functions provided by RTXDI that can be useful to applications. Some internal functions are not shown.
@@ -39,6 +39,7 @@ Define this macro to one of the `RTXDI_REGIR_DISABLED`, `RTXDI_REGIR_GRID`, `RTX
Define this macro to a resource name for the RIS buffer, which should have HLSL type `RWBuffer`. Not necessary when `RTXDI_ENABLE_PRESAMPLING` is `0`.
+
## Structures
### `RTXDI_PackedDIReservoir`
@@ -187,6 +188,7 @@ Adds `newReservoir` into `reservoir`, returns true if the new reservoir's sample
This is a very general form, allowing input parameters to specify normalization and `targetPdf`
rather than computing them from `newReservoir`.
+
## Low-Level Sampling Functions
### `RTXDI_SamplePdfMipmap`
@@ -202,7 +204,6 @@ Performs importance sampling of a set of items with their PDF values stored in a
The function returns the position of the final selected texel in the `position` parameter, and its normalized selection PDF in the `pdf` parameter. If the PDF texture is empty or malformed (i.e. has four adjacent zeros in one mip level and a nonzero corresponding texel in the next mip level), the returned PDF will be zero.
-
### `RTXDI_PresampleLocalLights`
void RTXDI_PresampleLocalLights(
@@ -345,7 +346,6 @@ Called to finish the process of doing pairwise MIS. This function must be calle
compensates for this overweighting, but it can only happen after all neighbors have been processed.
-
## High-Level Sampling and Resampling Functions
### `RTXDI_SampleLightsForSurface`
@@ -465,13 +465,12 @@ Applies a boiling filter over all threads in the compute shader thread group. Th
```
RTXDI_SampleParameters RTXDI_InitSampleParameters(
- uint numRegirSamples,
uint numLocalLightSamples,
uint numInfiniteLightSamples,
uint numEnvironmentMapSamples,
uint numBrdfSamples,
- float brdfCutoff = 0.0,
- float brdfRayMinT = 0.001
+ float brdfCutoff RTXDI_DEFAULT(0.0f),
+ float brdfRayMinT RTXDI_DEFAULT(0.001f))
```
Initializes the [`RTXDI_SampleParameters`](#rtxdi_sampleparameters) structure from the sample counts and BRDF sampling parameters. The structure should be the same when passed to various resampling functions to ensure correct MIS application.
diff --git a/DLSS b/External/DLSS
similarity index 100%
rename from DLSS
rename to External/DLSS
diff --git a/DLSS.cmake b/External/DLSS.cmake
similarity index 95%
rename from DLSS.cmake
rename to External/DLSS.cmake
index f48028d..591c6c4 100644
--- a/DLSS.cmake
+++ b/External/DLSS.cmake
@@ -1,5 +1,5 @@
-set(dlss_sdk "${CMAKE_CURRENT_SOURCE_DIR}/DLSS")
+set(dlss_sdk "${CMAKE_CURRENT_SOURCE_DIR}/external/DLSS")
if (WIN32)
add_library(DLSS SHARED IMPORTED)
diff --git a/NRD b/External/NRD
similarity index 100%
rename from NRD
rename to External/NRD
diff --git a/NRD.cmake b/External/NRD.cmake
similarity index 94%
rename from NRD.cmake
rename to External/NRD.cmake
index b009227..35d6c84 100644
--- a/NRD.cmake
+++ b/External/NRD.cmake
@@ -8,7 +8,7 @@ if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/NRD/CMakeLists.txt")
set (NRD_SHADERS_PATH "${CMAKE_CURRENT_BINARY_DIR}/NRD_Shaders" CACHE STRING "")
option(NRD_STATIC_LIBRARY "" ON)
- add_subdirectory(NRD)
+ add_subdirectory(external/NRD)
set_target_properties(NRD PROPERTIES FOLDER NRD)
set_target_properties(NRD_Shaders PROPERTIES FOLDER NRD)
diff --git a/thirdparty/cxxopts b/External/cxxopts
similarity index 100%
rename from thirdparty/cxxopts
rename to External/cxxopts
diff --git a/External/donut b/External/donut
new file mode 160000
index 0000000..04c9b20
--- /dev/null
+++ b/External/donut
@@ -0,0 +1 @@
+Subproject commit 04c9b20189ea59629c888f260cd3a3cef0119010
diff --git a/Libraries/Rtxdi b/Libraries/Rtxdi
new file mode 160000
index 0000000..e5c953c
--- /dev/null
+++ b/Libraries/Rtxdi
@@ -0,0 +1 @@
+Subproject commit e5c953c275b17c9a2fbaa12dab8b3805d87440f7
diff --git a/README.md b/README.md
index c172749..66b1508 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# RTXDI SDK and Sample Applications
-Version 2.2.0.
+Version 2.3.0.
[Change Log](ChangeLog.md)
@@ -15,31 +15,30 @@ For more information about RTXDI, see the [NVIDIA Developer Page](https://develo
## Package Contents
-[`rtxdi-runtime`](https://github.com/NVIDIAGameWorks/rtxdi-runtime) is a submodule that contains the integrable runtime sources that are meant to be included in the application build:
+[`Libraries/Rtxdi`](https://github.com/NVIDIAGameWorks/rtxdi-runtime) is a submodule that contains the integrable runtime sources that are meant to be included in the application build:
-- [`rtxdi-runtime/include/rtxdi`](https://github.com/NVIDIAGameWorks/rtxdi-runtime/tree/main/include/rtxdi) has the include files, both for host code and for shaders
-- [`rtxdi-runtime/include/rtxdi/DIResamplingFunctions.hlsli`](https://github.com/NVIDIAGameWorks/rtxdi-runtime/tree/main/include/rtxdi/DIResamplingFunctions.hlsli) and [`rtxdi-runtime/include/rtxdi/GIResamplingFunctions.hlsli`](https://github.com/NVIDIAGameWorks/rtxdi-runtime/tree/main/include/rtxdi/GIResamplingFunctions.hlsli) are the main shader includes that contain the resampling implementations
-- [`rtxdi-runtime/src`](https://github.com/NVIDIAGameWorks/rtxdi-runtime/tree/main/src) has the host code with various utility functions for setting up the parameters and resources for resampling
+- [`Rtxdi/Include/Rtxdi`](https://github.com/NVIDIAGameWorks/rtxdi-runtime/tree/main/include/rtxdi) has the include files, both for host code and for shaders.
+- [`Rtxdi/Include/Rtxdi/DI/`](https://github.com/NVIDIAGameWorks/rtxdi-runtime/tree/main/Include/Rtxdi/DI/) and [`Rtxdi/Include/Rtxdi/GI/`](https://github.com/NVIDIAGameWorks/rtxdi-runtime/tree/main/Include/Rtxdi/GI/) are the main shader include folders that contain the resampling implementations for their respective algorithms.
+- [`Rtxdi/Source`](https://github.com/NVIDIAGameWorks/rtxdi-runtime/tree/main/Source) has the host code with various utility functions for setting up the parameters and resources for resampling.
-[`src`](src) contains the sample application host code.
+[`Samples`](Samples) contains two sample projects, [`MinimalSample`](Samples/MinimalSample) and [`FullSample`](Samples/FullSample). The [`MinimalSample/Source`](Samples/MinimalSample/Source) project implements ReSTIR DI in a single combined pass to show a minimum viable implementation. The [`FullSample/Source`](Samples/FullSample/Source) project implements ReSTIR DI in several passes integrated into a broader rendering pipeline to show a more standard implementation. The shaders for each project live in their respective [`MinimalSample/Shaders`](Samples/MinimalSample/Shaders) and [`FullSample/Shaders`](Samples/FullSample/Shaders) folders.
-[`shaders`](shaders) contains the sample application shaders.
+[`External`](External) contains project dependencies both from Nvidia and third parties:
-[`donut`](donut) is a submodule structure with the ["Donut" rendering framework](https://github.com/NVIDIAGameWorks/donut) used to build the sample apps.
+- [`External/donut`](External/donut) is a Git submodule structure with the ["Donut" rendering framework](https://github.com/NVIDIAGameWorks/donut) used to build the sample apps.
-[`NRD`](NRD) is a submodule with the ["NRD" denoiser library](https://github.com/NVIDIAGameWorks/RayTracingDenoiser).
+- [`External/NRD`](External/NRD) is a Git submodule with the ["NRD" denoiser library](https://github.com/NVIDIAGameWorks/RayTracingDenoiser).
-[`DLSS`](DLSS) is a submodule with the [Deep Learning Super-Sampling SDK](https://github.com/NVIDIA/DLSS).
+- [`External/DLSS`](External/DLSS) is a Git submodule with the [Deep Learning Super-Sampling SDK](https://github.com/NVIDIA/DLSS).
-[`rtxdi-assets`](https://github.com/NVIDIAGameWorks/rtxdi-assets) is a submodule containing the [RTXDI SDK Sample Assets](https://github.com/NVIDIAGameWorks/rtxdi-assets).
+- `External/dxc` is a recent version of DirectX Shader Compiler. However, unlike the other dependencies, it is not a Git submodule but is instead fetched by CMake at project configuration time.
-Additional content delivered during CMake configuration:
+[`Assets/Media`](https://github.com/NVIDIAGameWorks/rtxdi-assets) is a Git submodule containing the [RTXDI SDK Sample Assets](https://github.com/NVIDIAGameWorks/rtxdi-assets).
-`thirdparty/dxc` is a recent version of DirectX Shader Compiler.
## Building and Running the Sample Apps
-**Note** that because the [`rtxdi-assets`](https://github.com/NVIDIAGameWorks/rtxdi-assets) submodule uses LFS. Cloning it without [LFS](https://git-lfs.com) installed will result in files containing LFS pointers instead of the actual assets.
+**Note** that because the [`rtxdi-assets`](https://github.com/NVIDIAGameWorks/rtxdi-assets) submodule that is cloned into `Assets/Media` uses LFS, cloning it without [LFS](https://git-lfs.com) installed will result in files containing LFS pointers instead of the actual assets.
### Windows
@@ -64,7 +63,7 @@ Additional content delivered during CMake configuration:
7. Build the solution with Visual Studio
-8. Run the `rtxdi-sample` or `minimal-sample` projects.
+8. Run the `FullSample` or `MinimalSample` projects.
### Linux
@@ -91,7 +90,7 @@ Additional content delivered during CMake configuration:
- `make -j8` (example for an 8-core CPU, or use [Ninja](https://ninja-build.org) instead)
7. Run:
- - `bin/rtxdi-sample` or `bin/minimal-sample`
+ - `bin/FullSample` or `bin/MinimalSample`
### Vulkan support
diff --git a/shaders/AccumulationPass.hlsl b/Samples/FullSample/Shaders/AccumulationPass.hlsl
similarity index 97%
rename from shaders/AccumulationPass.hlsl
rename to Samples/FullSample/Shaders/AccumulationPass.hlsl
index 3e28796..cfbd01a 100644
--- a/shaders/AccumulationPass.hlsl
+++ b/Samples/FullSample/Shaders/AccumulationPass.hlsl
@@ -12,7 +12,7 @@
#include "ShaderParameters.h"
#include "HelperFunctions.hlsli"
-#include
+#include
VK_PUSH_CONSTANT ConstantBuffer g_Const : register(b0);
diff --git a/shaders/BRDFPTParameters.h b/Samples/FullSample/Shaders/BRDFPTParameters.h
similarity index 97%
rename from shaders/BRDFPTParameters.h
rename to Samples/FullSample/Shaders/BRDFPTParameters.h
index 309ed9d..fe7eab8 100644
--- a/shaders/BRDFPTParameters.h
+++ b/Samples/FullSample/Shaders/BRDFPTParameters.h
@@ -11,7 +11,7 @@
#ifndef RTXDI_BRDFPT_PARAMETERS_H
#define RTXDI_BRDFPT_PARAMETERS_H
-#include
+#include
struct BRDFPathTracing_MaterialOverrideParameters
{
diff --git a/Samples/FullSample/Shaders/CMakeLists.txt b/Samples/FullSample/Shaders/CMakeLists.txt
new file mode 100644
index 0000000..ad93179
--- /dev/null
+++ b/Samples/FullSample/Shaders/CMakeLists.txt
@@ -0,0 +1,133 @@
+
+include("${DONUT_PATH}/compileshaders.cmake")
+
+set(shaders
+ DebugViz/NDirOctUNorm32Viz.hlsl
+ DebugViz/PackedR11G11B10UFloatViz.hlsl
+ DebugViz/PackedR8G8B8A8GammaUFloatViz.hlsl
+ DenoisingPasses/ComputeGradients.hlsl
+ DenoisingPasses/ConfidencePass.hlsl
+ DenoisingPasses/FilterGradientsPass.hlsl
+ LightingPasses/DI/FusedResampling.hlsl
+ LightingPasses/DI/GenerateInitialSamples.hlsl
+ LightingPasses/DI/ShadeSamples.hlsl
+ LightingPasses/DI/SpatialResampling.hlsl
+ LightingPasses/DI/TemporalResampling.hlsl
+ LightingPasses/GI/FinalShading.hlsl
+ LightingPasses/GI/FusedResampling.hlsl
+ LightingPasses/GI/SpatialResampling.hlsl
+ LightingPasses/GI/TemporalResampling.hlsl
+ LightingPasses/Presampling/PresampleEnvironmentMap.hlsl
+ LightingPasses/Presampling/PresampleLights.hlsl
+ LightingPasses/Presampling/PresampleReGIR.hlsl
+ LightingPasses/BrdfRayTracing.hlsl
+ LightingPasses/RtxdiApplicationBridge/RAB_Buffers.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_LightInfo.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_LightSample.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_LightSampling.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_Material.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_RandomSamplerState.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_RayPayload.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_RTShaders.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_SpatialHelpers.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_Surface.hlsli
+ LightingPasses/RtxdiApplicationBridge/RAB_VisibilityTest.hlsli
+ LightingPasses/RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli
+ LightingPasses/ShadeSecondarySurfaces.hlsl
+ LightingPasses/ShadingHelpers.hlsli
+ AccumulationPass.hlsl
+ BRDFPTParameters.h
+ CompositingPass.hlsl
+ DlssExposure.hlsl
+ GBufferHelpers.hlsli
+ GlassPass.hlsl
+ HelperFunctions.hlsli
+ GlassPass.hlsl
+ Helperfunctions.hlsli
+ LightShaping.hlsli
+ PolymorphicLight.hlsli
+ PostprocessGBuffer.hlsl
+ PrepareLights.hlsl
+ PreprocessEnvironmentMap.hlsl
+ RasterizedGBuffer.hlsl
+ RaytracedGBuffer.hlsl
+ RenderEnvironmentMap.hlsl
+ SceneGeometry.hlsli
+ ShaderParameters.h
+ VisualizeConfidence.hlsl
+ VisualizeHdrSignals.hlsl)
+
+# Organize MSVS filters (the little folders in the solution explorer) to match the folder structure
+foreach(source IN LISTS shaders)
+ get_filename_component(source_path "${source}" PATH)
+ string(REPLACE "/" "\\" source_path_msvc "${source_path}")
+ source_group("${source_path_msvc}" FILES "${source}")
+endforeach()
+
+set(project FullSample)
+set(folder "RTXDI SDK")
+set(shaders_target FullSampleShaders)
+
+add_custom_target(${shaders_target}
+ DEPENDS ShaderMake
+ SOURCES ${shaders} Shaders.cfg)
+
+if(TARGET NRD)
+ set(NRD_OPTIONS -I "${CMAKE_CURRENT_SOURCE_DIR}/../../../external/NRD/Shaders/Include" -D WITH_NRD -D NRD_USE_OCT_NORMAL_ENCODING=0 -D NRD_USE_MATERIAL_ID=0)
+else()
+ set(NRD_OPTIONS --relaxedInclude NRD.hlsli)
+endif()
+
+set (OUTPUT_PATH_BASE "${CMAKE_BINARY_DIR}/bin/shaders/full-sample")
+
+ if (WIN32)
+ set (USE_API_OPTION --useAPI)
+ else()
+ set (USE_API_OPTION "")
+ endif()
+
+if (DONUT_WITH_DX12)
+ set(DX12_COMPILER_OPTIONS
+ --platform DXIL
+ --shaderModel 6_5
+ --binaryBlob
+ --outputExt .bin
+ -I ${DONUT_SHADER_INCLUDE_DIR}
+ -I ${RTXDI_RUNTIME_INCLUDE_PATH}
+ --relaxedInclude "../Types.h"
+ ${NRD_OPTIONS}
+ ${USE_API_OPTION}
+ --compiler ${DXC_PATH})
+
+ add_custom_command(TARGET ${shaders_target} PRE_BUILD
+ COMMAND ShaderMake
+ --config ${CMAKE_CURRENT_SOURCE_DIR}/Shaders.cfg
+ --out ${OUTPUT_PATH_BASE}/dxil
+ ${DX12_COMPILER_OPTIONS})
+endif()
+
+if (DONUT_WITH_VULKAN)
+ set(VULKAN_COMPILER_OPTIONS
+ --platform SPIRV
+ --shaderModel 6_5
+ --vulkanVersion 1.2
+ --binaryBlob
+ --outputExt .bin
+ -I ${DONUT_SHADER_INCLUDE_DIR}
+ -I ${RTXDI_RUNTIME_INCLUDE_PATH}
+ --relaxedInclude "../Types.h"
+ ${NRD_OPTIONS}
+ ${USE_API_OPTION}
+ ${NVRHI_DEFAULT_VK_REGISTER_OFFSETS}
+ -D SPIRV
+ --compiler ${DXC_SPIRV_PATH})
+
+ add_custom_command(TARGET ${shaders_target} PRE_BUILD
+ COMMAND ShaderMake
+ --config ${CMAKE_CURRENT_SOURCE_DIR}/Shaders.cfg
+ --out ${OUTPUT_PATH_BASE}/spirv
+ ${VULKAN_COMPILER_OPTIONS})
+endif()
+
+set_target_properties(${shaders_target} PROPERTIES FOLDER ${folder})
+set_source_files_properties(${shaders} PROPERTIES VS_TOOL_OVERRIDE "None")
diff --git a/shaders/CompositingPass.hlsl b/Samples/FullSample/Shaders/CompositingPass.hlsl
similarity index 100%
rename from shaders/CompositingPass.hlsl
rename to Samples/FullSample/Shaders/CompositingPass.hlsl
diff --git a/shaders/DebugViz/NDirOctUNorm32Viz.hlsl b/Samples/FullSample/Shaders/DebugViz/NDirOctUNorm32Viz.hlsl
similarity index 100%
rename from shaders/DebugViz/NDirOctUNorm32Viz.hlsl
rename to Samples/FullSample/Shaders/DebugViz/NDirOctUNorm32Viz.hlsl
diff --git a/shaders/DebugViz/PackedR11G11B10UFloatViz.hlsl b/Samples/FullSample/Shaders/DebugViz/PackedR11G11B10UFloatViz.hlsl
similarity index 100%
rename from shaders/DebugViz/PackedR11G11B10UFloatViz.hlsl
rename to Samples/FullSample/Shaders/DebugViz/PackedR11G11B10UFloatViz.hlsl
diff --git a/shaders/DebugViz/PackedR8G8B8A8GammaUFloatViz.hlsl b/Samples/FullSample/Shaders/DebugViz/PackedR8G8B8A8GammaUFloatViz.hlsl
similarity index 100%
rename from shaders/DebugViz/PackedR8G8B8A8GammaUFloatViz.hlsl
rename to Samples/FullSample/Shaders/DebugViz/PackedR8G8B8A8GammaUFloatViz.hlsl
diff --git a/shaders/LightingPasses/DIComputeGradients.hlsl b/Samples/FullSample/Shaders/DenoisingPasses/ComputeGradients.hlsl
similarity index 97%
rename from shaders/LightingPasses/DIComputeGradients.hlsl
rename to Samples/FullSample/Shaders/DenoisingPasses/ComputeGradients.hlsl
index febd534..da891b1 100644
--- a/shaders/LightingPasses/DIComputeGradients.hlsl
+++ b/Samples/FullSample/Shaders/DenoisingPasses/ComputeGradients.hlsl
@@ -10,15 +10,15 @@
#pragma pack_matrix(row_major)
-#include "RtxdiApplicationBridge.hlsli"
+#include "../LightingPasses/RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include "Rtxdi/DI/Reservoir.hlsli"
#ifdef WITH_NRD
#undef WITH_NRD
#endif
-#include "ShadingHelpers.hlsli"
+#include "../LightingPasses/ShadingHelpers.hlsli"
#if USE_RAY_QUERY
[numthreads(RTXDI_SCREEN_SPACE_GROUP_SIZE, RTXDI_SCREEN_SPACE_GROUP_SIZE, 1)]
@@ -152,7 +152,7 @@ void RayGen()
/* previousFrameTLAS = */ !usePrevSample, /* enableVisibilityReuse = */ false, diffuse, specular, lightDistance);
// Calculate the sampled lighting luminance for the other surface
- float2 newDiffSpecLum = float2(calcLuminance(diffuse * surface.diffuseAlbedo), calcLuminance(specular));
+ float2 newDiffSpecLum = float2(calcLuminance(diffuse * surface.material.diffuseAlbedo), calcLuminance(specular));
// Convert to FP16 and back to avoid false-positive gradients due to precision loss in the
// u_RestirLuminance and t_PrevRestirLuminance textures where selectedDiffSpecLum comes from.
diff --git a/shaders/ConfidencePass.hlsl b/Samples/FullSample/Shaders/DenoisingPasses/ConfidencePass.hlsl
similarity index 98%
rename from shaders/ConfidencePass.hlsl
rename to Samples/FullSample/Shaders/DenoisingPasses/ConfidencePass.hlsl
index 1549245..8b75042 100644
--- a/shaders/ConfidencePass.hlsl
+++ b/Samples/FullSample/Shaders/DenoisingPasses/ConfidencePass.hlsl
@@ -10,8 +10,8 @@
#pragma pack_matrix(row_major)
-#include "ShaderParameters.h"
-#include
+#include "../ShaderParameters.h"
+#include
VK_PUSH_CONSTANT ConstantBuffer g_Const : register(b0);
diff --git a/shaders/FilterGradientsPass.hlsl b/Samples/FullSample/Shaders/DenoisingPasses/FilterGradientsPass.hlsl
similarity index 96%
rename from shaders/FilterGradientsPass.hlsl
rename to Samples/FullSample/Shaders/DenoisingPasses/FilterGradientsPass.hlsl
index 8d675f3..4b3eab4 100644
--- a/shaders/FilterGradientsPass.hlsl
+++ b/Samples/FullSample/Shaders/DenoisingPasses/FilterGradientsPass.hlsl
@@ -10,8 +10,8 @@
#pragma pack_matrix(row_major)
-#include "ShaderParameters.h"
-#include
+#include "../ShaderParameters.h"
+#include
VK_PUSH_CONSTANT ConstantBuffer g_Const : register(b0);
diff --git a/shaders/DlssExposure.hlsl b/Samples/FullSample/Shaders/DlssExposure.hlsl
similarity index 96%
rename from shaders/DlssExposure.hlsl
rename to Samples/FullSample/Shaders/DlssExposure.hlsl
index 627c76f..8edb210 100644
--- a/shaders/DlssExposure.hlsl
+++ b/Samples/FullSample/Shaders/DlssExposure.hlsl
@@ -8,7 +8,7 @@
# license agreement from NVIDIA CORPORATION is strictly prohibited.
**************************************************************************/
-#include
+#include
Buffer t_Source : register(t0);
RWTexture2D u_Dest : register(u0);
diff --git a/shaders/GBufferHelpers.hlsli b/Samples/FullSample/Shaders/GBufferHelpers.hlsli
similarity index 100%
rename from shaders/GBufferHelpers.hlsli
rename to Samples/FullSample/Shaders/GBufferHelpers.hlsli
diff --git a/shaders/GlassPass.hlsl b/Samples/FullSample/Shaders/GlassPass.hlsl
similarity index 100%
rename from shaders/GlassPass.hlsl
rename to Samples/FullSample/Shaders/GlassPass.hlsl
diff --git a/shaders/HelperFunctions.hlsli b/Samples/FullSample/Shaders/HelperFunctions.hlsli
similarity index 99%
rename from shaders/HelperFunctions.hlsli
rename to Samples/FullSample/Shaders/HelperFunctions.hlsli
index 0fc8ee1..2679c1a 100644
--- a/shaders/HelperFunctions.hlsli
+++ b/Samples/FullSample/Shaders/HelperFunctions.hlsli
@@ -12,7 +12,7 @@
#define HELPER_FUNCTIONS_HLSLI
#include
-#include
+#include
static const float c_pi = 3.1415926535;
diff --git a/shaders/LightShaping.hlsli b/Samples/FullSample/Shaders/LightShaping.hlsli
similarity index 100%
rename from shaders/LightShaping.hlsli
rename to Samples/FullSample/Shaders/LightShaping.hlsli
diff --git a/shaders/LightingPasses/BrdfRayTracing.hlsl b/Samples/FullSample/Shaders/LightingPasses/BrdfRayTracing.hlsl
similarity index 94%
rename from shaders/LightingPasses/BrdfRayTracing.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/BrdfRayTracing.hlsl
index a0f49de..e130567 100644
--- a/shaders/LightingPasses/BrdfRayTracing.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/BrdfRayTracing.hlsl
@@ -10,9 +10,9 @@
#pragma pack_matrix(row_major)
-#include "RtxdiApplicationBridge.hlsli"
+#include "RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include
#ifdef WITH_NRD
#define NRD_HEADER_ONLY
@@ -60,7 +60,7 @@ void RayGen()
float3 V = normalize(g_Const.view.cameraDirectionOrPosition.xyz - surface.worldPos);
bool isSpecularRay = false;
- bool isDeltaSurface = surface.roughness == 0;
+ bool isDeltaSurface = surface.material.roughness == 0;
float specular_PDF;
float3 BRDF_over_PDF;
float overall_PDF;
@@ -70,14 +70,14 @@ void RayGen()
float3 specular_BRDF_over_PDF;
{
float3 Ve = float3(dot(V, tangent), dot(V, bitangent), dot(V, surface.normal));
- float3 He = sampleGGX_VNDF(Ve, surface.roughness, Rand);
+ float3 He = sampleGGX_VNDF(Ve, surface.material.roughness, Rand);
float3 H = isDeltaSurface ? surface.normal : normalize(He.x * tangent + He.y * bitangent + He.z * surface.normal);
specularDirection = reflect(-V, H);
float HoV = saturate(dot(H, V));
float NoV = saturate(dot(surface.normal, V));
- float3 F = Schlick_Fresnel(surface.specularF0, HoV);
- float G1 = isDeltaSurface ? 1.0 : (NoV > 0) ? G1_Smith(surface.roughness, NoV) : 0;
+ float3 F = Schlick_Fresnel(surface.material.specularF0, HoV);
+ float G1 = isDeltaSurface ? 1.0 : (NoV > 0) ? G1_Smith(surface.material.roughness, NoV) : 0;
specular_BRDF_over_PDF = F * G1;
}
@@ -91,7 +91,7 @@ void RayGen()
}
specular_PDF = saturate(calcLuminance(specular_BRDF_over_PDF) /
- calcLuminance(specular_BRDF_over_PDF + diffuse_BRDF_over_PDF * surface.diffuseAlbedo));
+ calcLuminance(specular_BRDF_over_PDF + diffuse_BRDF_over_PDF * surface.material.diffuseAlbedo));
isSpecularRay = RAB_GetNextRandom(rng) < specular_PDF;
@@ -106,7 +106,7 @@ void RayGen()
BRDF_over_PDF = diffuse_BRDF_over_PDF / (1.0 - specular_PDF);
}
- const float specularLobe_PDF = ImportanceSampleGGX_VNDF_PDF(surface.roughness, surface.normal, V, ray.Direction);
+ const float specularLobe_PDF = ImportanceSampleGGX_VNDF_PDF(surface.material.roughness, surface.normal, V, ray.Direction);
const float diffuseLobe_PDF = saturate(dot(ray.Direction, surface.normal)) / c_pi;
// For delta surfaces, we only pass the diffuse lobe to ReSTIR GI, and this pdf is for that.
@@ -295,10 +295,10 @@ void RayGen()
float diffuseHitT = payload.committedRayT;
float specularHitT = payload.committedRayT;
- specular = DemodulateSpecular(surface.specularF0, specular);
+ specular = DemodulateSpecular(surface.material.specularF0, specular);
StoreShadingOutput(GlobalIndex, pixelPosition,
- surface.viewDepth, surface.roughness, diffuse, specular, payload.committedRayT, !g_Const.enableBrdfAdditiveBlend, !g_Const.enableBrdfIndirect);
+ surface.viewDepth, surface.material.roughness, diffuse, specular, payload.committedRayT, !g_Const.enableBrdfAdditiveBlend, !g_Const.enableBrdfIndirect);
}
}
diff --git a/shaders/LightingPasses/DIFusedResampling.hlsl b/Samples/FullSample/Shaders/LightingPasses/DI/FusedResampling.hlsl
similarity index 90%
rename from shaders/LightingPasses/DIFusedResampling.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/DI/FusedResampling.hlsl
index a56140b..7d7b673 100644
--- a/shaders/LightingPasses/DIFusedResampling.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/DI/FusedResampling.hlsl
@@ -15,12 +15,13 @@
#define RTXDI_BOILING_FILTER_GROUP_SIZE RTXDI_SCREEN_SPACE_GROUP_SIZE
#endif
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
-#include
+#include
+#include
+#include
#if RTXDI_REGIR_MODE != RTXDI_REGIR_DISABLED
-#include "rtxdi/ReGIRSampling.hlsli"
+#include "Rtxdi/ReGIR/ReGIRSampling.hlsli"
#endif
#ifdef WITH_NRD
@@ -29,7 +30,7 @@
#include
#endif
-#include "ShadingHelpers.hlsli"
+#include "../ShadingHelpers.hlsli"
#if USE_RAY_QUERY
[numthreads(RTXDI_SCREEN_SPACE_GROUP_SIZE, RTXDI_SCREEN_SPACE_GROUP_SIZE, 1)]
@@ -130,9 +131,9 @@ void RayGen()
ShadeSurfaceWithLightSample(reservoir, surface, lightSample,
/* previousFrameTLAS = */ false, /* enableVisibilityReuse = */ true, diffuse, specular, lightDistance);
- currLuminance = float2(calcLuminance(diffuse * surface.diffuseAlbedo), calcLuminance(specular));
+ currLuminance = float2(calcLuminance(diffuse * surface.material.diffuseAlbedo), calcLuminance(specular));
- specular = DemodulateSpecular(surface.specularF0, specular);
+ specular = DemodulateSpecular(surface.material.specularF0, specular);
}
// Store the sampled lighting luminance for the gradient pass.
@@ -149,5 +150,5 @@ void RayGen()
#endif
StoreShadingOutput(GlobalIndex, pixelPosition,
- surface.viewDepth, surface.roughness, diffuse, specular, lightDistance, true, g_Const.restirDI.shadingParams.enableDenoiserInputPacking);
+ surface.viewDepth, surface.material.roughness, diffuse, specular, lightDistance, true, g_Const.restirDI.shadingParams.enableDenoiserInputPacking);
}
\ No newline at end of file
diff --git a/shaders/LightingPasses/DIGenerateInitialSamples.hlsl b/Samples/FullSample/Shaders/LightingPasses/DI/GenerateInitialSamples.hlsl
similarity index 96%
rename from shaders/LightingPasses/DIGenerateInitialSamples.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/DI/GenerateInitialSamples.hlsl
index fa2ca70..15e690e 100644
--- a/shaders/LightingPasses/DIGenerateInitialSamples.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/DI/GenerateInitialSamples.hlsl
@@ -10,9 +10,9 @@
#pragma pack_matrix(row_major)
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include
#if USE_RAY_QUERY
[numthreads(RTXDI_SCREEN_SPACE_GROUP_SIZE, RTXDI_SCREEN_SPACE_GROUP_SIZE, 1)]
diff --git a/shaders/LightingPasses/DIShadeSamples.hlsl b/Samples/FullSample/Shaders/LightingPasses/DI/ShadeSamples.hlsl
similarity index 84%
rename from shaders/LightingPasses/DIShadeSamples.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/DI/ShadeSamples.hlsl
index c4db00c..db23e7b 100644
--- a/shaders/LightingPasses/DIShadeSamples.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/DI/ShadeSamples.hlsl
@@ -10,11 +10,12 @@
#pragma pack_matrix(row_major)
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
+
+#include "Rtxdi/DI/Reservoir.hlsli"
-#include
#if RTXDI_REGIR_MODE != RTXDI_REGIR_DISABLED
-#include "rtxdi/ReGIRSampling.hlsli"
+#include "Rtxdi/ReGIR/ReGIRSampling.hlsli"
#endif
#ifdef WITH_NRD
@@ -23,7 +24,7 @@
#include
#endif
-#include "ShadingHelpers.hlsli"
+#include "../ShadingHelpers.hlsli"
#if USE_RAY_QUERY
[numthreads(RTXDI_SCREEN_SPACE_GROUP_SIZE, RTXDI_SCREEN_SPACE_GROUP_SIZE, 1)]
@@ -60,9 +61,9 @@ void RayGen()
bool needToStore = ShadeSurfaceWithLightSample(reservoir, surface, lightSample,
/* previousFrameTLAS = */ false, /* enableVisibilityReuse = */ true, diffuse, specular, lightDistance);
- currLuminance = float2(calcLuminance(diffuse * surface.diffuseAlbedo), calcLuminance(specular));
+ currLuminance = float2(calcLuminance(diffuse * surface.material.diffuseAlbedo), calcLuminance(specular));
- specular = DemodulateSpecular(surface.specularF0, specular);
+ specular = DemodulateSpecular(surface.material.specularF0, specular);
if (needToStore)
{
@@ -82,5 +83,5 @@ void RayGen()
#endif
StoreShadingOutput(GlobalIndex, pixelPosition,
- surface.viewDepth, surface.roughness, diffuse, specular, lightDistance, true, g_Const.restirDI.shadingParams.enableDenoiserInputPacking);
+ surface.viewDepth, surface.material.roughness, diffuse, specular, lightDistance, true, g_Const.restirDI.shadingParams.enableDenoiserInputPacking);
}
diff --git a/shaders/LightingPasses/DISpatialResampling.hlsl b/Samples/FullSample/Shaders/LightingPasses/DI/SpatialResampling.hlsl
similarity index 96%
rename from shaders/LightingPasses/DISpatialResampling.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/DI/SpatialResampling.hlsl
index 8d9d375..48fdfb4 100644
--- a/shaders/LightingPasses/DISpatialResampling.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/DI/SpatialResampling.hlsl
@@ -10,9 +10,9 @@
#pragma pack_matrix(row_major)
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include
#if USE_RAY_QUERY
[numthreads(RTXDI_SCREEN_SPACE_GROUP_SIZE, RTXDI_SCREEN_SPACE_GROUP_SIZE, 1)]
diff --git a/shaders/LightingPasses/DITemporalResampling.hlsl b/Samples/FullSample/Shaders/LightingPasses/DI/TemporalResampling.hlsl
similarity index 96%
rename from shaders/LightingPasses/DITemporalResampling.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/DI/TemporalResampling.hlsl
index 7eff199..d018874 100644
--- a/shaders/LightingPasses/DITemporalResampling.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/DI/TemporalResampling.hlsl
@@ -16,9 +16,10 @@
#define RTXDI_BOILING_FILTER_GROUP_SIZE RTXDI_SCREEN_SPACE_GROUP_SIZE
#endif
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include
+#include
#if USE_RAY_QUERY
[numthreads(RTXDI_SCREEN_SPACE_GROUP_SIZE, RTXDI_SCREEN_SPACE_GROUP_SIZE, 1)]
diff --git a/shaders/LightingPasses/GIFinalShading.hlsl b/Samples/FullSample/Shaders/LightingPasses/GI/FinalShading.hlsl
similarity index 88%
rename from shaders/LightingPasses/GIFinalShading.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/GI/FinalShading.hlsl
index cf452bf..bde6d5a 100644
--- a/shaders/LightingPasses/GIFinalShading.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/GI/FinalShading.hlsl
@@ -10,9 +10,11 @@
#pragma pack_matrix(row_major)
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
+#include "../ShadingHelpers.hlsli"
-#include
+#include
+#include
#ifdef WITH_NRD
#define NRD_HEADER_ONLY
@@ -20,7 +22,7 @@
#include
#endif
-#include "ShadingHelpers.hlsli"
+#include "../ShadingHelpers.hlsli"
static const float kMaxBrdfValue = 1e4;
static const float kMISRoughness = 0.3;
@@ -94,13 +96,13 @@ void RayGen()
const SplitBrdf brdf0 = EvaluateBrdf(primarySurface, initialReservoir.position);
RAB_Surface roughenedSurface = primarySurface;
- roughenedSurface.roughness = max(roughenedSurface.roughness, kMISRoughness);
+ roughenedSurface.material.roughness = max(roughenedSurface.material.roughness, kMISRoughness);
const SplitBrdf roughBrdf = EvaluateBrdf(roughenedSurface, reservoir.position);
const SplitBrdf roughBrdf0 = EvaluateBrdf(roughenedSurface, initialReservoir.position);
- const float finalWeight = 1.0 - GetMISWeight(roughBrdf, brdf, primarySurface.diffuseAlbedo);
- const float initialWeight = GetMISWeight(roughBrdf0, brdf0, primarySurface.diffuseAlbedo);
+ const float finalWeight = 1.0 - GetMISWeight(roughBrdf, brdf, primarySurface.material.diffuseAlbedo);
+ const float initialWeight = GetMISWeight(roughBrdf0, brdf0, primarySurface.material.diffuseAlbedo);
const float3 initialRadiance = initialReservoir.radiance * initialReservoir.weightSum;
@@ -117,9 +119,9 @@ void RayGen()
}
- specular = DemodulateSpecular(primarySurface.specularF0, specular);
+ specular = DemodulateSpecular(primarySurface.material.specularF0, specular);
}
StoreShadingOutput(GlobalIndex, pixelPosition,
- primarySurface.viewDepth, primarySurface.roughness, diffuse, specular, 0, false, true);
+ primarySurface.viewDepth, primarySurface.material.roughness, diffuse, specular, 0, false, true);
}
diff --git a/shaders/LightingPasses/GIFusedResampling.hlsl b/Samples/FullSample/Shaders/LightingPasses/GI/FusedResampling.hlsl
similarity index 96%
rename from shaders/LightingPasses/GIFusedResampling.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/GI/FusedResampling.hlsl
index 3485997..2cc470c 100644
--- a/shaders/LightingPasses/GIFusedResampling.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/GI/FusedResampling.hlsl
@@ -15,9 +15,10 @@
#define RTXDI_BOILING_FILTER_GROUP_SIZE RTXDI_SCREEN_SPACE_GROUP_SIZE
#endif
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include
+#include
#if USE_RAY_QUERY
[numthreads(RTXDI_SCREEN_SPACE_GROUP_SIZE, RTXDI_SCREEN_SPACE_GROUP_SIZE, 1)]
diff --git a/shaders/LightingPasses/GISpatialResampling.hlsl b/Samples/FullSample/Shaders/LightingPasses/GI/SpatialResampling.hlsl
similarity index 95%
rename from shaders/LightingPasses/GISpatialResampling.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/GI/SpatialResampling.hlsl
index a1f55d5..eb2a26b 100644
--- a/shaders/LightingPasses/GISpatialResampling.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/GI/SpatialResampling.hlsl
@@ -10,10 +10,9 @@
#pragma pack_matrix(row_major)
-#include "RtxdiApplicationBridge.hlsli"
-
-#include
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
+#include
#if USE_RAY_QUERY
[numthreads(RTXDI_SCREEN_SPACE_GROUP_SIZE, RTXDI_SCREEN_SPACE_GROUP_SIZE, 1)]
diff --git a/shaders/LightingPasses/GITemporalResampling.hlsl b/Samples/FullSample/Shaders/LightingPasses/GI/TemporalResampling.hlsl
similarity index 94%
rename from shaders/LightingPasses/GITemporalResampling.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/GI/TemporalResampling.hlsl
index 4f09d59..fcb4601 100644
--- a/shaders/LightingPasses/GITemporalResampling.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/GI/TemporalResampling.hlsl
@@ -1,5 +1,5 @@
/***************************************************************************
- # Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
+ # Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
@@ -15,9 +15,10 @@
#define RTXDI_BOILING_FILTER_GROUP_SIZE RTXDI_SCREEN_SPACE_GROUP_SIZE
#endif
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include
+#include
#if USE_RAY_QUERY
[numthreads(RTXDI_SCREEN_SPACE_GROUP_SIZE, RTXDI_SCREEN_SPACE_GROUP_SIZE, 1)]
diff --git a/shaders/LightingPasses/PresampleEnvironmentMap.hlsl b/Samples/FullSample/Shaders/LightingPasses/Presampling/PresampleEnvironmentMap.hlsl
similarity index 89%
rename from shaders/LightingPasses/PresampleEnvironmentMap.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/Presampling/PresampleEnvironmentMap.hlsl
index 46f65f7..57be42c 100644
--- a/shaders/LightingPasses/PresampleEnvironmentMap.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/Presampling/PresampleEnvironmentMap.hlsl
@@ -8,9 +8,9 @@
# license agreement from NVIDIA CORPORATION is strictly prohibited.
**************************************************************************/
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include
[numthreads(RTXDI_PRESAMPLING_GROUP_SIZE, 1, 1)]
void main(uint2 GlobalIndex : SV_DispatchThreadID)
diff --git a/shaders/LightingPasses/PresampleLights.hlsl b/Samples/FullSample/Shaders/LightingPasses/Presampling/PresampleLights.hlsl
similarity index 89%
rename from shaders/LightingPasses/PresampleLights.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/Presampling/PresampleLights.hlsl
index 79ddd8c..1ca9e94 100644
--- a/shaders/LightingPasses/PresampleLights.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/Presampling/PresampleLights.hlsl
@@ -8,9 +8,9 @@
# license agreement from NVIDIA CORPORATION is strictly prohibited.
**************************************************************************/
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include
[numthreads(RTXDI_PRESAMPLING_GROUP_SIZE, 1, 1)]
void main(uint2 GlobalIndex : SV_DispatchThreadID)
diff --git a/shaders/LightingPasses/PresampleReGIR.hlsl b/Samples/FullSample/Shaders/LightingPasses/Presampling/PresampleReGIR.hlsl
similarity index 89%
rename from shaders/LightingPasses/PresampleReGIR.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/Presampling/PresampleReGIR.hlsl
index 65f2e99..cfbedc7 100644
--- a/shaders/LightingPasses/PresampleReGIR.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/Presampling/PresampleReGIR.hlsl
@@ -10,9 +10,9 @@
#pragma pack_matrix(row_major)
-#include "RtxdiApplicationBridge.hlsli"
+#include "../RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
+#include
[numthreads(256, 1, 1)]
void main(uint GlobalIndex : SV_DispatchThreadID)
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_Buffers.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_Buffers.hlsli
new file mode 100644
index 0000000..1892eb0
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_Buffers.hlsli
@@ -0,0 +1,77 @@
+#ifndef RAB_BUFFER_HLSLI
+#define RAB_BUFFER_HLSLI
+
+// G-buffer resources
+Texture2D t_GBufferDepth : register(t0);
+Texture2D t_GBufferNormals : register(t1);
+Texture2D t_GBufferGeoNormals : register(t2);
+Texture2D t_GBufferDiffuseAlbedo : register(t3);
+Texture2D t_GBufferSpecularRough : register(t4);
+Texture2D t_PrevGBufferDepth : register(t5);
+Texture2D t_PrevGBufferNormals : register(t6);
+Texture2D t_PrevGBufferGeoNormals : register(t7);
+Texture2D t_PrevGBufferDiffuseAlbedo : register(t8);
+Texture2D t_PrevGBufferSpecularRough : register(t9);
+Texture2D t_PrevRestirLuminance : register(t10);
+Texture2D t_MotionVectors : register(t11);
+Texture2D t_DenoiserNormalRoughness : register(t12);
+
+// Scene resources
+RaytracingAccelerationStructure SceneBVH : register(t30);
+RaytracingAccelerationStructure PrevSceneBVH : register(t31);
+StructuredBuffer t_InstanceData : register(t32);
+StructuredBuffer t_GeometryData : register(t33);
+StructuredBuffer t_MaterialConstants : register(t34);
+
+// RTXDI resources
+StructuredBuffer t_LightDataBuffer : register(t20);
+Buffer t_NeighborOffsets : register(t21);
+Buffer t_LightIndexMappingBuffer : register(t22);
+Texture2D t_EnvironmentPdfTexture : register(t23);
+Texture2D t_LocalLightPdfTexture : register(t24);
+StructuredBuffer t_GeometryInstanceToLight : register(t25);
+
+// Screen-sized UAVs
+RWStructuredBuffer u_LightReservoirs : register(u0);
+RWTexture2D u_DiffuseLighting : register(u1);
+RWTexture2D u_SpecularLighting : register(u2);
+RWTexture2D u_TemporalSamplePositions : register(u3);
+RWTexture2DArray u_Gradients : register(u4);
+RWTexture2D u_RestirLuminance : register(u5);
+RWStructuredBuffer u_GIReservoirs : register(u6);
+
+// RTXDI UAVs
+RWBuffer u_RisBuffer : register(u10);
+RWBuffer u_RisLightDataBuffer : register(u11);
+RWBuffer u_RayCountBuffer : register(u12);
+RWStructuredBuffer u_SecondaryGBuffer : register(u13);
+
+// Other
+ConstantBuffer g_Const : register(b0);
+VK_PUSH_CONSTANT ConstantBuffer g_PerPassConstants : register(b1);
+SamplerState s_MaterialSampler : register(s0);
+SamplerState s_EnvironmentSampler : register(s1);
+
+#define RTXDI_RIS_BUFFER u_RisBuffer
+#define RTXDI_LIGHT_RESERVOIR_BUFFER u_LightReservoirs
+#define RTXDI_NEIGHBOR_OFFSETS_BUFFER t_NeighborOffsets
+#define RTXDI_GI_RESERVOIR_BUFFER u_GIReservoirs
+
+#define IES_SAMPLER s_EnvironmentSampler
+
+// Translates the light index from the current frame to the previous frame (if currentToPrevious = true)
+// or from the previous frame to the current frame (if currentToPrevious = false).
+// Returns the new index, or a negative number if the light does not exist in the other frame.
+int RAB_TranslateLightIndex(uint lightIndex, bool currentToPrevious)
+{
+ // In this implementation, the mapping buffer contains both forward and reverse mappings,
+ // stored at different offsets, so we don't care about the currentToPrevious parameter.
+ uint mappedIndexPlusOne = t_LightIndexMappingBuffer[lightIndex];
+
+ // The mappings are stored offset by 1 to differentiate between valid and invalid mappings.
+ // The buffer is cleared with zeros which indicate an invalid mapping.
+ // Subtract that one to make this function return expected values.
+ return int(mappedIndexPlusOne) - 1;
+}
+
+#endif // RAB_BUFFER_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_LightInfo.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_LightInfo.hlsli
new file mode 100644
index 0000000..e78ac11
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_LightInfo.hlsli
@@ -0,0 +1,73 @@
+#ifndef RAB_LIGHT_INFO_HLSLI
+#define RAB_LIGHT_INFO_HLSLI
+
+#include "../../PolymorphicLight.hlsli"
+#include "RAB_Surface.hlsli"
+#include "RAB_LightSample.hlsli"
+
+typedef PolymorphicLightInfo RAB_LightInfo;
+
+RAB_LightInfo RAB_EmptyLightInfo()
+{
+ return (RAB_LightInfo)0;
+}
+
+// Loads polymorphic light data from the global light buffer.
+RAB_LightInfo RAB_LoadLightInfo(uint index, bool previousFrame)
+{
+ return t_LightDataBuffer[index];
+}
+
+// Loads triangle light data from a tile produced by the presampling pass.
+RAB_LightInfo RAB_LoadCompactLightInfo(uint linearIndex)
+{
+ uint4 packedData1, packedData2;
+ packedData1 = u_RisLightDataBuffer[linearIndex * 2 + 0];
+ packedData2 = u_RisLightDataBuffer[linearIndex * 2 + 1];
+ return unpackCompactLightInfo(packedData1, packedData2);
+}
+
+// Stores triangle light data into a tile.
+// Returns true if this light can be stored in a tile (i.e. compacted).
+// If it cannot, for example it's a shaped light, this function returns false and doesn't store.
+// A basic implementation can ignore this feature and always return false, which is just slower.
+bool RAB_StoreCompactLightInfo(uint linearIndex, RAB_LightInfo lightInfo)
+{
+ uint4 data1, data2;
+ if (!packCompactLightInfo(lightInfo, data1, data2))
+ return false;
+
+ u_RisLightDataBuffer[linearIndex * 2 + 0] = data1;
+ u_RisLightDataBuffer[linearIndex * 2 + 1] = data2;
+
+ return true;
+}
+
+// Computes the weight of the given light for arbitrary surfaces located inside
+// the specified volume. Used for world-space light grid construction.
+float RAB_GetLightTargetPdfForVolume(RAB_LightInfo light, float3 volumeCenter, float volumeRadius)
+{
+ return PolymorphicLight::getWeightForVolume(light, volumeCenter, volumeRadius);
+}
+
+// Samples a polymorphic light relative to the given receiver surface.
+// For most light types, the "uv" parameter is just a pair of uniform random numbers, originally
+// produced by the RAB_GetNextRandom function and then stored in light reservoirs.
+// For importance sampled environment lights, the "uv" parameter has the texture coordinates
+// in the PDF texture, normalized to the (0..1) range.
+RAB_LightSample RAB_SamplePolymorphicLight(RAB_LightInfo lightInfo, RAB_Surface surface, float2 uv)
+{
+ PolymorphicLightSample pls = PolymorphicLight::calcSample(lightInfo, uv, surface.worldPos);
+
+ RAB_LightSample lightSample;
+ lightSample.position = pls.position;
+ lightSample.normal = pls.normal;
+ lightSample.radiance = pls.radiance;
+ lightSample.solidAnglePdf = pls.solidAnglePdf;
+ lightSample.lightType = getLightType(lightInfo);
+ return lightSample;
+}
+
+
+
+#endif // RAB_LIGHT_INFO_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_LightSample.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_LightSample.hlsli
new file mode 100644
index 0000000..59c471d
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_LightSample.hlsli
@@ -0,0 +1,29 @@
+#ifndef RTXDI_RAB_LIGHT_INFO_HLSLI
+#define RTXDI_RAB_LIGHT_INFO_HLSLI
+
+struct RAB_LightSample
+{
+ float3 position;
+ float3 normal;
+ float3 radiance;
+ float solidAnglePdf;
+ PolymorphicLightType lightType;
+};
+
+RAB_LightSample RAB_EmptyLightSample()
+{
+ return (RAB_LightSample)0;
+}
+
+bool RAB_IsAnalyticLightSample(RAB_LightSample lightSample)
+{
+ return lightSample.lightType != PolymorphicLightType::kTriangle &&
+ lightSample.lightType != PolymorphicLightType::kEnvironment;
+}
+
+float RAB_LightSampleSolidAnglePdf(RAB_LightSample lightSample)
+{
+ return lightSample.solidAnglePdf;
+}
+
+#endif // RTXDI_RAB_LIGHT_INFO_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_LightSampling.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_LightSampling.hlsli
new file mode 100644
index 0000000..49fb841
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_LightSampling.hlsli
@@ -0,0 +1,211 @@
+#ifndef RAB_LIGHT_SAMPLING_HLSLI
+#define RAB_LIGHT_SAMPLING_HLSLI
+
+#include "RAB_RayPayload.hlsli"
+
+float2 RAB_GetEnvironmentMapRandXYFromDir(float3 worldDir)
+{
+ float2 uv = directionToEquirectUV(worldDir);
+ uv.x -= g_Const.sceneConstants.environmentRotation;
+ uv = frac(uv);
+ return uv;
+}
+
+// Computes the probability of a particular direction being sampled from the environment map
+// relative to all the other possible directions, based on the environment map pdf texture.
+float RAB_EvaluateEnvironmentMapSamplingPdf(float3 L)
+{
+ if (!g_Const.restirDI.initialSamplingParams.environmentMapImportanceSampling)
+ return 1.0;
+
+ float2 uv = RAB_GetEnvironmentMapRandXYFromDir(L);
+
+ uint2 pdfTextureSize = g_Const.environmentPdfTextureSize.xy;
+ uint2 texelPosition = uint2(pdfTextureSize * uv);
+ float texelValue = t_EnvironmentPdfTexture[texelPosition].r;
+
+ int lastMipLevel = max(0, int(floor(log2(max(pdfTextureSize.x, pdfTextureSize.y)))));
+ float averageValue = t_EnvironmentPdfTexture.mips[lastMipLevel][uint2(0, 0)].x;
+
+ // The single texel in the last mip level is effectively the average of all texels in mip 0,
+ // padded to a square shape with zeros. So, in case the PDF texture has a 2:1 aspect ratio,
+ // that texel's value is only half of the true average of the rectangular input texture.
+ // Compensate for that by assuming that the input texture is square.
+ float sum = averageValue * square(1u << lastMipLevel);
+
+ return texelValue / sum;
+}
+
+// Evaluates pdf for a particular light
+float RAB_EvaluateLocalLightSourcePdf(uint lightIndex)
+{
+ uint2 pdfTextureSize = g_Const.localLightPdfTextureSize.xy;
+ uint2 texelPosition = RTXDI_LinearIndexToZCurve(lightIndex);
+ float texelValue = t_LocalLightPdfTexture[texelPosition].r;
+
+ int lastMipLevel = max(0, int(floor(log2(max(pdfTextureSize.x, pdfTextureSize.y)))));
+ float averageValue = t_LocalLightPdfTexture.mips[lastMipLevel][uint2(0, 0)].x;
+
+ // See the comment at 'sum' in RAB_EvaluateEnvironmentMapSamplingPdf.
+ // The same texture shape considerations apply to local lights.
+ float sum = averageValue * square(1u << lastMipLevel);
+
+ return texelValue / sum;
+}
+
+float3 RAB_GetReflectedRadianceForSurface(float3 incomingRadianceLocation, float3 incomingRadiance, RAB_Surface surface)
+{
+ float3 L = normalize(incomingRadianceLocation - surface.worldPos);
+ float3 N = surface.normal;
+ float3 V = surface.viewDir;
+
+ if (dot(L, surface.geoNormal) <= 0)
+ return 0;
+
+ float d = Lambert(N, -L);
+ float3 s;
+ if (surface.material.roughness == 0)
+ s = 0;
+ else
+ s = GGX_times_NdotL(V, L, N, max(surface.material.roughness, kMinRoughness), surface.material.specularF0);
+
+ return incomingRadiance * (d * surface.material.diffuseAlbedo + s);
+}
+
+float RAB_GetReflectedLuminanceForSurface(float3 incomingRadianceLocation, float3 incomingRadiance, RAB_Surface surface)
+{
+ return RTXDI_Luminance(RAB_GetReflectedRadianceForSurface(incomingRadianceLocation, incomingRadiance, surface));
+}
+
+// Computes the weight of the given light samples when the given surface is
+// shaded using that light sample. Exact or approximate BRDF evaluation can be
+// used to compute the weight. ReSTIR will converge to a correct lighting result
+// even if all samples have a fixed weight of 1.0, but that will be very noisy.
+// Scaling of the weights can be arbitrary, as long as it's consistent
+// between all lights and surfaces.
+float RAB_GetLightSampleTargetPdfForSurface(RAB_LightSample lightSample, RAB_Surface surface)
+{
+ if (lightSample.solidAnglePdf <= 0)
+ return 0;
+
+ return RAB_GetReflectedLuminanceForSurface(lightSample.position, lightSample.radiance, surface) / lightSample.solidAnglePdf;
+}
+
+// Computes the weight of the given GI sample when the given surface is shaded using that GI sample.
+float RAB_GetGISampleTargetPdfForSurface(float3 samplePosition, float3 sampleRadiance, RAB_Surface surface)
+{
+ float3 reflectedRadiance = RAB_GetReflectedRadianceForSurface(samplePosition, sampleRadiance, surface);
+
+ return RTXDI_Luminance(reflectedRadiance);
+}
+
+void RAB_GetLightDirDistance(RAB_Surface surface, RAB_LightSample lightSample,
+ out float3 o_lightDir,
+ out float o_lightDistance)
+{
+ if (lightSample.lightType == PolymorphicLightType::kEnvironment)
+ {
+ o_lightDir = -lightSample.normal;
+ o_lightDistance = DISTANT_LIGHT_DISTANCE;
+ }
+ else
+ {
+ float3 toLight = lightSample.position - surface.worldPos;
+ o_lightDistance = length(toLight);
+ o_lightDir = toLight / o_lightDistance;
+ }
+}
+
+// Forward declare the SDK function that's used in RAB_AreMaterialsSimilar
+bool RTXDI_CompareRelativeDifference(float reference, float candidate, float threshold);
+
+float3 GetEnvironmentRadiance(float3 direction)
+{
+ if (!g_Const.sceneConstants.enableEnvironmentMap)
+ return 0;
+
+ Texture2D environmentLatLongMap = t_BindlessTextures[g_Const.sceneConstants.environmentMapTextureIndex];
+
+ float2 uv = directionToEquirectUV(direction);
+ uv.x -= g_Const.sceneConstants.environmentRotation;
+
+ float3 environmentRadiance = environmentLatLongMap.SampleLevel(s_EnvironmentSampler, uv, 0).rgb;
+ environmentRadiance *= g_Const.sceneConstants.environmentScale;
+
+ return environmentRadiance;
+}
+
+bool IsComplexSurface(int2 pixelPosition, RAB_Surface surface)
+{
+ // Use a simple classification of surfaces into simple and complex based on the roughness.
+ // The PostprocessGBuffer pass modifies the surface roughness and writes the DenoiserNormalRoughness
+ // channel where the roughness is preserved. The roughness stored in the regular G-buffer is modified
+ // based on the surface curvature around the current pixel. If the surface is curved, roughness increases.
+ // Detect that increase here and disable permutation sampling based on a threshold.
+ // Other classification methods can be employed for better quality.
+ float originalRoughness = t_DenoiserNormalRoughness[pixelPosition].a;
+ return originalRoughness < (surface.material.roughness * g_Const.restirDI.temporalResamplingParams.permutationSamplingThreshold);
+}
+
+uint getLightIndex(uint instanceID, uint geometryIndex, uint primitiveIndex)
+{
+ uint lightIndex = RTXDI_InvalidLightIndex;
+ InstanceData hitInstance = t_InstanceData[instanceID];
+ uint geometryInstanceIndex = hitInstance.firstGeometryInstanceIndex + geometryIndex;
+ lightIndex = t_GeometryInstanceToLight[geometryInstanceIndex];
+ if (lightIndex != RTXDI_InvalidLightIndex)
+ lightIndex += primitiveIndex;
+ return lightIndex;
+}
+
+// Return true if anything was hit. If false, RTXDI will do environment map sampling
+// o_lightIndex: If hit, must be a valid light index for RAB_LoadLightInfo, if no local light was hit, must be RTXDI_InvalidLightIndex
+// randXY: The randXY that corresponds to the hit location and is the same used for RAB_SamplePolymorphicLight
+bool RAB_TraceRayForLocalLight(float3 origin, float3 direction, float tMin, float tMax,
+ out uint o_lightIndex, out float2 o_randXY)
+{
+ o_lightIndex = RTXDI_InvalidLightIndex;
+ o_randXY = 0;
+
+ RayDesc ray;
+ ray.Origin = origin;
+ ray.Direction = direction;
+ ray.TMin = tMin;
+ ray.TMax = tMax;
+
+ float2 hitUV;
+ bool hitAnything;
+#if USE_RAY_QUERY
+ RayQuery rayQuery;
+ rayQuery.TraceRayInline(SceneBVH, RAY_FLAG_NONE, INSTANCE_MASK_OPAQUE, ray);
+ rayQuery.Proceed();
+
+ hitAnything = rayQuery.CommittedStatus() == COMMITTED_TRIANGLE_HIT;
+ if (hitAnything)
+ {
+ o_lightIndex = getLightIndex(rayQuery.CommittedInstanceID(), rayQuery.CommittedGeometryIndex(), rayQuery.CommittedPrimitiveIndex());
+ hitUV = rayQuery.CommittedTriangleBarycentrics();
+ }
+#else
+ RayPayload payload = (RayPayload)0;
+ payload.instanceID = ~0u;
+ payload.throughput = 1.0;
+
+ TraceRay(SceneBVH, RAY_FLAG_CULL_NON_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES, INSTANCE_MASK_OPAQUE, 0, 0, 0, ray, payload);
+ hitAnything = payload.instanceID != ~0u;
+ if (hitAnything)
+ {
+ o_lightIndex = getLightIndex(payload.instanceID, payload.geometryIndex, payload.primitiveIndex);
+ hitUV = payload.barycentrics;
+ }
+#endif
+
+ if (o_lightIndex != RTXDI_InvalidLightIndex)
+ {
+ o_randXY = randomFromBarycentric(hitUVToBarycentric(hitUV));
+ }
+
+ return hitAnything;
+}
+
+#endif // RAB_LIGHT_SAMPLING_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_Material.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_Material.hlsli
new file mode 100644
index 0000000..524a7d5
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_Material.hlsli
@@ -0,0 +1,97 @@
+#ifndef RAB_MATERIAL_HLSLI
+#define RAB_MATERIAL_HLSLI
+
+static const float kMinRoughness = 0.05f;
+
+struct RAB_Material
+{
+ float3 diffuseAlbedo;
+ float3 specularF0;
+ float roughness;
+};
+
+RAB_Material RAB_EmptyMaterial()
+{
+ RAB_Material material = (RAB_Material)0;
+
+ return material;
+}
+
+float3 GetDiffuseAlbedo(RAB_Material material)
+{
+ return material.diffuseAlbedo;
+}
+
+float3 GetSpecularF0(RAB_Material material)
+{
+ return material.specularF0;
+}
+
+float GetRoughness(RAB_Material material)
+{
+ return material.roughness;
+}
+
+RAB_Material GetGBufferMaterial(
+ int2 pixelPosition,
+ PlanarViewConstants view,
+ Texture2D diffuseAlbedoTexture,
+ Texture2D specularRoughTexture)
+{
+ RAB_Material material = RAB_EmptyMaterial();
+
+ if (any(pixelPosition >= view.viewportSize))
+ return material;
+
+ material.diffuseAlbedo = Unpack_R11G11B10_UFLOAT(diffuseAlbedoTexture[pixelPosition]).rgb;
+ float4 specularRough = Unpack_R8G8B8A8_Gamma_UFLOAT(specularRoughTexture[pixelPosition]);
+ material.roughness = specularRough.a;
+ material.specularF0 = specularRough.rgb;
+
+ return material;
+}
+
+RAB_Material RAB_GetGBufferMaterial(
+ int2 pixelPosition,
+ bool previousFrame)
+{
+ if(previousFrame)
+ {
+ return GetGBufferMaterial(
+ pixelPosition,
+ g_Const.prevView,
+ t_PrevGBufferDiffuseAlbedo,
+ t_PrevGBufferSpecularRough);
+ }
+ else
+ {
+ return GetGBufferMaterial(
+ pixelPosition,
+ g_Const.view,
+ t_GBufferDiffuseAlbedo,
+ t_GBufferSpecularRough);
+ }
+}
+
+// Compares the materials of two surfaces, returns true if the surfaces
+// are similar enough that we can share the light reservoirs between them.
+// If unsure, just return true.
+bool RAB_AreMaterialsSimilar(RAB_Material a, RAB_Material b)
+{
+ const float roughnessThreshold = 0.5;
+ const float reflectivityThreshold = 0.25;
+ const float albedoThreshold = 0.25;
+
+ if (!RTXDI_CompareRelativeDifference(a.roughness, b.roughness, roughnessThreshold))
+ return false;
+
+ if (abs(calcLuminance(a.specularF0) - calcLuminance(b.specularF0)) > reflectivityThreshold)
+ return false;
+
+ if (abs(calcLuminance(a.diffuseAlbedo) - calcLuminance(b.diffuseAlbedo)) > albedoThreshold)
+ return false;
+
+ return true;
+}
+
+#endif // RAB_MATERIAL_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_RTShaders.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_RTShaders.hlsli
new file mode 100644
index 0000000..a089ec2
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_RTShaders.hlsli
@@ -0,0 +1,76 @@
+#ifndef RAB_RT_SHADERS_HLSLI
+#define RAB_RT_SHADERS_HLSLI
+
+bool considerTransparentMaterial(uint instanceIndex, uint geometryIndex, uint triangleIndex, float2 rayBarycentrics, inout float3 throughput)
+{
+ GeometrySample gs = getGeometryFromHit(
+ instanceIndex,
+ geometryIndex,
+ triangleIndex,
+ rayBarycentrics,
+ GeomAttr_TexCoord,
+ t_InstanceData, t_GeometryData, t_MaterialConstants);
+
+ MaterialSample ms = sampleGeometryMaterial(gs, 0, 0, 0,
+ MatAttr_BaseColor | MatAttr_Transmission, s_MaterialSampler);
+
+ bool alphaMask = ms.opacity >= gs.material.alphaCutoff;
+
+ if (gs.material.domain == MaterialDomain_AlphaTested)
+ return alphaMask;
+
+ if (gs.material.domain == MaterialDomain_AlphaBlended)
+ {
+ throughput *= (1.0 - ms.opacity);
+ return false;
+ }
+
+ if (gs.material.domain == MaterialDomain_Transmissive ||
+ (gs.material.domain == MaterialDomain_TransmissiveAlphaTested && alphaMask) ||
+ gs.material.domain == MaterialDomain_TransmissiveAlphaBlended)
+ {
+ throughput *= ms.transmission;
+
+ if (ms.hasMetalRoughParams)
+ throughput *= (1.0 - ms.metalness) * ms.baseColor;
+
+ if (gs.material.domain == MaterialDomain_TransmissiveAlphaBlended)
+ throughput *= (1.0 - ms.opacity);
+
+ return all(throughput == 0);
+ }
+
+ return false;
+}
+
+#if !USE_RAY_QUERY
+struct RayAttributes
+{
+ float2 uv;
+};
+
+[shader("miss")]
+void Miss(inout RayPayload payload : SV_RayPayload)
+{
+}
+
+[shader("closesthit")]
+void ClosestHit(inout RayPayload payload : SV_RayPayload, in RayAttributes attrib : SV_IntersectionAttributes)
+{
+ payload.committedRayT = RayTCurrent();
+ payload.instanceID = InstanceID();
+ payload.geometryIndex = GeometryIndex();
+ payload.primitiveIndex = PrimitiveIndex();
+ payload.frontFace = HitKind() == HIT_KIND_TRIANGLE_FRONT_FACE;
+ payload.barycentrics = attrib.uv;
+}
+
+[shader("anyhit")]
+void AnyHit(inout RayPayload payload : SV_RayPayload, in RayAttributes attrib : SV_IntersectionAttributes)
+{
+ if (!considerTransparentMaterial(InstanceID(), GeometryIndex(), PrimitiveIndex(), attrib.uv, payload.throughput))
+ IgnoreHit();
+}
+#endif
+
+#endif // RAB_RT_SHADERS_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_RandomSamplerState.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_RandomSamplerState.hlsli
new file mode 100644
index 0000000..c0eebb2
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_RandomSamplerState.hlsli
@@ -0,0 +1,24 @@
+#ifndef RTXDI_RAB_RANDOM_SAMPLER_STATE_HLSLI
+#define RTXDI_RAB_RANDOM_SAMPLER_STATE_HLSLI
+
+#include "../../HelperFunctions.hlsli"
+
+typedef RandomSamplerState RAB_RandomSamplerState;
+
+// Initialized the random sampler for a given pixel or tile index.
+// The pass parameter is provided to help generate different RNG sequences
+// for different resampling passes, which is important for image quality.
+// In general, a high quality RNG is critical to get good results from ReSTIR.
+// A table-based blue noise RNG dose not provide enough entropy, for example.
+RAB_RandomSamplerState RAB_InitRandomSampler(uint2 index, uint pass)
+{
+ return initRandomSampler(index, g_Const.frameIndex + pass * 13);
+}
+
+// Draws a random number X from the sampler, so that (0 <= X < 1).
+float RAB_GetNextRandom(inout RAB_RandomSamplerState rng)
+{
+ return sampleUniformRng(rng);
+}
+
+#endif // RTXDI_RAB_RANDOM_SAMPLER_STATE_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_RayPayload.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_RayPayload.hlsli
new file mode 100644
index 0000000..9389dfd
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_RayPayload.hlsli
@@ -0,0 +1,15 @@
+#ifndef RAB_RAY_PAYLOAD_HLSLI
+#define RAB_RAY_PAYLOAD_HLSLI
+
+struct RayPayload
+{
+ float3 throughput;
+ float committedRayT;
+ uint instanceID;
+ uint geometryIndex;
+ uint primitiveIndex;
+ bool frontFace;
+ float2 barycentrics;
+};
+
+#endif // RAB_RAY_PAYLOAD_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_SpatialHelpers.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_SpatialHelpers.hlsli
new file mode 100644
index 0000000..68c1245
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_SpatialHelpers.hlsli
@@ -0,0 +1,38 @@
+#ifndef RAB_SPATIAL_HELPERS_HLSLI
+#define RAB_SPATIAL_HELPERS_HLSLI
+
+// This function is called in the spatial resampling passes to make sure that
+// the samples actually land on the screen and not outside of its boundaries.
+// It can clamp the position or reflect it across the nearest screen edge.
+// The simplest implementation will just return the input pixelPosition.
+int2 RAB_ClampSamplePositionIntoView(int2 pixelPosition, bool previousFrame)
+{
+ int width = int(g_Const.view.viewportSize.x);
+ int height = int(g_Const.view.viewportSize.y);
+
+ // Reflect the position across the screen edges.
+ // Compared to simple clamping, this prevents the spread of colorful blobs from screen edges.
+ if (pixelPosition.x < 0) pixelPosition.x = -pixelPosition.x;
+ if (pixelPosition.y < 0) pixelPosition.y = -pixelPosition.y;
+ if (pixelPosition.x >= width) pixelPosition.x = 2 * width - pixelPosition.x - 1;
+ if (pixelPosition.y >= height) pixelPosition.y = 2 * height - pixelPosition.y - 1;
+
+ return pixelPosition;
+}
+
+// Check if the sample is fine to be used as a valid spatial sample.
+// This function also be able to clamp the value of the Jacobian.
+bool RAB_ValidateGISampleWithJacobian(inout float jacobian)
+{
+ // Sold angle ratio is too different. Discard the sample.
+ if (jacobian > 10.0 || jacobian < 1 / 10.0) {
+ return false;
+ }
+
+ // clamp Jacobian.
+ jacobian = clamp(jacobian, 1 / 3.0, 3.0);
+
+ return true;
+}
+
+#endif // RAB_SPATIAL_HELPERS_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_Surface.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_Surface.hlsli
new file mode 100644
index 0000000..7aaca62
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_Surface.hlsli
@@ -0,0 +1,187 @@
+#ifndef RTXDI_RAB_SURFACE_HLSLI
+#define RTXDI_RAB_SURFACE_HLSLI
+
+#include "../../GBufferHelpers.hlsli"
+#include "../../SceneGeometry.hlsli"
+#include "../../ShaderParameters.h"
+
+#include "RAB_RandomSamplerState.hlsli"
+#include "RAB_Material.hlsli"
+
+static const bool kSpecularOnly = false;
+
+struct RAB_Surface
+{
+ float3 worldPos;
+ float3 viewDir;
+ float3 normal;
+ float3 geoNormal;
+ float viewDepth;
+ float diffuseProbability;
+ RAB_Material material;
+};
+
+RAB_Surface RAB_EmptySurface()
+{
+ RAB_Surface surface = (RAB_Surface)0;
+ surface.viewDepth = BACKGROUND_DEPTH;
+ return surface;
+}
+
+// Checks if the given surface is valid, see RAB_GetGBufferSurface.
+bool RAB_IsSurfaceValid(RAB_Surface surface)
+{
+ return surface.viewDepth != BACKGROUND_DEPTH;
+}
+
+// Returns the world position of the given surface
+float3 RAB_GetSurfaceWorldPos(RAB_Surface surface)
+{
+ return surface.worldPos;
+}
+
+RAB_Material RAB_GetMaterial(RAB_Surface surface)
+{
+ return surface.material;
+}
+
+// Returns the world shading normal of the given surface
+float3 RAB_GetSurfaceNormal(RAB_Surface surface)
+{
+ return surface.normal;
+}
+
+// Returns the linear depth of the given surface.
+// It doesn't have to be linear depth in a strict sense (i.e. viewPos.z),
+// and can be distance to the camera or primary path length instead.
+// Just make sure that the motion vectors' .z component follows the same logic.
+float RAB_GetSurfaceLinearDepth(RAB_Surface surface)
+{
+ return surface.viewDepth;
+}
+
+float getSurfaceDiffuseProbability(RAB_Surface surface)
+{
+ float diffuseWeight = calcLuminance(surface.material.diffuseAlbedo);
+ float specularWeight = calcLuminance(Schlick_Fresnel(surface.material.specularF0, dot(surface.viewDir, surface.normal)));
+ float sumWeights = diffuseWeight + specularWeight;
+ return sumWeights < 1e-7f ? 1.f : (diffuseWeight / sumWeights);
+}
+
+RAB_Surface GetGBufferSurface(
+ int2 pixelPosition,
+ bool previousFrame,
+ PlanarViewConstants view,
+ Texture2D depthTexture,
+ Texture2D normalsTexture,
+ Texture2D geoNormalsTexture)
+{
+ RAB_Surface surface = RAB_EmptySurface();
+
+ if (any(pixelPosition >= view.viewportSize))
+ return surface;
+
+ surface.viewDepth = depthTexture[pixelPosition];
+
+ if(surface.viewDepth == BACKGROUND_DEPTH)
+ return surface;
+
+ surface.material = RAB_GetGBufferMaterial(pixelPosition, previousFrame);
+
+ surface.geoNormal = octToNdirUnorm32(geoNormalsTexture[pixelPosition]);
+ surface.normal = octToNdirUnorm32(normalsTexture[pixelPosition]);
+ surface.worldPos = viewDepthToWorldPos(view, pixelPosition, surface.viewDepth);
+ surface.viewDir = normalize(view.cameraDirectionOrPosition.xyz - surface.worldPos);
+ surface.diffuseProbability = getSurfaceDiffuseProbability(surface);
+
+ return surface;
+}
+
+
+// Reads the G-buffer, either the current one or the previous one, and returns a surface.
+// If the provided pixel position is outside of the viewport bounds, the surface
+// should indicate that it's invalid when RAB_IsSurfaceValid is called on it.
+RAB_Surface RAB_GetGBufferSurface(int2 pixelPosition, bool previousFrame)
+{
+ if(previousFrame)
+ {
+ return GetGBufferSurface(
+ pixelPosition,
+ previousFrame,
+ g_Const.prevView,
+ t_PrevGBufferDepth,
+ t_PrevGBufferNormals,
+ t_PrevGBufferGeoNormals);
+ }
+ else
+ {
+ return GetGBufferSurface(
+ pixelPosition,
+ previousFrame,
+ g_Const.view,
+ t_GBufferDepth,
+ t_GBufferNormals,
+ t_GBufferGeoNormals);
+ }
+}
+
+float3 worldToTangent(RAB_Surface surface, float3 w)
+{
+ // reconstruct tangent frame based off worldspace normal
+ // this is ok for isotropic BRDFs
+ // for anisotropic BRDFs, we need a user defined tangent
+ float3 tangent;
+ float3 bitangent;
+ ConstructONB(surface.normal, tangent, bitangent);
+
+ return float3(dot(bitangent, w), dot(tangent, w), dot(surface.normal, w));
+}
+
+float3 tangentToWorld(RAB_Surface surface, float3 h)
+{
+ // reconstruct tangent frame based off worldspace normal
+ // this is ok for isotropic BRDFs
+ // for anisotropic BRDFs, we need a user defined tangent
+ float3 tangent;
+ float3 bitangent;
+ ConstructONB(surface.normal, tangent, bitangent);
+
+ return bitangent * h.x + tangent * h.y + surface.normal * h.z;
+}
+
+bool RAB_GetSurfaceBrdfSample(RAB_Surface surface, inout RAB_RandomSamplerState rng, out float3 dir)
+{
+ float3 rand;
+ rand.x = RAB_GetNextRandom(rng);
+ rand.y = RAB_GetNextRandom(rng);
+ rand.z = RAB_GetNextRandom(rng);
+ if (rand.x < surface.diffuseProbability)
+ {
+ if (kSpecularOnly)
+ return false;
+
+ float pdf;
+ float3 h = SampleCosHemisphere(rand.yz, pdf);
+ dir = tangentToWorld(surface, h);
+ }
+ else
+ {
+ float3 Ve = normalize(worldToTangent(surface, surface.viewDir));
+ float3 h = ImportanceSampleGGX_VNDF(rand.yz, max(surface.material.roughness, kMinRoughness), Ve, 1.0);
+ h = normalize(h);
+ dir = reflect(-surface.viewDir, tangentToWorld(surface, h));
+ }
+
+ return dot(surface.normal, dir) > 0.f;
+}
+
+float RAB_GetSurfaceBrdfPdf(RAB_Surface surface, float3 dir)
+{
+ float cosTheta = saturate(dot(surface.normal, dir));
+ float diffusePdf = kSpecularOnly ? 0.f : (cosTheta / M_PI);
+ float specularPdf = ImportanceSampleGGX_VNDF_PDF(max(surface.material.roughness, kMinRoughness), surface.normal, surface.viewDir, dir);
+ float pdf = cosTheta > 0.f ? lerp(specularPdf, diffusePdf, surface.diffuseProbability) : 0.f;
+ return pdf;
+}
+
+#endif // RTXDI_RAB_SURFACE_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_VisibilityTest.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_VisibilityTest.hlsli
new file mode 100644
index 0000000..c872be4
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RAB_VisibilityTest.hlsli
@@ -0,0 +1,151 @@
+#ifndef RAB_VISIBILITY_TEST_HLSLI
+#define RAB_VISIBILITY_TEST_HLSLI
+
+#include "../../SceneGeometry.hlsli"
+
+RayDesc setupVisibilityRay(RAB_Surface surface, float3 samplePosition, float offset = 0.001)
+{
+ float3 L = samplePosition - surface.worldPos;
+
+ RayDesc ray;
+ ray.TMin = offset;
+ ray.TMax = max(offset, length(L) - offset * 2);
+ ray.Direction = normalize(L);
+ ray.Origin = surface.worldPos;
+
+ return ray;
+}
+
+bool GetConservativeVisibility(RaytracingAccelerationStructure accelStruct, RAB_Surface surface, float3 samplePosition)
+{
+ RayDesc ray = setupVisibilityRay(surface, samplePosition);
+
+#if USE_RAY_QUERY
+ RayQuery rayQuery;
+
+ rayQuery.TraceRayInline(accelStruct, RAY_FLAG_NONE, INSTANCE_MASK_OPAQUE, ray);
+
+ rayQuery.Proceed();
+
+ bool visible = (rayQuery.CommittedStatus() == COMMITTED_NOTHING);
+#else
+ RayPayload payload = (RayPayload)0;
+ payload.instanceID = ~0u;
+ payload.throughput = 1.0;
+
+ TraceRay(accelStruct, RAY_FLAG_CULL_NON_OPAQUE | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, INSTANCE_MASK_OPAQUE, 0, 0, 0, ray, payload);
+
+ bool visible = (payload.instanceID == ~0u);
+#endif
+
+ REPORT_RAY(!visible);
+
+ return visible;
+}
+
+// Traces a cheap visibility ray that returns approximate, conservative visibility
+// between the surface and the light sample. Conservative means if unsure, assume the light is visible.
+// Significant differences between this conservative visibility and the final one will result in more noise.
+// This function is used in the spatial resampling functions for ray traced bias correction.
+bool RAB_GetConservativeVisibility(RAB_Surface surface, RAB_LightSample lightSample)
+{
+ return GetConservativeVisibility(SceneBVH, surface, lightSample.position);
+}
+
+// Same as RAB_GetConservativeVisibility but for temporal resampling.
+// When the previous frame TLAS and BLAS are available, the implementation should use the previous position and the previous AS.
+// When they are not available, use the current AS. That will result in transient bias.
+bool RAB_GetTemporalConservativeVisibility(RAB_Surface currentSurface, RAB_Surface previousSurface, RAB_LightSample lightSample)
+{
+ if (g_Const.enablePreviousTLAS)
+ return GetConservativeVisibility(PrevSceneBVH, previousSurface, lightSample.position);
+ else
+ return GetConservativeVisibility(SceneBVH, currentSurface, lightSample.position);
+}
+
+// Traces an expensive visibility ray that considers all alpha tested and transparent geometry along the way.
+// Only used for final shading.
+// Not a required bridge function.
+float3 GetFinalVisibility(RaytracingAccelerationStructure accelStruct, RAB_Surface surface, float3 samplePosition)
+{
+ RayDesc ray = setupVisibilityRay(surface, samplePosition, 0.01);
+
+ uint instanceMask = INSTANCE_MASK_OPAQUE;
+ uint rayFlags = RAY_FLAG_NONE;
+
+ if (g_Const.sceneConstants.enableAlphaTestedGeometry)
+ instanceMask |= INSTANCE_MASK_ALPHA_TESTED;
+
+ if (g_Const.sceneConstants.enableTransparentGeometry)
+ instanceMask |= INSTANCE_MASK_TRANSPARENT;
+
+ if (!g_Const.sceneConstants.enableTransparentGeometry && !g_Const.sceneConstants.enableAlphaTestedGeometry)
+ rayFlags |= RAY_FLAG_CULL_NON_OPAQUE;
+
+ RayPayload payload = (RayPayload)0;
+ payload.instanceID = ~0u;
+ payload.throughput = 1.0;
+
+#if USE_RAY_QUERY
+ RayQuery rayQuery;
+
+ rayQuery.TraceRayInline(accelStruct, rayFlags, instanceMask, ray);
+
+ while (rayQuery.Proceed())
+ {
+ if (rayQuery.CandidateType() == CANDIDATE_NON_OPAQUE_TRIANGLE)
+ {
+ if (considerTransparentMaterial(
+ rayQuery.CandidateInstanceID(),
+ rayQuery.CandidateGeometryIndex(),
+ rayQuery.CandidatePrimitiveIndex(),
+ rayQuery.CandidateTriangleBarycentrics(),
+ payload.throughput))
+ {
+ rayQuery.CommitNonOpaqueTriangleHit();
+ }
+ }
+ }
+
+ if (rayQuery.CommittedStatus() == COMMITTED_TRIANGLE_HIT)
+ {
+ payload.instanceID = rayQuery.CommittedInstanceID();
+ payload.primitiveIndex = rayQuery.CommittedPrimitiveIndex();
+ payload.geometryIndex = rayQuery.CommittedGeometryIndex();
+ payload.barycentrics = rayQuery.CommittedTriangleBarycentrics();
+ payload.committedRayT = rayQuery.CommittedRayT();
+ payload.frontFace = rayQuery.CommittedTriangleFrontFace();
+ }
+#else
+ TraceRay(accelStruct, rayFlags, instanceMask, 0, 0, 0, ray, payload);
+#endif
+
+ REPORT_RAY(payload.instanceID != ~0u);
+
+ if(payload.instanceID == ~0u)
+ return payload.throughput.rgb;
+ else
+ return 0;
+}
+
+// Traces a cheap visibility ray that returns approximate, conservative visibility
+// between the surface and the light sample. Conservative means if unsure, assume the light is visible.
+// Significant differences between this conservative visibility and the final one will result in more noise.
+// This function is used in the spatial resampling functions for ray traced bias correction.
+bool RAB_GetConservativeVisibility(RAB_Surface surface, float3 samplePosition)
+{
+ return GetConservativeVisibility(SceneBVH, surface, samplePosition);
+}
+
+// Same as RAB_GetConservativeVisibility but for temporal resampling.
+// When the previous frame TLAS and BLAS are available, the implementation should use the previous position and the previous AS.
+// When they are not available, use the current AS. That will result in transient bias.
+bool RAB_GetTemporalConservativeVisibility(RAB_Surface currentSurface, RAB_Surface previousSurface, float3 samplePosition)
+{
+ if (g_Const.enablePreviousTLAS)
+ return GetConservativeVisibility(PrevSceneBVH, previousSurface, samplePosition);
+ else
+ return GetConservativeVisibility(SceneBVH, currentSurface, samplePosition);
+}
+
+#endif // RAB_VISIBILITY_TEST_HLSLI
\ No newline at end of file
diff --git a/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli
new file mode 100644
index 0000000..35a4c8c
--- /dev/null
+++ b/Samples/FullSample/Shaders/LightingPasses/RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli
@@ -0,0 +1,48 @@
+/***************************************************************************
+ # Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
+ #
+ # NVIDIA CORPORATION and its licensors retain all intellectual property
+ # and proprietary rights in and to this software, related documentation
+ # and any modifications thereto. Any use, reproduction, disclosure or
+ # distribution of this software and related documentation without an express
+ # license agreement from NVIDIA CORPORATION is strictly prohibited.
+ **************************************************************************/
+
+/*
+This header file is the bridge between the RTXDI resampling functions
+and the application resources and parts of shader functionality.
+
+The RTXDI SDK provides the resampling logic, and the application provides
+other necessary aspects:
+ - Material BRDF evaluation;
+ - Ray tracing and transparent/alpha-tested material processing;
+ - Light sampling functions and emission profiles.
+
+The structures and functions that are necessary for SDK operation
+start with the RAB_ prefix (for RTXDI-Application Bridge).
+
+All structures defined here are opaque for the SDK, meaning that
+it makes no assumptions about their contents, they are just passed
+between the bridge functions.
+*/
+
+#ifndef RTXDI_APPLICATION_BRIDGE_HLSLI
+#define RTXDI_APPLICATION_BRIDGE_HLSLI
+
+#include "../../ShaderParameters.h"
+#include "../../SceneGeometry.hlsli"
+
+#include "RAB_Buffers.hlsli"
+
+#include "RAB_LightInfo.hlsli"
+#include "RAB_LightSample.hlsli"
+#include "RAB_LightSampling.hlsli"
+#include "RAB_Material.hlsli"
+#include "RAB_RandomSamplerState.hlsli"
+#include "RAB_RayPayload.hlsli"
+#include "RAB_RTShaders.hlsli"
+#include "RAB_SpatialHelpers.hlsli"
+#include "RAB_Surface.hlsli"
+#include "RAB_VisibilityTest.hlsli"
+
+#endif // RTXDI_APPLICATION_BRIDGE_HLSLI
diff --git a/shaders/LightingPasses/ShadeSecondarySurfaces.hlsl b/Samples/FullSample/Shaders/LightingPasses/ShadeSecondarySurfaces.hlsl
similarity index 92%
rename from shaders/LightingPasses/ShadeSecondarySurfaces.hlsl
rename to Samples/FullSample/Shaders/LightingPasses/ShadeSecondarySurfaces.hlsl
index 5056209..8f3e944 100644
--- a/shaders/LightingPasses/ShadeSecondarySurfaces.hlsl
+++ b/Samples/FullSample/Shaders/LightingPasses/ShadeSecondarySurfaces.hlsl
@@ -14,11 +14,11 @@
// because we do not trace the BRDF rays further.
#define RAB_ENABLE_SPECULAR_MIS 0
-#include "RtxdiApplicationBridge.hlsli"
+#include "RtxdiApplicationBridge/RtxdiApplicationBridge.hlsli"
-#include
-#include
-#include
+#include
+#include
+#include
#ifdef WITH_NRD
#define NRD_HEADER_ONLY
@@ -71,10 +71,10 @@ void RayGen()
secondarySurface.viewDepth = 1.0; // doesn't matter
secondarySurface.normal = octToNdirUnorm32(secondaryGBufferData.normal);
secondarySurface.geoNormal = secondarySurface.normal;
- secondarySurface.diffuseAlbedo = Unpack_R11G11B10_UFLOAT(secondaryGBufferData.diffuseAlbedo);
+ secondarySurface.material.diffuseAlbedo = Unpack_R11G11B10_UFLOAT(secondaryGBufferData.diffuseAlbedo);
float4 specularRough = Unpack_R8G8B8A8_Gamma_UFLOAT(secondaryGBufferData.specularAndRoughness);
- secondarySurface.specularF0 = specularRough.rgb;
- secondarySurface.roughness = specularRough.a;
+ secondarySurface.material.specularF0 = specularRough.rgb;
+ secondarySurface.material.roughness = specularRough.a;
secondarySurface.diffuseProbability = getSurfaceDiffuseProbability(secondarySurface);
secondarySurface.viewDir = normalize(primarySurface.worldPos - secondarySurface.worldPos);
@@ -136,7 +136,7 @@ void RayGen()
ShadeSurfaceWithLightSample(reservoir, secondarySurface, lightSample, /* previousFrameTLAS = */ false,
/* enableVisibilityReuse = */ false, indirectDiffuse, indirectSpecular, lightDistance);
- radiance += indirectDiffuse * secondarySurface.diffuseAlbedo + indirectSpecular;
+ radiance += indirectDiffuse * secondarySurface.material.diffuseAlbedo + indirectSpecular;
// Firefly suppression
float indirectLuminance = calcLuminance(radiance);
@@ -172,9 +172,9 @@ void RayGen()
float3 diffuse = isSpecularRay ? 0.0 : radiance * throughput.rgb;
float3 specular = isSpecularRay ? radiance * throughput.rgb : 0.0;
- specular = DemodulateSpecular(primarySurface.specularF0, specular);
+ specular = DemodulateSpecular(primarySurface.material.specularF0, specular);
StoreShadingOutput(GlobalIndex, pixelPosition,
- primarySurface.viewDepth, primarySurface.roughness, diffuse, specular, 0, false, true);
+ primarySurface.viewDepth, primarySurface.material.roughness, diffuse, specular, 0, false, true);
}
}
diff --git a/shaders/LightingPasses/ShadingHelpers.hlsli b/Samples/FullSample/Shaders/LightingPasses/ShadingHelpers.hlsli
similarity index 90%
rename from shaders/LightingPasses/ShadingHelpers.hlsli
rename to Samples/FullSample/Shaders/LightingPasses/ShadingHelpers.hlsli
index 43bd59e..1e26fd1 100644
--- a/shaders/LightingPasses/ShadingHelpers.hlsli
+++ b/Samples/FullSample/Shaders/LightingPasses/ShadingHelpers.hlsli
@@ -11,6 +11,30 @@
#ifndef SHADING_HELPERS_HLSLI
#define SHADING_HELPERS_HLSLI
+#include "NRDEncoding.hlsli"
+#include "NRD.hlsli"
+
+struct SplitBrdf
+{
+ float demodulatedDiffuse;
+ float3 specular;
+};
+
+SplitBrdf EvaluateBrdf(RAB_Surface surface, float3 samplePosition)
+{
+ float3 N = surface.normal;
+ float3 V = surface.viewDir;
+ float3 L = normalize(samplePosition - surface.worldPos);
+
+ SplitBrdf brdf;
+ brdf.demodulatedDiffuse = Lambert(surface.normal, -L);
+ if (surface.material.roughness == 0)
+ brdf.specular = 0;
+ else
+ brdf.specular = GGX_times_NdotL(V, L, surface.normal, max(surface.material.roughness, kMinRoughness), surface.material.specularF0);
+ return brdf;
+}
+
#ifdef RTXDI_DIRESERVOIR_HLSLI
bool ShadeSurfaceWithLightSample(
diff --git a/shaders/PolymorphicLight.hlsli b/Samples/FullSample/Shaders/PolymorphicLight.hlsli
similarity index 99%
rename from shaders/PolymorphicLight.hlsli
rename to Samples/FullSample/Shaders/PolymorphicLight.hlsli
index 1ce072c..c069dbc 100644
--- a/shaders/PolymorphicLight.hlsli
+++ b/Samples/FullSample/Shaders/PolymorphicLight.hlsli
@@ -13,7 +13,6 @@
#include "HelperFunctions.hlsli"
#include "LightShaping.hlsli"
-#include
#define LIGHT_SAMPING_EPSILON 1e-10
#define DISTANT_LIGHT_DISTANCE 10000.0
diff --git a/shaders/PostprocessGBuffer.hlsl b/Samples/FullSample/Shaders/PostprocessGBuffer.hlsl
similarity index 100%
rename from shaders/PostprocessGBuffer.hlsl
rename to Samples/FullSample/Shaders/PostprocessGBuffer.hlsl
diff --git a/shaders/PrepareLights.hlsl b/Samples/FullSample/Shaders/PrepareLights.hlsl
similarity index 99%
rename from shaders/PrepareLights.hlsl
rename to Samples/FullSample/Shaders/PrepareLights.hlsl
index f93a446..625f6ec 100644
--- a/shaders/PrepareLights.hlsl
+++ b/Samples/FullSample/Shaders/PrepareLights.hlsl
@@ -11,9 +11,9 @@
#pragma pack_matrix(row_major)
#include
-#include
+#include
#include
-#include
+#include
#include "ShaderParameters.h"
VK_PUSH_CONSTANT ConstantBuffer g_Const : register(b0);
diff --git a/shaders/PreprocessEnvironmentMap.hlsl b/Samples/FullSample/Shaders/PreprocessEnvironmentMap.hlsl
similarity index 98%
rename from shaders/PreprocessEnvironmentMap.hlsl
rename to Samples/FullSample/Shaders/PreprocessEnvironmentMap.hlsl
index 70c563a..d4d5b3c 100644
--- a/shaders/PreprocessEnvironmentMap.hlsl
+++ b/Samples/FullSample/Shaders/PreprocessEnvironmentMap.hlsl
@@ -10,8 +10,8 @@
#include "ShaderParameters.h"
#include "HelperFunctions.hlsli"
-#include
-#include
+#include
+#include
RWTexture2D u_IntegratedMips[] : register(u0);
diff --git a/shaders/RasterizedGBuffer.hlsl b/Samples/FullSample/Shaders/RasterizedGBuffer.hlsl
similarity index 100%
rename from shaders/RasterizedGBuffer.hlsl
rename to Samples/FullSample/Shaders/RasterizedGBuffer.hlsl
diff --git a/shaders/RaytracedGBuffer.hlsl b/Samples/FullSample/Shaders/RaytracedGBuffer.hlsl
similarity index 100%
rename from shaders/RaytracedGBuffer.hlsl
rename to Samples/FullSample/Shaders/RaytracedGBuffer.hlsl
diff --git a/shaders/RenderEnvironmentMap.hlsl b/Samples/FullSample/Shaders/RenderEnvironmentMap.hlsl
similarity index 95%
rename from shaders/RenderEnvironmentMap.hlsl
rename to Samples/FullSample/Shaders/RenderEnvironmentMap.hlsl
index dc5fdf5..e023591 100644
--- a/shaders/RenderEnvironmentMap.hlsl
+++ b/Samples/FullSample/Shaders/RenderEnvironmentMap.hlsl
@@ -11,7 +11,7 @@
#include "ShaderParameters.h"
#include "HelperFunctions.hlsli"
#include
-#include
+#include
VK_PUSH_CONSTANT ConstantBuffer g_Const : register(b0);
diff --git a/minimal/shaders/SceneGeometry.hlsli b/Samples/FullSample/Shaders/SceneGeometry.hlsli
similarity index 99%
rename from minimal/shaders/SceneGeometry.hlsli
rename to Samples/FullSample/Shaders/SceneGeometry.hlsli
index f910659..29a0ab3 100644
--- a/minimal/shaders/SceneGeometry.hlsli
+++ b/Samples/FullSample/Shaders/SceneGeometry.hlsli
@@ -13,7 +13,7 @@
#include
-#include
+#include
#include
#include
diff --git a/shaders/ShaderParameters.h b/Samples/FullSample/Shaders/ShaderParameters.h
similarity index 98%
rename from shaders/ShaderParameters.h
rename to Samples/FullSample/Shaders/ShaderParameters.h
index 549153c..e029771 100644
--- a/shaders/ShaderParameters.h
+++ b/Samples/FullSample/Shaders/ShaderParameters.h
@@ -14,9 +14,9 @@
#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
#include "BRDFPTParameters.h"
diff --git a/Samples/FullSample/Shaders/Shaders.cfg b/Samples/FullSample/Shaders/Shaders.cfg
new file mode 100644
index 0000000..ef6266e
--- /dev/null
+++ b/Samples/FullSample/Shaders/Shaders.cfg
@@ -0,0 +1,51 @@
+RasterizedGBuffer.hlsl -T vs -E vs_main
+RasterizedGBuffer.hlsl -T ps -E ps_main -D ALPHA_TESTED={0,1}
+RaytracedGBuffer.hlsl -T cs -E main -D USE_RAY_QUERY=1
+RaytracedGBuffer.hlsl -T lib -D USE_RAY_QUERY=0
+CompositingPass.hlsl -T cs -E main
+GlassPass.hlsl -T cs -E main -D USE_RAY_QUERY=1
+GlassPass.hlsl -T lib -D USE_RAY_QUERY=0
+AccumulationPass.hlsl -T cs -E main
+RenderEnvironmentMap.hlsl -T cs -E main
+PreprocessEnvironmentMap.hlsl -T cs -E main -D INPUT_ENVIRONMENT_MAP={0,1}
+VisualizeHdrSignals.hlsl -T ps -E main
+VisualizeConfidence.hlsl -T ps -E main
+DlssExposure.hlsl -T cs -E main
+PostprocessGBuffer.hlsl -T cs -E main
+DebugViz/NDirOctUNorm32Viz.hlsl -T cs -E main
+DebugViz/PackedR8G8B8A8GammaUFloatViz.hlsl -T cs -E main
+DebugViz/PackedR11G11B10UFloatViz.hlsl -T cs -E main
+
+PrepareLights.hlsl -T cs -E main
+LightingPasses/Presampling/PresampleLights.hlsl -T cs -E main
+LightingPasses/Presampling/PresampleEnvironmentMap.hlsl -T cs -E main
+LightingPasses/Presampling/PresampleReGIR.hlsl -T cs -E main -D RTXDI_REGIR_MODE={RTXDI_REGIR_GRID,RTXDI_REGIR_ONION}
+LightingPasses/DI/GenerateInitialSamples.hlsl -T cs -E main -D USE_RAY_QUERY=1 -D RTXDI_REGIR_MODE={RTXDI_REGIR_DISABLED,RTXDI_REGIR_GRID,RTXDI_REGIR_ONION}
+LightingPasses/DI/GenerateInitialSamples.hlsl -T lib -D USE_RAY_QUERY=0 -D RTXDI_REGIR_MODE={RTXDI_REGIR_DISABLED,RTXDI_REGIR_GRID,RTXDI_REGIR_ONION}
+LightingPasses/DI/TemporalResampling.hlsl -T cs -E main -D USE_RAY_QUERY=1
+LightingPasses/DI/TemporalResampling.hlsl -T lib -D USE_RAY_QUERY=0
+LightingPasses/DI/SpatialResampling.hlsl -T cs -E main -D USE_RAY_QUERY=1
+LightingPasses/DI/SpatialResampling.hlsl -T lib -D USE_RAY_QUERY=0
+LightingPasses/DI/FusedResampling.hlsl -T cs -E main -D USE_RAY_QUERY=1 -D RTXDI_REGIR_MODE={RTXDI_REGIR_DISABLED,RTXDI_REGIR_GRID,RTXDI_REGIR_ONION}
+LightingPasses/DI/FusedResampling.hlsl -T lib -D USE_RAY_QUERY=0 -D RTXDI_REGIR_MODE={RTXDI_REGIR_DISABLED,RTXDI_REGIR_GRID,RTXDI_REGIR_ONION}
+LightingPasses/DI/ShadeSamples.hlsl -T cs -E main -D USE_RAY_QUERY=1 -D RTXDI_REGIR_MODE={RTXDI_REGIR_DISABLED,RTXDI_REGIR_GRID,RTXDI_REGIR_ONION}
+LightingPasses/DI/ShadeSamples.hlsl -T lib -D USE_RAY_QUERY=0 -D RTXDI_REGIR_MODE={RTXDI_REGIR_DISABLED,RTXDI_REGIR_GRID,RTXDI_REGIR_ONION}
+
+LightingPasses/BrdfRayTracing.hlsl -T cs -E main -D USE_RAY_QUERY=1
+LightingPasses/BrdfRayTracing.hlsl -T lib -D USE_RAY_QUERY=0
+LightingPasses/ShadeSecondarySurfaces.hlsl -T cs -E main -D USE_RAY_QUERY=1 -D RTXDI_REGIR_MODE={RTXDI_REGIR_DISABLED,RTXDI_REGIR_GRID,RTXDI_REGIR_ONION}
+LightingPasses/ShadeSecondarySurfaces.hlsl -T lib -D USE_RAY_QUERY=0 -D RTXDI_REGIR_MODE={RTXDI_REGIR_DISABLED,RTXDI_REGIR_GRID,RTXDI_REGIR_ONION}
+
+DenoisingPasses/ComputeGradients.hlsl -T cs -E main -D USE_RAY_QUERY=1
+DenoisingPasses/ComputeGradients.hlsl -T lib -D USE_RAY_QUERY=0
+DenoisingPasses/FilterGradientsPass.hlsl -T cs -E main
+DenoisingPasses/ConfidencePass.hlsl -T cs -E main
+
+LightingPasses/GI/TemporalResampling.hlsl -T cs -E main -D USE_RAY_QUERY=1
+LightingPasses/GI/TemporalResampling.hlsl -T lib -E main -D USE_RAY_QUERY=0
+LightingPasses/GI/SpatialResampling.hlsl -T cs -E main -D USE_RAY_QUERY=1
+LightingPasses/GI/SpatialResampling.hlsl -T lib -E main -D USE_RAY_QUERY=0
+LightingPasses/GI/FusedResampling.hlsl -T cs -E main -D USE_RAY_QUERY=1
+LightingPasses/GI/FusedResampling.hlsl -T lib -E main -D USE_RAY_QUERY=0
+LightingPasses/GI/FinalShading.hlsl -T cs -E main -D USE_RAY_QUERY=1
+LightingPasses/GI/FinalShading.hlsl -T lib -E main -D USE_RAY_QUERY=0
diff --git a/shaders/VisualizeConfidence.hlsl b/Samples/FullSample/Shaders/VisualizeConfidence.hlsl
similarity index 100%
rename from shaders/VisualizeConfidence.hlsl
rename to Samples/FullSample/Shaders/VisualizeConfidence.hlsl
diff --git a/shaders/VisualizeHdrSignals.hlsl b/Samples/FullSample/Shaders/VisualizeHdrSignals.hlsl
similarity index 97%
rename from shaders/VisualizeHdrSignals.hlsl
rename to Samples/FullSample/Shaders/VisualizeHdrSignals.hlsl
index 2092235..c3ea521 100644
--- a/shaders/VisualizeHdrSignals.hlsl
+++ b/Samples/FullSample/Shaders/VisualizeHdrSignals.hlsl
@@ -13,8 +13,7 @@
#include "ShaderParameters.h"
#include "HelperFunctions.hlsli"
-#include
-#include
+#include
ConstantBuffer g_Const : register(b0);
Texture2D t_CompositedColor : register(t0);
@@ -31,8 +30,8 @@ StructuredBuffer t_GIReservoirs : register(t9);
#define RTXDI_LIGHT_RESERVOIR_BUFFER t_Reservoirs
#define RTXDI_GI_RESERVOIR_BUFFER t_GIReservoirs
#define RTXDI_ENABLE_STORE_RESERVOIR 0
-#include
-#include
+#include
+#include
float4 blend(float4 top, float4 bottom)
{
diff --git a/src/AppDefines.h b/Samples/FullSample/Source/AppDefines.h
similarity index 100%
rename from src/AppDefines.h
rename to Samples/FullSample/Source/AppDefines.h
diff --git a/Samples/FullSample/Source/CMakeLists.txt b/Samples/FullSample/Source/CMakeLists.txt
new file mode 100644
index 0000000..9522ea6
--- /dev/null
+++ b/Samples/FullSample/Source/CMakeLists.txt
@@ -0,0 +1,93 @@
+set(project FullSample)
+set(folder "RTXDI SDK")
+
+set(sources
+ "DebugViz/DebugVizPasses.cpp"
+ "DebugViz/DebugVizPasses.h"
+ "DebugViz/PackedDataVizPass.cpp"
+ "DebugViz/PackedDataVizPass.h"
+ "RenderPasses/AccumulationPass.cpp"
+ "RenderPasses/AccumulationPass.h"
+ "RenderPasses/CompositingPass.cpp"
+ "RenderPasses/CompositingPass.h"
+ "RenderPasses/ConfidencePass.cpp"
+ "RenderPasses/ConfidencePass.h"
+ "RenderPasses/FilterGradientsPass.cpp"
+ "RenderPasses/FilterGradientsPass.h"
+ "RenderPasses/GBufferPass.cpp"
+ "RenderPasses/GBufferPass.h"
+ "RenderPasses/GenerateMipsPass.cpp"
+ "RenderPasses/GenerateMipsPass.h"
+ "RenderPasses/GlassPass.cpp"
+ "RenderPasses/GlassPass.h"
+ "RenderPasses/LightingPasses.cpp"
+ "RenderPasses/LightingPasses.h"
+ "RenderPasses/PrepareLightsPass.cpp"
+ "RenderPasses/PrepareLightsPass.h"
+ "RenderPasses/RaytracingPass.cpp"
+ "RenderPasses/RaytracingPass.h"
+ "RenderPasses/RenderEnvironmentMapPass.cpp"
+ "RenderPasses/RenderEnvironmentMapPass.h"
+ "RenderPasses/VisualizationPass.cpp"
+ "RenderPasses/VisualizationPass.h"
+ "AppDefines.h"
+ "DLSS-DX12.cpp"
+ "DLSS-VK.cpp"
+ "DLSS.cpp"
+ "DLSS.h"
+ "main.cpp"
+ "NrdIntegration.cpp"
+ "NrdIntegration.h"
+ "Profiler.cpp"
+ "Profiler.h"
+ "ProfilerSections.h"
+ "RenderTargets.cpp"
+ "RenderTargets.h"
+ "RtxdiResources.cpp"
+ "RtxdiResources.h"
+ "SampleScene.cpp"
+ "SampleScene.h"
+ "Testing.cpp"
+ "Testing.h"
+ "UserInterface.cpp"
+ "UserInterface.h")
+
+# Organize MSVS filters (the little folders in the solution explorer) to match the folder structure
+foreach(source IN LISTS sources)
+ get_filename_component(source_path "${source}" PATH)
+ string(REPLACE "/" "\\" source_path_msvc "${source_path}")
+ source_group("${source_path_msvc}" FILES "${source}")
+endforeach()
+
+
+include(CMakeDependentOption)
+
+cmake_dependent_option(RTXDI_CONSOLE_APP "Build the sample as a console application" OFF WIN32 OFF)
+
+if (RTXDI_CONSOLE_APP)
+ add_executable(${project} ${sources})
+ target_compile_definitions(${project} PRIVATE IS_CONSOLE_APP=1)
+else()
+ add_executable(${project} WIN32 ${sources})
+endif()
+
+target_link_libraries(${project} donut_core donut_engine donut_app donut_render Rtxdi cxxopts)
+add_dependencies(${project} FullSampleShaders)
+set_target_properties(${project} PROPERTIES FOLDER ${folder})
+
+if (TARGET NRD)
+ target_compile_definitions(${project} PRIVATE WITH_NRD=1)
+ target_link_libraries(${project} NRD)
+
+ # NRD doesn't add a public include path at this time, work around that
+ target_include_directories(${project} PRIVATE "${CMAKE_SOURCE_DIR}/NRD/Include")
+endif()
+
+if (TARGET DLSS)
+ target_compile_definitions(${project} PRIVATE WITH_DLSS=1)
+ target_link_libraries(${project} DLSS)
+ add_custom_command(TARGET ${project} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${DLSS_SHARED_LIBRARY_PATH}"
+ "$/")
+endif()
diff --git a/src/DLSS-DX12.cpp b/Samples/FullSample/Source/DLSS-DX12.cpp
similarity index 81%
rename from src/DLSS-DX12.cpp
rename to Samples/FullSample/Source/DLSS-DX12.cpp
index 17a5154..9dec599 100644
--- a/src/DLSS-DX12.cpp
+++ b/Samples/FullSample/Source/DLSS-DX12.cpp
@@ -43,7 +43,7 @@ class DLSS_DX12 : public DLSS
featureCommonInfo.LoggingInfo.MinimumLoggingLevel = NVSDK_NGX_LOGGING_LEVEL_OFF;
featureCommonInfo.LoggingInfo.DisableOtherLoggingSinks = true;
- NVSDK_NGX_Result result = NVSDK_NGX_D3D12_Init(c_ApplicationID, executablePathW.c_str(), d3ddevice, &featureCommonInfo);
+ NVSDK_NGX_Result result = NVSDK_NGX_D3D12_Init(c_applicationID, executablePathW.c_str(), d3ddevice, &featureCommonInfo);
if (result != NVSDK_NGX_Result_Success)
{
@@ -51,44 +51,44 @@ class DLSS_DX12 : public DLSS
return;
}
- result = NVSDK_NGX_D3D12_GetCapabilityParameters(&m_Parameters);
+ result = NVSDK_NGX_D3D12_GetCapabilityParameters(&m_parameters);
if (result != NVSDK_NGX_Result_Success)
return;
int dlssAvailable = 0;
- result = m_Parameters->Get(NVSDK_NGX_Parameter_SuperSampling_Available, &dlssAvailable);
+ result = m_parameters->Get(NVSDK_NGX_Parameter_SuperSampling_Available, &dlssAvailable);
if (result != NVSDK_NGX_Result_Success || !dlssAvailable)
{
result = NVSDK_NGX_Result_Fail;
- NVSDK_NGX_Parameter_GetI(m_Parameters, NVSDK_NGX_Parameter_SuperSampling_FeatureInitResult, (int*)&result);
+ NVSDK_NGX_Parameter_GetI(m_parameters, NVSDK_NGX_Parameter_SuperSampling_FeatureInitResult, (int*)&result);
log::warning("NVIDIA DLSS is not available on this system, FeatureInitResult = 0x%08x (%ls)",
result, GetNGXResultAsString(result));
return;
}
- m_FeatureSupported = true;
+ m_featureSupported = true;
}
void SetRenderSize(
uint32_t inputWidth, uint32_t inputHeight,
uint32_t outputWidth, uint32_t outputHeight) override
{
- if (!m_FeatureSupported)
+ if (!m_featureSupported)
return;
- if (m_InputWidth == inputWidth && m_InputHeight == inputHeight && m_OutputWidth == outputWidth && m_OutputHeight == outputHeight)
+ if (m_inputWidth == inputWidth && m_inputHeight == inputHeight && m_outputWidth == outputWidth && m_outputHeight == outputHeight)
return;
- if (m_DlssHandle)
+ if (m_dlssHandle)
{
- m_Device->waitForIdle();
- NVSDK_NGX_D3D12_ReleaseFeature(m_DlssHandle);
- m_DlssHandle = nullptr;
+ m_device->waitForIdle();
+ NVSDK_NGX_D3D12_ReleaseFeature(m_dlssHandle);
+ m_dlssHandle = nullptr;
}
- m_FeatureCommandList->open();
- ID3D12GraphicsCommandList* d3dcmdlist = m_FeatureCommandList->getNativeObject(nvrhi::ObjectTypes::D3D12_GraphicsCommandList);
+ m_featureCommandList->open();
+ ID3D12GraphicsCommandList* d3dcmdlist = m_featureCommandList->getNativeObject(nvrhi::ObjectTypes::D3D12_GraphicsCommandList);
NVSDK_NGX_DLSS_Create_Params dlssParams = {};
dlssParams.Feature.InWidth = inputWidth;
@@ -101,10 +101,10 @@ class DLSS_DX12 : public DLSS
NVSDK_NGX_DLSS_Feature_Flags_DepthInverted |
NVSDK_NGX_DLSS_Feature_Flags_MVLowRes;
- NVSDK_NGX_Result result = NGX_D3D12_CREATE_DLSS_EXT(d3dcmdlist, 1, 1, &m_DlssHandle, m_Parameters, &dlssParams);
+ NVSDK_NGX_Result result = NGX_D3D12_CREATE_DLSS_EXT(d3dcmdlist, 1, 1, &m_dlssHandle, m_parameters, &dlssParams);
- m_FeatureCommandList->close();
- m_Device->executeCommandList(m_FeatureCommandList);
+ m_featureCommandList->close();
+ m_device->executeCommandList(m_featureCommandList);
if (result != NVSDK_NGX_Result_Success)
{
@@ -112,12 +112,12 @@ class DLSS_DX12 : public DLSS
return;
}
- m_IsAvailable = true;
+ m_isAvailable = true;
- m_InputWidth = inputWidth;
- m_InputHeight = inputHeight;
- m_OutputWidth = outputWidth;
- m_OutputHeight = outputHeight;
+ m_inputWidth = inputWidth;
+ m_inputHeight = inputHeight;
+ m_outputWidth = outputWidth;
+ m_outputHeight = outputHeight;
}
void Render(
@@ -131,7 +131,7 @@ class DLSS_DX12 : public DLSS
const donut::engine::PlanarView& view,
const donut::engine::PlanarView& viewPrev) override
{
- if (!m_IsAvailable)
+ if (!m_isAvailable)
return;
commandList->beginMarker("DLSS");
@@ -146,7 +146,7 @@ class DLSS_DX12 : public DLSS
commandList->setTextureState(renderTargets.ResolvedColor, nvrhi::AllSubresources, nvrhi::ResourceStates::UnorderedAccess);
commandList->setTextureState(depthTexture, nvrhi::AllSubresources, nvrhi::ResourceStates::ShaderResource);
commandList->setTextureState(renderTargets.MotionVectors, nvrhi::AllSubresources, nvrhi::ResourceStates::ShaderResource);
- commandList->setTextureState(m_ExposureTexture, nvrhi::AllSubresources, nvrhi::ResourceStates::ShaderResource);
+ commandList->setTextureState(m_exposureTexture, nvrhi::AllSubresources, nvrhi::ResourceStates::ShaderResource);
commandList->commitBarriers();
NVSDK_NGX_D3D12_DLSS_Eval_Params evalParams = {};
@@ -155,14 +155,14 @@ class DLSS_DX12 : public DLSS
evalParams.Feature.InSharpness = sharpness;
evalParams.pInDepth = depthTexture->getNativeObject(nvrhi::ObjectTypes::D3D12_Resource);
evalParams.pInMotionVectors = renderTargets.MotionVectors->getNativeObject(nvrhi::ObjectTypes::D3D12_Resource);
- evalParams.pInExposureTexture = m_ExposureTexture->getNativeObject(nvrhi::ObjectTypes::D3D12_Resource);
+ evalParams.pInExposureTexture = m_exposureTexture->getNativeObject(nvrhi::ObjectTypes::D3D12_Resource);
evalParams.InReset = resetHistory;
evalParams.InJitterOffsetX = view.GetPixelOffset().x;
evalParams.InJitterOffsetY = view.GetPixelOffset().y;
evalParams.InRenderSubrectDimensions.Width = view.GetViewExtent().width();
evalParams.InRenderSubrectDimensions.Height = view.GetViewExtent().height();
- NVSDK_NGX_Result result = NGX_D3D12_EVALUATE_DLSS_EXT(d3dcmdlist, m_DlssHandle, m_Parameters, &evalParams);
+ NVSDK_NGX_Result result = NGX_D3D12_EVALUATE_DLSS_EXT(d3dcmdlist, m_dlssHandle, m_parameters, &evalParams);
commandList->clearState();
@@ -177,16 +177,16 @@ class DLSS_DX12 : public DLSS
~DLSS_DX12() override
{
- if (m_DlssHandle)
+ if (m_dlssHandle)
{
- NVSDK_NGX_D3D12_ReleaseFeature(m_DlssHandle);
- m_DlssHandle = nullptr;
+ NVSDK_NGX_D3D12_ReleaseFeature(m_dlssHandle);
+ m_dlssHandle = nullptr;
}
- if (m_Parameters)
+ if (m_parameters)
{
- NVSDK_NGX_D3D12_DestroyParameters(m_Parameters);
- m_Parameters = nullptr;
+ NVSDK_NGX_D3D12_DestroyParameters(m_parameters);
+ m_parameters = nullptr;
}
NVSDK_NGX_D3D12_Shutdown();
diff --git a/src/DLSS-VK.cpp b/Samples/FullSample/Source/DLSS-VK.cpp
similarity index 85%
rename from src/DLSS-VK.cpp
rename to Samples/FullSample/Source/DLSS-VK.cpp
index 6ff5bbe..2de8cc9 100644
--- a/src/DLSS-VK.cpp
+++ b/Samples/FullSample/Source/DLSS-VK.cpp
@@ -47,7 +47,7 @@ class DLSS_VK : public DLSS
featureCommonInfo.LoggingInfo.MinimumLoggingLevel = NVSDK_NGX_LOGGING_LEVEL_OFF;
featureCommonInfo.LoggingInfo.DisableOtherLoggingSinks = true;
- NVSDK_NGX_Result result = NVSDK_NGX_VULKAN_Init(c_ApplicationID,
+ NVSDK_NGX_Result result = NVSDK_NGX_VULKAN_Init(c_applicationID,
executablePathW.c_str(), vkInstance, vkPhysicalDevice, vkDevice, &featureCommonInfo);
if (result != NVSDK_NGX_Result_Success)
@@ -56,44 +56,44 @@ class DLSS_VK : public DLSS
return;
}
- result = NVSDK_NGX_VULKAN_GetCapabilityParameters(&m_Parameters);
+ result = NVSDK_NGX_VULKAN_GetCapabilityParameters(&m_parameters);
if (result != NVSDK_NGX_Result_Success)
return;
int dlssAvailable = 0;
- result = m_Parameters->Get(NVSDK_NGX_Parameter_SuperSampling_Available, &dlssAvailable);
+ result = m_parameters->Get(NVSDK_NGX_Parameter_SuperSampling_Available, &dlssAvailable);
if (result != NVSDK_NGX_Result_Success || !dlssAvailable)
{
result = NVSDK_NGX_Result_Fail;
- NVSDK_NGX_Parameter_GetI(m_Parameters, NVSDK_NGX_Parameter_SuperSampling_FeatureInitResult, (int*)&result);
+ NVSDK_NGX_Parameter_GetI(m_parameters, NVSDK_NGX_Parameter_SuperSampling_FeatureInitResult, (int*)&result);
log::warning("NVIDIA DLSS is not available on this system, FeatureInitResult = 0x%08x (%ls)",
result, GetNGXResultAsString(result));
return;
}
- m_FeatureSupported = true;
+ m_featureSupported = true;
}
void SetRenderSize(
uint32_t inputWidth, uint32_t inputHeight,
uint32_t outputWidth, uint32_t outputHeight) override
{
- if (!m_FeatureSupported)
+ if (!m_featureSupported)
return;
- if (m_InputWidth == inputWidth && m_InputHeight == inputHeight && m_OutputWidth == outputWidth && m_OutputHeight == outputHeight)
+ if (m_inputWidth == inputWidth && m_inputHeight == inputHeight && m_outputWidth == outputWidth && m_outputHeight == outputHeight)
return;
- if (m_DlssHandle)
+ if (m_dlssHandle)
{
- m_Device->waitForIdle();
- NVSDK_NGX_VULKAN_ReleaseFeature(m_DlssHandle);
- m_DlssHandle = nullptr;
+ m_device->waitForIdle();
+ NVSDK_NGX_VULKAN_ReleaseFeature(m_dlssHandle);
+ m_dlssHandle = nullptr;
}
- m_FeatureCommandList->open();
- VkCommandBuffer vkCmdBuf = m_FeatureCommandList->getNativeObject(nvrhi::ObjectTypes::VK_CommandBuffer);
+ m_featureCommandList->open();
+ VkCommandBuffer vkCmdBuf = m_featureCommandList->getNativeObject(nvrhi::ObjectTypes::VK_CommandBuffer);
NVSDK_NGX_DLSS_Create_Params dlssParams = {};
dlssParams.Feature.InWidth = inputWidth;
@@ -106,10 +106,10 @@ class DLSS_VK : public DLSS
NVSDK_NGX_DLSS_Feature_Flags_DepthInverted |
NVSDK_NGX_DLSS_Feature_Flags_MVLowRes;
- NVSDK_NGX_Result result = NGX_VULKAN_CREATE_DLSS_EXT(vkCmdBuf, 1, 1, &m_DlssHandle, m_Parameters, &dlssParams);
+ NVSDK_NGX_Result result = NGX_VULKAN_CREATE_DLSS_EXT(vkCmdBuf, 1, 1, &m_dlssHandle, m_parameters, &dlssParams);
- m_FeatureCommandList->close();
- m_Device->executeCommandList(m_FeatureCommandList);
+ m_featureCommandList->close();
+ m_device->executeCommandList(m_featureCommandList);
if (result != NVSDK_NGX_Result_Success)
{
@@ -117,12 +117,12 @@ class DLSS_VK : public DLSS
return;
}
- m_IsAvailable = true;
+ m_isAvailable = true;
- m_InputWidth = inputWidth;
- m_InputHeight = inputHeight;
- m_OutputWidth = outputWidth;
- m_OutputHeight = outputHeight;
+ m_inputWidth = inputWidth;
+ m_inputHeight = inputHeight;
+ m_outputWidth = outputWidth;
+ m_outputHeight = outputHeight;
}
static void FillTextureResource(NVSDK_NGX_Resource_VK& resource, nvrhi::ITexture* texture)
@@ -155,7 +155,7 @@ class DLSS_VK : public DLSS
const donut::engine::PlanarView& view,
const donut::engine::PlanarView& viewPrev) override
{
- if (!m_IsAvailable)
+ if (!m_isAvailable)
return;
ComputeExposure(commandList, toneMapperExposureBuffer, exposureScale);
@@ -173,13 +173,13 @@ class DLSS_VK : public DLSS
FillTextureResource(outColorResource, renderTargets.ResolvedColor);
FillTextureResource(depthResource, depthTexture);
FillTextureResource(motionVectorResource, renderTargets.MotionVectors);
- FillTextureResource(exposureResource, m_ExposureTexture);
+ FillTextureResource(exposureResource, m_exposureTexture);
commandList->setTextureState(renderTargets.HdrColor, nvrhi::AllSubresources, nvrhi::ResourceStates::ShaderResource);
commandList->setTextureState(renderTargets.ResolvedColor, nvrhi::AllSubresources, nvrhi::ResourceStates::UnorderedAccess);
commandList->setTextureState(depthTexture, nvrhi::AllSubresources, nvrhi::ResourceStates::ShaderResource);
commandList->setTextureState(renderTargets.MotionVectors, nvrhi::AllSubresources, nvrhi::ResourceStates::ShaderResource);
- commandList->setTextureState(m_ExposureTexture, nvrhi::AllSubresources, nvrhi::ResourceStates::ShaderResource);
+ commandList->setTextureState(m_exposureTexture, nvrhi::AllSubresources, nvrhi::ResourceStates::ShaderResource);
commandList->commitBarriers();
NVSDK_NGX_VK_DLSS_Eval_Params evalParams = {};
@@ -195,7 +195,7 @@ class DLSS_VK : public DLSS
evalParams.InRenderSubrectDimensions.Width = view.GetViewExtent().width();
evalParams.InRenderSubrectDimensions.Height = view.GetViewExtent().height();
- NVSDK_NGX_Result result = NGX_VULKAN_EVALUATE_DLSS_EXT(vkCmdBuf, m_DlssHandle, m_Parameters, &evalParams);
+ NVSDK_NGX_Result result = NGX_VULKAN_EVALUATE_DLSS_EXT(vkCmdBuf, m_dlssHandle, m_parameters, &evalParams);
commandList->clearState();
@@ -208,16 +208,16 @@ class DLSS_VK : public DLSS
~DLSS_VK() override
{
- if (m_DlssHandle)
+ if (m_dlssHandle)
{
- NVSDK_NGX_VULKAN_ReleaseFeature(m_DlssHandle);
- m_DlssHandle = nullptr;
+ NVSDK_NGX_VULKAN_ReleaseFeature(m_dlssHandle);
+ m_dlssHandle = nullptr;
}
- if (m_Parameters)
+ if (m_parameters)
{
- NVSDK_NGX_VULKAN_DestroyParameters(m_Parameters);
- m_Parameters = nullptr;
+ NVSDK_NGX_VULKAN_DestroyParameters(m_parameters);
+ m_parameters = nullptr;
}
NVSDK_NGX_VULKAN_Shutdown();
diff --git a/src/DLSS.cpp b/Samples/FullSample/Source/DLSS.cpp
similarity index 63%
rename from src/DLSS.cpp
rename to Samples/FullSample/Source/DLSS.cpp
index 1b081cc..5580189 100644
--- a/src/DLSS.cpp
+++ b/Samples/FullSample/Source/DLSS.cpp
@@ -16,10 +16,18 @@
using namespace donut;
-DLSS::DLSS(nvrhi::IDevice* device, donut::engine::ShaderFactory& shaderFactory)
- : m_Device(device)
+DLSS::DLSS(nvrhi::IDevice* device, donut::engine::ShaderFactory& shaderFactory) :
+ m_featureSupported(false),
+ m_isAvailable(false),
+ m_dlssHandle(nullptr),
+ m_parameters(nullptr),
+ m_inputWidth(0),
+ m_inputHeight(0),
+ m_outputWidth(0),
+ m_outputHeight(0),
+ m_device(device)
{
- m_ExposureShader = shaderFactory.CreateShader("app/DlssExposure.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
+ m_exposureShader = shaderFactory.CreateShader("app/DlssExposure.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
auto layoutDesc = nvrhi::BindingLayoutDesc()
.setVisibility(nvrhi::ShaderType::Compute)
@@ -27,13 +35,13 @@ DLSS::DLSS(nvrhi::IDevice* device, donut::engine::ShaderFactory& shaderFactory)
.addItem(nvrhi::BindingLayoutItem::Texture_UAV(0))
.addItem(nvrhi::BindingLayoutItem::PushConstants(0, sizeof(float)));
- m_ExposureBindingLayout = device->createBindingLayout(layoutDesc);
+ m_exposureBindingLayout = device->createBindingLayout(layoutDesc);
auto pipelineDesc = nvrhi::ComputePipelineDesc()
- .addBindingLayout(m_ExposureBindingLayout)
- .setComputeShader(m_ExposureShader);
+ .addBindingLayout(m_exposureBindingLayout)
+ .setComputeShader(m_exposureShader);
- m_ExposurePipeline = device->createComputePipeline(pipelineDesc);
+ m_exposurePipeline = device->createComputePipeline(pipelineDesc);
auto textureDesc = nvrhi::TextureDesc()
.setWidth(1)
@@ -45,32 +53,42 @@ DLSS::DLSS(nvrhi::IDevice* device, donut::engine::ShaderFactory& shaderFactory)
.setDimension(nvrhi::TextureDimension::Texture2D)
.setIsUAV(true);
- m_ExposureTexture = device->createTexture(textureDesc);
+ m_exposureTexture = device->createTexture(textureDesc);
- m_FeatureCommandList = device->createCommandList();
+ m_featureCommandList = device->createCommandList();
+}
+
+bool DLSS::IsSupported() const
+{
+ return m_featureSupported;
+}
+
+bool DLSS::IsAvailable() const
+{
+ return m_featureSupported && m_isAvailable;
}
void DLSS::ComputeExposure(nvrhi::ICommandList* commandList, nvrhi::IBuffer* toneMapperExposureBuffer, float exposureScale)
{
- if (m_ExposureSourceBuffer != toneMapperExposureBuffer)
+ if (m_exposureSourceBuffer != toneMapperExposureBuffer)
{
- m_ExposureSourceBuffer = nullptr;
- m_ExposureBindingSet = nullptr;
+ m_exposureSourceBuffer = nullptr;
+ m_exposureBindingSet = nullptr;
}
- if (!m_ExposureBindingSet)
+ if (!m_exposureBindingSet)
{
auto setDesc = nvrhi::BindingSetDesc()
.addItem(nvrhi::BindingSetItem::TypedBuffer_SRV(0, toneMapperExposureBuffer))
- .addItem(nvrhi::BindingSetItem::Texture_UAV(0, m_ExposureTexture))
+ .addItem(nvrhi::BindingSetItem::Texture_UAV(0, m_exposureTexture))
.addItem(nvrhi::BindingSetItem::PushConstants(0, sizeof(float)));
- m_ExposureBindingSet = m_Device->createBindingSet(setDesc, m_ExposureBindingLayout);
+ m_exposureBindingSet = m_device->createBindingSet(setDesc, m_exposureBindingLayout);
}
auto state = nvrhi::ComputeState()
- .setPipeline(m_ExposurePipeline)
- .addBindingSet(m_ExposureBindingSet);
+ .setPipeline(m_exposurePipeline)
+ .addBindingSet(m_exposureBindingSet);
commandList->setComputeState(state);
commandList->setPushConstants(&exposureScale, sizeof(float));
diff --git a/src/DLSS.h b/Samples/FullSample/Source/DLSS.h
similarity index 70%
rename from src/DLSS.h
rename to Samples/FullSample/Source/DLSS.h
index 1d4115e..f706de2 100644
--- a/src/DLSS.h
+++ b/Samples/FullSample/Source/DLSS.h
@@ -28,38 +28,11 @@ struct NVSDK_NGX_Parameter;
class DLSS
{
-protected:
- bool m_FeatureSupported = false;
- bool m_IsAvailable = false;
-
- NVSDK_NGX_Handle* m_DlssHandle = nullptr;
- NVSDK_NGX_Parameter* m_Parameters = nullptr;
-
- // Use the AppID from the DLSS sample app until we get a separate one for RTXDI... wait, is it random?
- static const uint32_t c_ApplicationID = 231313132;
-
- uint32_t m_InputWidth = 0;
- uint32_t m_InputHeight = 0;
- uint32_t m_OutputWidth = 0;
- uint32_t m_OutputHeight = 0;
-
- nvrhi::DeviceHandle m_Device;
- nvrhi::ShaderHandle m_ExposureShader;
- nvrhi::ComputePipelineHandle m_ExposurePipeline;
- nvrhi::TextureHandle m_ExposureTexture;
- nvrhi::BufferHandle m_ExposureSourceBuffer;
- nvrhi::BindingLayoutHandle m_ExposureBindingLayout;
- nvrhi::BindingSetHandle m_ExposureBindingSet;
- nvrhi::CommandListHandle m_FeatureCommandList;
-
- void ComputeExposure(nvrhi::ICommandList* commandList, nvrhi::IBuffer* toneMapperExposureBuffer, float exposureScale);
-
public:
-
DLSS(nvrhi::IDevice* device, donut::engine::ShaderFactory& shaderFactory);
- [[nodiscard]] bool IsSupported() const { return m_FeatureSupported; }
- [[nodiscard]] bool IsAvailable() const { return m_FeatureSupported && m_IsAvailable; }
+ [[nodiscard]] bool IsSupported() const;
+ [[nodiscard]] bool IsAvailable() const;
virtual void SetRenderSize(
uint32_t inputWidth, uint32_t inputHeight,
@@ -85,6 +58,32 @@ class DLSS
static std::unique_ptr CreateVK(nvrhi::IDevice* device, donut::engine::ShaderFactory& shaderFactory);
#endif
static void GetRequiredVulkanExtensions(std::vector& instanceExtensions, std::vector& deviceExtensions);
+
+protected:
+ bool m_featureSupported;
+ bool m_isAvailable;
+
+ NVSDK_NGX_Handle* m_dlssHandle;
+ NVSDK_NGX_Parameter* m_parameters;
+
+ // Use the AppID from the DLSS sample app until we get a separate one for RTXDI... wait, is it random?
+ static const uint32_t c_applicationID = 231313132;
+
+ uint32_t m_inputWidth;
+ uint32_t m_inputHeight;
+ uint32_t m_outputWidth;
+ uint32_t m_outputHeight;
+
+ nvrhi::DeviceHandle m_device;
+ nvrhi::ShaderHandle m_exposureShader;
+ nvrhi::ComputePipelineHandle m_exposurePipeline;
+ nvrhi::TextureHandle m_exposureTexture;
+ nvrhi::BufferHandle m_exposureSourceBuffer;
+ nvrhi::BindingLayoutHandle m_exposureBindingLayout;
+ nvrhi::BindingSetHandle m_exposureBindingSet;
+ nvrhi::CommandListHandle m_featureCommandList;
+
+ void ComputeExposure(nvrhi::ICommandList* commandList, nvrhi::IBuffer* toneMapperExposureBuffer, float exposureScale);
};
#endif
diff --git a/src/DebugViz/DebugVizPasses.cpp b/Samples/FullSample/Source/DebugViz/DebugVizPasses.cpp
similarity index 64%
rename from src/DebugViz/DebugVizPasses.cpp
rename to Samples/FullSample/Source/DebugViz/DebugVizPasses.cpp
index a9ccaca..1b18643 100644
--- a/src/DebugViz/DebugVizPasses.cpp
+++ b/Samples/FullSample/Source/DebugViz/DebugVizPasses.cpp
@@ -17,54 +17,54 @@ DebugVizPasses::DebugVizPasses(
std::shared_ptr shaderFactory,
std::shared_ptr scene,
nvrhi::IBindingLayout* bindlessLayout) :
- m_GBufferNormalsViz(std::make_unique(device, shaderFactory, scene, bindlessLayout)),
- m_GBufferGeoNormalsViz(std::make_unique(device, shaderFactory, scene, bindlessLayout)),
- m_GBufferDiffuseAlbedoViz(std::make_unique(device, shaderFactory, scene, bindlessLayout)),
- m_GBufferSpecularRoughnessViz(std::make_unique(device, shaderFactory, scene, bindlessLayout))
+ m_gBufferNormalsViz(std::make_unique(device, shaderFactory, scene, bindlessLayout)),
+ m_gBufferGeoNormalsViz(std::make_unique(device, shaderFactory, scene, bindlessLayout)),
+ m_gBufferDiffuseAlbedoViz(std::make_unique(device, shaderFactory, scene, bindlessLayout)),
+ m_gBufferSpecularRoughnessViz(std::make_unique(device, shaderFactory, scene, bindlessLayout))
{
}
void DebugVizPasses::CreatePipelines()
{
- m_GBufferNormalsViz->CreatePipeline("app/DebugViz/NDirOctUNorm32Viz.hlsl");
- m_GBufferGeoNormalsViz->CreatePipeline("app/DebugViz/NDirOctUNorm32Viz.hlsl");
- m_GBufferDiffuseAlbedoViz->CreatePipeline("app/DebugViz/PackedR11G11B10UFloatViz.hlsl");
- m_GBufferSpecularRoughnessViz->CreatePipeline("app/DebugViz/PackedR8G8B8A8GammaUFloatViz.hlsl");
+ m_gBufferNormalsViz->CreatePipeline("app/DebugViz/NDirOctUNorm32Viz.hlsl");
+ m_gBufferGeoNormalsViz->CreatePipeline("app/DebugViz/NDirOctUNorm32Viz.hlsl");
+ m_gBufferDiffuseAlbedoViz->CreatePipeline("app/DebugViz/PackedR11G11B10UFloatViz.hlsl");
+ m_gBufferSpecularRoughnessViz->CreatePipeline("app/DebugViz/PackedR8G8B8A8GammaUFloatViz.hlsl");
}
void DebugVizPasses::CreateBindingSets(RenderTargets& renderTargets, nvrhi::TextureHandle dst)
{
- m_GBufferNormalsViz->CreateBindingSet(renderTargets.GBufferNormals, renderTargets.PrevGBufferNormals, renderTargets.DebugColor);
- m_GBufferGeoNormalsViz->CreateBindingSet(renderTargets.GBufferGeoNormals, renderTargets.PrevGBufferGeoNormals, renderTargets.DebugColor);
- m_GBufferDiffuseAlbedoViz->CreateBindingSet(renderTargets.GBufferDiffuseAlbedo, renderTargets.PrevGBufferDiffuseAlbedo, renderTargets.DebugColor);
- m_GBufferSpecularRoughnessViz->CreateBindingSet(renderTargets.GBufferSpecularRough, renderTargets.PrevGBufferSpecularRough, renderTargets.DebugColor);
+ m_gBufferNormalsViz->CreateBindingSet(renderTargets.GBufferNormals, renderTargets.PrevGBufferNormals, renderTargets.DebugColor);
+ m_gBufferGeoNormalsViz->CreateBindingSet(renderTargets.GBufferGeoNormals, renderTargets.PrevGBufferGeoNormals, renderTargets.DebugColor);
+ m_gBufferDiffuseAlbedoViz->CreateBindingSet(renderTargets.GBufferDiffuseAlbedo, renderTargets.PrevGBufferDiffuseAlbedo, renderTargets.DebugColor);
+ m_gBufferSpecularRoughnessViz->CreateBindingSet(renderTargets.GBufferSpecularRough, renderTargets.PrevGBufferSpecularRough, renderTargets.DebugColor);
}
void DebugVizPasses::RenderUnpackedNormals(nvrhi::ICommandList* commandList, const donut::engine::IView& view)
{
- m_GBufferNormalsViz->Render(commandList, view);
+ m_gBufferNormalsViz->Render(commandList, view);
}
void DebugVizPasses::RenderUnpackedGeoNormals(nvrhi::ICommandList* commandList, const donut::engine::IView& view)
{
- m_GBufferGeoNormalsViz->Render(commandList, view);
+ m_gBufferGeoNormalsViz->Render(commandList, view);
}
void DebugVizPasses::RenderUnpackedDiffuseAlbeo(nvrhi::ICommandList* commandList, const donut::engine::IView& view)
{
- m_GBufferDiffuseAlbedoViz->Render(commandList, view);
+ m_gBufferDiffuseAlbedoViz->Render(commandList, view);
}
void DebugVizPasses::RenderUnpackedSpecularRoughness(nvrhi::ICommandList* commandList, const donut::engine::IView& view)
{
- m_GBufferSpecularRoughnessViz->Render(commandList, view);
+ m_gBufferSpecularRoughnessViz->Render(commandList, view);
}
void DebugVizPasses::NextFrame()
{
- m_GBufferNormalsViz->NextFrame();
- m_GBufferGeoNormalsViz->NextFrame();
- m_GBufferDiffuseAlbedoViz->NextFrame();
- m_GBufferSpecularRoughnessViz->NextFrame();
+ m_gBufferNormalsViz->NextFrame();
+ m_gBufferGeoNormalsViz->NextFrame();
+ m_gBufferDiffuseAlbedoViz->NextFrame();
+ m_gBufferSpecularRoughnessViz->NextFrame();
}
\ No newline at end of file
diff --git a/src/DebugViz/DebugVizPasses.h b/Samples/FullSample/Source/DebugViz/DebugVizPasses.h
similarity index 85%
rename from src/DebugViz/DebugVizPasses.h
rename to Samples/FullSample/Source/DebugViz/DebugVizPasses.h
index 9f54c9b..255d948 100644
--- a/src/DebugViz/DebugVizPasses.h
+++ b/Samples/FullSample/Source/DebugViz/DebugVizPasses.h
@@ -35,9 +35,8 @@ class DebugVizPasses
void NextFrame();
private:
- std::unique_ptr m_GBufferNormalsViz;
- std::unique_ptr m_GBufferGeoNormalsViz;
- std::unique_ptr m_GBufferDiffuseAlbedoViz;
- std::unique_ptr m_GBufferSpecularRoughnessViz;
+ std::unique_ptr m_gBufferNormalsViz;
+ std::unique_ptr m_gBufferGeoNormalsViz;
+ std::unique_ptr m_gBufferDiffuseAlbedoViz;
+ std::unique_ptr m_gBufferSpecularRoughnessViz;
};
-
diff --git a/src/DebugViz/PackedDataVizPass.cpp b/Samples/FullSample/Source/DebugViz/PackedDataVizPass.cpp
similarity index 75%
rename from src/DebugViz/PackedDataVizPass.cpp
rename to Samples/FullSample/Source/DebugViz/PackedDataVizPass.cpp
index 003c715..2276b85 100644
--- a/src/DebugViz/PackedDataVizPass.cpp
+++ b/Samples/FullSample/Source/DebugViz/PackedDataVizPass.cpp
@@ -31,10 +31,10 @@ PackedDataVizPass::PackedDataVizPass(
std::shared_ptr shaderFactory,
std::shared_ptr scene,
nvrhi::IBindingLayout* bindlessLayout) :
- m_Device(device)
- , m_BindlessLayout(bindlessLayout)
- , m_ShaderFactory(std::move(shaderFactory))
- , m_Scene(std::move(scene))
+ m_device(device)
+ , m_bindlessLayout(bindlessLayout)
+ , m_shaderFactory(std::move(shaderFactory))
+ , m_scene(std::move(scene))
{
nvrhi::BindingLayoutDesc bindingLayoutDesc;
bindingLayoutDesc.visibility = nvrhi::ShaderType::Compute;
@@ -43,21 +43,21 @@ PackedDataVizPass::PackedDataVizPass(
nvrhi::BindingLayoutItem::Texture_UAV(0),
};
- m_BindingLayout = m_Device->createBindingLayout(bindingLayoutDesc);
+ m_bindingLayout = m_device->createBindingLayout(bindingLayoutDesc);
}
void PackedDataVizPass::CreatePipeline(const std::string& shaderPath)
{
std::string debugMsg = "Initializing PackedDataVizPass with " + shaderPath + "...";
donut::log::debug(debugMsg.c_str());
- gpuPerfMarker = "Packed Data Viz Pass:" + shaderPath;
+ m_gpuPerfMarker = "Packed Data Viz Pass:" + shaderPath;
- m_ComputeShader = m_ShaderFactory->CreateShader(shaderPath.c_str(), "main", nullptr, nvrhi::ShaderType::Compute);
+ m_computeShader = m_shaderFactory->CreateShader(shaderPath.c_str(), "main", nullptr, nvrhi::ShaderType::Compute);
nvrhi::ComputePipelineDesc pipelineDesc;
- pipelineDesc.bindingLayouts = { m_BindingLayout, m_BindlessLayout };
- pipelineDesc.CS = m_ComputeShader;
- m_ComputePipeline = m_Device->createComputePipeline(pipelineDesc);
+ pipelineDesc.bindingLayouts = { m_bindingLayout, m_bindlessLayout };
+ pipelineDesc.CS = m_computeShader;
+ m_computePipeline = m_device->createComputePipeline(pipelineDesc);
}
void PackedDataVizPass::CreateBindingSet(nvrhi::TextureHandle src, nvrhi::TextureHandle prevSrc, nvrhi::TextureHandle dst)
@@ -70,22 +70,22 @@ void PackedDataVizPass::CreateBindingSet(nvrhi::TextureHandle src, nvrhi::Textur
nvrhi::BindingSetItem::Texture_UAV(0, dst)
};
- m_BindingSetEven = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ m_bindingSetEven = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
bindingSetDesc.bindings[0].resourceHandle = prevSrc;
- m_BindingSetOdd = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ m_bindingSetOdd = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
}
void PackedDataVizPass::Render(
nvrhi::ICommandList* commandList,
const donut::engine::IView& view)
{
- commandList->beginMarker(gpuPerfMarker.c_str());
+ commandList->beginMarker(m_gpuPerfMarker.c_str());
nvrhi::ComputeState state;
- state.bindings = { m_BindingSetEven, m_Scene->GetDescriptorTable() };
- state.pipeline = m_ComputePipeline;
+ state.bindings = { m_bindingSetEven, m_scene->GetDescriptorTable() };
+ state.pipeline = m_computePipeline;
commandList->setComputeState(state);
commandList->dispatch(
@@ -98,5 +98,5 @@ void PackedDataVizPass::Render(
void PackedDataVizPass::NextFrame()
{
- std::swap(m_BindingSetEven, m_BindingSetOdd);
+ std::swap(m_bindingSetEven, m_bindingSetOdd);
}
\ No newline at end of file
diff --git a/src/DebugViz/PackedDataVizPass.h b/Samples/FullSample/Source/DebugViz/PackedDataVizPass.h
similarity index 73%
rename from src/DebugViz/PackedDataVizPass.h
rename to Samples/FullSample/Source/DebugViz/PackedDataVizPass.h
index 2c528a2..c47b7b6 100644
--- a/src/DebugViz/PackedDataVizPass.h
+++ b/Samples/FullSample/Source/DebugViz/PackedDataVizPass.h
@@ -27,22 +27,6 @@ struct UIData;
class PackedDataVizPass
{
-private:
- nvrhi::DeviceHandle m_Device;
-
- nvrhi::ShaderHandle m_ComputeShader;
- nvrhi::ComputePipelineHandle m_ComputePipeline;
- nvrhi::BindingLayoutHandle m_BindingLayout;
- nvrhi::BindingLayoutHandle m_BindlessLayout;
- nvrhi::BindingSetHandle m_BindingSetEven;
- nvrhi::BindingSetHandle m_BindingSetOdd;
-
- nvrhi::BufferHandle m_ConstantBuffer;
-
- std::shared_ptr m_ShaderFactory;
- std::shared_ptr m_Scene;
- std::string gpuPerfMarker;
-
public:
PackedDataVizPass(
nvrhi::IDevice* device,
@@ -59,4 +43,20 @@ class PackedDataVizPass
const donut::engine::IView& view);
void NextFrame();
+
+private:
+ nvrhi::DeviceHandle m_device;
+
+ nvrhi::ShaderHandle m_computeShader;
+ nvrhi::ComputePipelineHandle m_computePipeline;
+ nvrhi::BindingLayoutHandle m_bindingLayout;
+ nvrhi::BindingLayoutHandle m_bindlessLayout;
+ nvrhi::BindingSetHandle m_bindingSetEven;
+ nvrhi::BindingSetHandle m_bindingSetOdd;
+
+ nvrhi::BufferHandle m_constantBuffer;
+
+ std::shared_ptr m_shaderFactory;
+ std::shared_ptr m_scene;
+ std::string m_gpuPerfMarker;
};
diff --git a/src/NrdIntegration.cpp b/Samples/FullSample/Source/NrdIntegration.cpp
similarity index 91%
rename from src/NrdIntegration.cpp
rename to Samples/FullSample/Source/NrdIntegration.cpp
index 340dea3..96d9529 100644
--- a/src/NrdIntegration.cpp
+++ b/Samples/FullSample/Source/NrdIntegration.cpp
@@ -92,12 +92,12 @@ static nvrhi::Format GetNvrhiFormat(nrd::Format format)
}
NrdIntegration::NrdIntegration(nvrhi::IDevice* device, nrd::Denoiser denoiser)
- : m_Device(device)
- , m_Initialized(false)
- , m_Instance(nullptr)
- , m_Denoiser(denoiser)
- , m_BindingCache(device)
- , m_PixelOffsetPrev(0.0f, 0.0f)
+ : m_device(device)
+ , m_initialized(false)
+ , m_instance(nullptr)
+ , m_denoiser(denoiser)
+ , m_bindingCache(device)
+ , m_pixelOffsetPrev(0.0f, 0.0f)
{
}
@@ -106,7 +106,7 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
const nrd::LibraryDesc& libraryDesc = nrd::GetLibraryDesc();
const nrd::DenoiserDesc denoisers[] = {
- { ID, m_Denoiser }
+ { ID, m_denoiser }
};
nrd::InstanceCreationDesc instanceCreationDesc;
@@ -116,13 +116,13 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
instanceCreationDesc.denoisersNum = dim(denoisers);
instanceCreationDesc.denoisers = denoisers;
- nrd::Result res = nrd::CreateInstance(instanceCreationDesc, m_Instance);
+ nrd::Result res = nrd::CreateInstance(instanceCreationDesc, m_instance);
if (res != nrd::Result::SUCCESS)
return false;
- const nrd::InstanceDesc& instanceDesc = nrd::GetInstanceDesc(*m_Instance);
- const bool isVulkan = m_Device->getGraphicsAPI() == nvrhi::GraphicsAPI::VULKAN;
+ const nrd::InstanceDesc& instanceDesc = nrd::GetInstanceDesc(*m_instance);
+ const bool isVulkan = m_device->getGraphicsAPI() == nvrhi::GraphicsAPI::VULKAN;
const nvrhi::BufferDesc constantBufferDesc = nvrhi::utils::CreateVolatileConstantBufferDesc(
@@ -130,7 +130,7 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
"NrdConstantBuffer",
instanceDesc.descriptorPoolDesc.constantBuffersMaxNum * 4);
- m_ConstantBuffer = m_Device->createBuffer(constantBufferDesc);
+ m_constantBuffer = m_device->createBuffer(constantBufferDesc);
for (uint32_t samplerIndex = 0; samplerIndex < instanceDesc.samplersNum; samplerIndex++)
@@ -159,7 +159,7 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
.setAllAddressModes(addressMode)
.setAllFilters(filter);
- const nvrhi::SamplerHandle sampler = m_Device->createSampler(samplerDesc);
+ const nvrhi::SamplerHandle sampler = m_device->createSampler(samplerDesc);
if (!sampler)
{
@@ -167,7 +167,7 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
return false;
}
- m_Samplers.push_back(sampler);
+ m_samplers.push_back(sampler);
}
nvrhi::VulkanBindingOffsets bindingOffsets;
@@ -182,7 +182,7 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
const nrd::ComputeShaderDesc& nrdComputeShader = isVulkan ? nrdPipelineDesc.computeShaderSPIRV : nrdPipelineDesc.computeShaderDXIL;
NrdPipeline pipeline;
- pipeline.Shader = m_Device->createShader(nvrhi::ShaderDesc(nvrhi::ShaderType::Compute), nrdComputeShader.bytecode, nrdComputeShader.size);
+ pipeline.Shader = m_device->createShader(nvrhi::ShaderDesc(nvrhi::ShaderType::Compute), nrdComputeShader.bytecode, nrdComputeShader.size);
if (!pipeline.Shader)
{
@@ -235,7 +235,7 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
}
}
- pipeline.BindingLayout = m_Device->createBindingLayout(layoutDesc);
+ pipeline.BindingLayout = m_device->createBindingLayout(layoutDesc);
if (!pipeline.BindingLayout)
{
@@ -246,7 +246,7 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
nvrhi::ComputePipelineDesc pipelineDesc;
pipelineDesc.bindingLayouts = { pipeline.BindingLayout };
pipelineDesc.CS = pipeline.Shader;
- pipeline.Pipeline = m_Device->createComputePipeline(pipelineDesc);
+ pipeline.Pipeline = m_device->createComputePipeline(pipelineDesc);
if (!pipeline.Pipeline)
{
@@ -254,7 +254,7 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
return false;
}
- m_Pipelines.push_back(pipeline);
+ m_pipelines.push_back(pipeline);
}
@@ -290,7 +290,7 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
textureDesc.isUAV = true;
textureDesc.debugName = ss.str();
- const nvrhi::TextureHandle texture = m_Device->createTexture(textureDesc);
+ const nvrhi::TextureHandle texture = m_device->createTexture(textureDesc);
if (!texture)
{
@@ -299,18 +299,18 @@ bool NrdIntegration::Initialize(uint32_t width, uint32_t height)
}
if (isPermanent)
- m_PermanentTextures.push_back(texture);
+ m_permanentTextures.push_back(texture);
else
- m_TransientTextures.push_back(texture);
+ m_transientTextures.push_back(texture);
}
- m_Initialized = true;
+ m_initialized = true;
return true;
}
bool NrdIntegration::IsAvailable() const
{
- return m_Initialized;
+ return m_initialized;
}
static inline void MatrixToNrd(float* dest, const dm::float4x4& m)
@@ -331,7 +331,7 @@ void NrdIntegration::RunDenoiserPasses(
{
if (denoiserSettings)
{
- nrd::SetDenoiserSettings(*m_Instance, ID, denoiserSettings);
+ nrd::SetDenoiserSettings(*m_instance, ID, denoiserSettings);
}
nrd::CommonSettings commonSettings = {};
@@ -349,9 +349,9 @@ void NrdIntegration::RunDenoiserPasses(
commonSettings.cameraJitter[0] = pixelOffset.x;
commonSettings.cameraJitter[1] = pixelOffset.y;
- commonSettings.cameraJitterPrev[0] = m_PixelOffsetPrev.x;
- commonSettings.cameraJitterPrev[1] = m_PixelOffsetPrev.y;
- m_PixelOffsetPrev = pixelOffset;
+ commonSettings.cameraJitterPrev[0] = m_pixelOffsetPrev.x;
+ commonSettings.cameraJitterPrev[1] = m_pixelOffsetPrev.y;
+ m_pixelOffsetPrev = pixelOffset;
commonSettings.resourceSize[0] = motionVectorDesc.width;
commonSettings.resourceSize[1] = motionVectorDesc.height;
@@ -382,13 +382,13 @@ void NrdIntegration::RunDenoiserPasses(
commonSettings.isBaseColorMetalnessAvailable = false;
commonSettings.enableValidation = false;
- nrd::SetCommonSettings(*m_Instance, commonSettings);
+ nrd::SetCommonSettings(*m_instance, commonSettings);
const nrd::DispatchDesc* dispatchDescs = nullptr;
uint32_t dispatchDescNum = 0;
- nrd::GetComputeDispatches(*m_Instance, &ID, 1, dispatchDescs, dispatchDescNum);
+ nrd::GetComputeDispatches(*m_instance, &ID, 1, dispatchDescs, dispatchDescNum);
- const nrd::InstanceDesc& instanceDesc = nrd::GetInstanceDesc(*m_Instance);
+ const nrd::InstanceDesc& instanceDesc = nrd::GetInstanceDesc(*m_instance);
for (uint32_t dispatchIndex = 0; dispatchIndex < dispatchDescNum; dispatchIndex++)
{
@@ -399,16 +399,16 @@ void NrdIntegration::RunDenoiserPasses(
commandList->beginMarker(dispatchDesc.name);
}
- assert(m_ConstantBuffer);
- commandList->writeBuffer(m_ConstantBuffer, dispatchDesc.constantBufferData, dispatchDesc.constantBufferDataSize);
+ assert(m_constantBuffer);
+ commandList->writeBuffer(m_constantBuffer, dispatchDesc.constantBufferData, dispatchDesc.constantBufferDataSize);
nvrhi::BindingSetDesc setDesc;
- setDesc.bindings.push_back(nvrhi::BindingSetItem::ConstantBuffer(instanceDesc.constantBufferRegisterIndex, m_ConstantBuffer));
+ setDesc.bindings.push_back(nvrhi::BindingSetItem::ConstantBuffer(instanceDesc.constantBufferRegisterIndex, m_constantBuffer));
for (uint32_t samplerIndex = 0; samplerIndex < instanceDesc.samplersNum; samplerIndex++)
{
- assert(m_Samplers[samplerIndex]);
- setDesc.bindings.push_back(nvrhi::BindingSetItem::Sampler(instanceDesc.samplersBaseRegisterIndex + samplerIndex, m_Samplers[samplerIndex]));
+ assert(m_samplers[samplerIndex]);
+ setDesc.bindings.push_back(nvrhi::BindingSetItem::Sampler(instanceDesc.samplersBaseRegisterIndex + samplerIndex, m_samplers[samplerIndex]));
}
const nrd::PipelineDesc& nrdPipelineDesc = instanceDesc.pipelines[dispatchDesc.pipelineIndex];
@@ -456,10 +456,10 @@ void NrdIntegration::RunDenoiserPasses(
texture = renderTargets.DenoisedSpecularLighting;
break;
case nrd::ResourceType::TRANSIENT_POOL:
- texture = m_TransientTextures[resource.indexInPool];
+ texture = m_transientTextures[resource.indexInPool];
break;
case nrd::ResourceType::PERMANENT_POOL:
- texture = m_PermanentTextures[resource.indexInPool];
+ texture = m_permanentTextures[resource.indexInPool];
break;
default:
assert(!"Unavailable resource type");
@@ -488,9 +488,9 @@ void NrdIntegration::RunDenoiserPasses(
assert(resourceIndex == dispatchDesc.resourcesNum);
- const NrdPipeline& pipeline = m_Pipelines[dispatchDesc.pipelineIndex];
+ const NrdPipeline& pipeline = m_pipelines[dispatchDesc.pipelineIndex];
- nvrhi::BindingSetHandle bindingSet = m_BindingCache.GetOrCreateBindingSet(setDesc, pipeline.BindingLayout);
+ nvrhi::BindingSetHandle bindingSet = m_bindingCache.GetOrCreateBindingSet(setDesc, pipeline.BindingLayout);
nvrhi::ComputeState state;
state.bindings = { bindingSet };
@@ -506,4 +506,9 @@ void NrdIntegration::RunDenoiserPasses(
}
}
+const nrd::Denoiser NrdIntegration::GetDenoiser() const
+{
+ return m_denoiser;
+}
+
#endif
diff --git a/src/NrdIntegration.h b/Samples/FullSample/Source/NrdIntegration.h
similarity index 74%
rename from src/NrdIntegration.h
rename to Samples/FullSample/Source/NrdIntegration.h
index 9d20b2f..3a934ab 100644
--- a/src/NrdIntegration.h
+++ b/Samples/FullSample/Source/NrdIntegration.h
@@ -27,27 +27,6 @@ namespace donut::engine
class NrdIntegration
{
-private:
- nvrhi::DeviceHandle m_Device;
- bool m_Initialized;
- nrd::Instance* m_Instance;
- nrd::Denoiser m_Denoiser;
-
- struct NrdPipeline
- {
- nvrhi::ShaderHandle Shader;
- nvrhi::BindingLayoutHandle BindingLayout;
- nvrhi::ComputePipelineHandle Pipeline;
- };
-
- nvrhi::BufferHandle m_ConstantBuffer;
- std::vector m_Pipelines;
- std::vector m_Samplers;
- std::vector m_PermanentTextures;
- std::vector m_TransientTextures;
- donut::engine::BindingCache m_BindingCache;
- dm::float2 m_PixelOffsetPrev;
-
public:
NrdIntegration(nvrhi::IDevice* device, nrd::Denoiser denoiser);
@@ -64,7 +43,28 @@ class NrdIntegration
const void* denoiserSettings,
float debug);
- const nrd::Denoiser GetDenoiser() const { return m_Denoiser; }
+ const nrd::Denoiser GetDenoiser() const;
+
+private:
+ nvrhi::DeviceHandle m_device;
+ bool m_initialized;
+ nrd::Instance* m_instance;
+ nrd::Denoiser m_denoiser;
+
+ struct NrdPipeline
+ {
+ nvrhi::ShaderHandle Shader;
+ nvrhi::BindingLayoutHandle BindingLayout;
+ nvrhi::ComputePipelineHandle Pipeline;
+ };
+
+ nvrhi::BufferHandle m_constantBuffer;
+ std::vector m_pipelines;
+ std::vector m_samplers;
+ std::vector m_permanentTextures;
+ std::vector m_transientTextures;
+ donut::engine::BindingCache m_bindingCache;
+ dm::float2 m_pixelOffsetPrev;
};
#endif
diff --git a/src/Profiler.cpp b/Samples/FullSample/Source/Profiler.cpp
similarity index 75%
rename from src/Profiler.cpp
rename to Samples/FullSample/Source/Profiler.cpp
index af8d700..7e5551d 100644
--- a/src/Profiler.cpp
+++ b/Samples/FullSample/Source/Profiler.cpp
@@ -44,11 +44,11 @@ static const char* g_SectionNames[ProfilerSection::Count] = {
};
Profiler::Profiler(donut::app::DeviceManager& deviceManager)
- : m_DeviceManager(deviceManager)
- , m_Device(deviceManager.GetDevice())
+ : m_deviceManager(deviceManager)
+ , m_device(deviceManager.GetDevice())
{
- for (auto& query : m_TimerQueries)
- query = m_Device->createTimerQuery();
+ for (auto& query : m_timerQueries)
+ query = m_device->createTimerQuery();
nvrhi::BufferDesc rayCountBufferDesc;
rayCountBufferDesc.byteSize = sizeof(uint32_t) * 2 * ProfilerSection::Count;
@@ -58,7 +58,7 @@ Profiler::Profiler(donut::app::DeviceManager& deviceManager)
rayCountBufferDesc.debugName = "RayCount";
rayCountBufferDesc.initialState = nvrhi::ResourceStates::UnorderedAccess;
rayCountBufferDesc.keepInitialState = true;
- m_RayCountBuffer = m_Device->createBuffer(rayCountBufferDesc);
+ m_rayCountBuffer = m_device->createBuffer(rayCountBufferDesc);
rayCountBufferDesc.canHaveUAVs = false;
rayCountBufferDesc.cpuAccess = nvrhi::CpuAccessMode::Read;
@@ -66,36 +66,41 @@ Profiler::Profiler(donut::app::DeviceManager& deviceManager)
rayCountBufferDesc.debugName = "RayCountReadback";
for (size_t bank = 0; bank < 2; bank++)
{
- m_RayCountReadback[bank] = m_Device->createBuffer(rayCountBufferDesc);
+ m_rayCountReadback[bank] = m_device->createBuffer(rayCountBufferDesc);
}
}
+bool Profiler::IsEnabled() const
+{
+ return m_enabled;
+}
+
void Profiler::EnableProfiler(bool enable)
{
- m_Enabled = enable;
+ m_enabled = enable;
}
void Profiler::EnableAccumulation(bool enable)
{
- m_IsAccumulating = enable;
+ m_isAccumulating = enable;
}
void Profiler::ResetAccumulation()
{
- m_AccumulatedFrames = 0;
- m_TimerValues.fill(0.0);
- m_RayCounts.fill(0);
- m_HitCounts.fill(0);
+ m_accumulatedFrames = 0;
+ m_timerValues.fill(0.0);
+ m_rayCounts.fill(0);
+ m_hitCounts.fill(0);
}
void Profiler::ResolvePreviousFrame()
{
- m_ActiveBank = !m_ActiveBank;
+ m_activeBank = !m_activeBank;
- if (!m_Enabled)
+ if (!m_enabled)
return;
- const uint32_t* rayCountData = static_cast(m_Device->mapBuffer(m_RayCountReadback[m_ActiveBank], nvrhi::CpuAccessMode::Read));
+ const uint32_t* rayCountData = static_cast(m_device->mapBuffer(m_rayCountReadback[m_activeBank], nvrhi::CpuAccessMode::Read));
for (uint32_t section = 0; section < ProfilerSection::MaterialReadback; section++)
{
@@ -103,11 +108,11 @@ void Profiler::ResolvePreviousFrame()
uint32_t rayCount = 0;
uint32_t hitCount = 0;
- uint32_t timerIndex = section + m_ActiveBank * ProfilerSection::Count;
+ uint32_t timerIndex = section + m_activeBank * ProfilerSection::Count;
- if (m_TimersUsed[timerIndex])
+ if (m_timersUsed[timerIndex])
{
- time = double(m_Device->getTimerQueryTime(m_TimerQueries[timerIndex]));
+ time = double(m_device->getTimerQueryTime(m_timerQueries[timerIndex]));
time *= 1000.0; // seconds -> milliseconds
if (rayCountData)
@@ -117,44 +122,44 @@ void Profiler::ResolvePreviousFrame()
}
}
- m_TimersUsed[timerIndex] = false;
+ m_timersUsed[timerIndex] = false;
- if (m_IsAccumulating)
+ if (m_isAccumulating)
{
- m_TimerValues[section] += time;
- m_RayCounts[section] += rayCount;
- m_HitCounts[section] += hitCount;
+ m_timerValues[section] += time;
+ m_rayCounts[section] += rayCount;
+ m_hitCounts[section] += hitCount;
}
else
{
- m_TimerValues[section] = time;
- m_RayCounts[section] = rayCount;
- m_HitCounts[section] = hitCount;
+ m_timerValues[section] = time;
+ m_rayCounts[section] = rayCount;
+ m_hitCounts[section] = hitCount;
}
}
if (rayCountData)
- m_RayCounts[ProfilerSection::MaterialReadback] = rayCountData[ProfilerSection::MaterialReadback * 2];
+ m_rayCounts[ProfilerSection::MaterialReadback] = rayCountData[ProfilerSection::MaterialReadback * 2];
else
- m_RayCounts[ProfilerSection::MaterialReadback] = 0;
+ m_rayCounts[ProfilerSection::MaterialReadback] = 0;
if (rayCountData)
{
- m_Device->unmapBuffer(m_RayCountReadback[m_ActiveBank]);
+ m_device->unmapBuffer(m_rayCountReadback[m_activeBank]);
}
- if (m_IsAccumulating)
- m_AccumulatedFrames += 1;
+ if (m_isAccumulating)
+ m_accumulatedFrames += 1;
else
- m_AccumulatedFrames = 1;
+ m_accumulatedFrames = 1;
}
void Profiler::BeginFrame(nvrhi::ICommandList* commandList)
{
- if (!m_Enabled)
+ if (!m_enabled)
return;
- commandList->clearBufferUInt(m_RayCountBuffer, 0);
+ commandList->clearBufferUInt(m_rayCountBuffer, 0);
BeginSection(commandList, ProfilerSection::Frame);
}
@@ -163,12 +168,12 @@ void Profiler::EndFrame(nvrhi::ICommandList* commandList)
{
EndSection(commandList, ProfilerSection::Frame);
- if (m_Enabled)
+ if (m_enabled)
{
commandList->copyBuffer(
- m_RayCountReadback[m_ActiveBank],
+ m_rayCountReadback[m_activeBank],
0,
- m_RayCountBuffer,
+ m_rayCountBuffer,
0,
ProfilerSection::Count * sizeof(uint32_t) * 2);
}
@@ -176,55 +181,60 @@ void Profiler::EndFrame(nvrhi::ICommandList* commandList)
void Profiler::BeginSection(nvrhi::ICommandList* commandList, const ProfilerSection::Enum section)
{
- if (!m_Enabled)
+ if (!m_enabled)
return;
- uint32_t timerIndex = section + m_ActiveBank * ProfilerSection::Count;
- commandList->beginTimerQuery(m_TimerQueries[timerIndex]);
- m_TimersUsed[timerIndex] = true;
+ uint32_t timerIndex = section + m_activeBank * ProfilerSection::Count;
+ commandList->beginTimerQuery(m_timerQueries[timerIndex]);
+ m_timersUsed[timerIndex] = true;
}
void Profiler::EndSection(nvrhi::ICommandList* commandList, const ProfilerSection::Enum section)
{
- if (!m_Enabled)
+ if (!m_enabled)
return;
- uint32_t timerIndex = section + m_ActiveBank * ProfilerSection::Count;
- commandList->endTimerQuery(m_TimerQueries[timerIndex]);
+ uint32_t timerIndex = section + m_activeBank * ProfilerSection::Count;
+ commandList->endTimerQuery(m_timerQueries[timerIndex]);
+}
+
+void Profiler::SetRenderTargets(const std::shared_ptr& renderTargets)
+{
+ m_renderTargets = renderTargets;
}
double Profiler::GetTimer(ProfilerSection::Enum section)
{
- if (m_AccumulatedFrames == 0)
+ if (m_accumulatedFrames == 0)
return 0.0;
- return m_TimerValues[section] / double(m_AccumulatedFrames);
+ return m_timerValues[section] / double(m_accumulatedFrames);
}
double Profiler::GetRayCount(ProfilerSection::Enum section)
{
- if (m_AccumulatedFrames == 0)
+ if (m_accumulatedFrames == 0)
return 0.0;
- return double(m_RayCounts[section]) / double(m_AccumulatedFrames);
+ return double(m_rayCounts[section]) / double(m_accumulatedFrames);
}
double Profiler::GetHitCount(ProfilerSection::Enum section)
{
- if (m_AccumulatedFrames == 0)
+ if (m_accumulatedFrames == 0)
return 0.0;
- return double(m_HitCounts[section]) / double(m_AccumulatedFrames);
+ return double(m_hitCounts[section]) / double(m_accumulatedFrames);
}
int Profiler::GetMaterialReadback()
{
- return int(m_RayCounts[ProfilerSection::MaterialReadback]) - 1;
+ return int(m_rayCounts[ProfilerSection::MaterialReadback]) - 1;
}
void Profiler::BuildUI(const bool enableRayCounts)
{
- auto renderTargets = m_RenderTargets.lock();
+ auto renderTargets = m_renderTargets.lock();
if (!renderTargets)
return;
@@ -294,14 +304,14 @@ void Profiler::BuildUI(const bool enableRayCounts)
std::string Profiler::GetAsText()
{
- auto renderTargets = m_RenderTargets.lock();
+ auto renderTargets = m_renderTargets.lock();
if (!renderTargets)
return "";
const int renderPixels = renderTargets->Size.x * renderTargets->Size.y;
std::stringstream text;
- text << "Renderer: " << m_DeviceManager.GetRendererString() << std::endl;
+ text << "Renderer: " << m_deviceManager.GetRendererString() << std::endl;
text << "Resolution: " << renderTargets->Size.x << " x " << renderTargets->Size.y << std::endl;
for (uint32_t section = 0; section < ProfilerSection::MaterialReadback; section++)
@@ -340,6 +350,11 @@ std::string Profiler::GetAsText()
return text.str();
}
+nvrhi::IBuffer* Profiler::GetRayCountBuffer() const
+{
+ return m_rayCountBuffer;
+}
+
ProfilerScope::ProfilerScope(Profiler& profiler, nvrhi::ICommandList* commandList, ProfilerSection::Enum section)
: m_Profiler(profiler)
, m_CommandList(commandList)
diff --git a/src/Profiler.h b/Samples/FullSample/Source/Profiler.h
similarity index 72%
rename from src/Profiler.h
rename to Samples/FullSample/Source/Profiler.h
index cd6ce68..360ae67 100644
--- a/src/Profiler.h
+++ b/Samples/FullSample/Source/Profiler.h
@@ -25,28 +25,10 @@ namespace donut::app
class Profiler
{
-private:
- bool m_Enabled = true;
- bool m_IsAccumulating = false;
- uint32_t m_AccumulatedFrames = 0;
- uint32_t m_ActiveBank = 0;
-
- std::array m_TimerQueries;
- std::array m_TimerValues{};
- std::array m_RayCounts{};
- std::array m_HitCounts{};
- std::array m_TimersUsed{};
-
- donut::app::DeviceManager& m_DeviceManager;
- nvrhi::DeviceHandle m_Device;
- nvrhi::BufferHandle m_RayCountBuffer;
- std::array m_RayCountReadback;
- std::weak_ptr m_RenderTargets;
-
public:
explicit Profiler(donut::app::DeviceManager& deviceManager);
- bool IsEnabled() const { return m_Enabled; }
+ bool IsEnabled() const;
void EnableProfiler(bool enable);
void EnableAccumulation(bool enable);
void ResetAccumulation();
@@ -55,7 +37,7 @@ class Profiler
void EndFrame(nvrhi::ICommandList* commandList);
void BeginSection(nvrhi::ICommandList* commandList, ProfilerSection::Enum section);
void EndSection(nvrhi::ICommandList* commandList, ProfilerSection::Enum section);
- void SetRenderTargets(const std::shared_ptr& renderTargets) { m_RenderTargets = renderTargets; }
+ void SetRenderTargets(const std::shared_ptr& renderTargets);
double GetTimer(ProfilerSection::Enum section);
double GetRayCount(ProfilerSection::Enum section);
@@ -65,16 +47,29 @@ class Profiler
void BuildUI(bool enableRayCounts);
std::string GetAsText();
- [[nodiscard]] nvrhi::IBuffer* GetRayCountBuffer() const { return m_RayCountBuffer; }
+ [[nodiscard]] nvrhi::IBuffer* GetRayCountBuffer() const;
+
+private:
+ bool m_enabled = true;
+ bool m_isAccumulating = false;
+ uint32_t m_accumulatedFrames = 0;
+ uint32_t m_activeBank = 0;
+
+ std::array m_timerQueries;
+ std::array m_timerValues{};
+ std::array m_rayCounts{};
+ std::array m_hitCounts{};
+ std::array m_timersUsed{};
+
+ donut::app::DeviceManager& m_deviceManager;
+ nvrhi::DeviceHandle m_device;
+ nvrhi::BufferHandle m_rayCountBuffer;
+ std::array m_rayCountReadback;
+ std::weak_ptr m_renderTargets;
};
class ProfilerScope
{
-private:
- Profiler& m_Profiler;
- nvrhi::ICommandList* m_CommandList;
- ProfilerSection::Enum m_Section;
-
public:
ProfilerScope(Profiler& profiler, nvrhi::ICommandList* commandList, ProfilerSection::Enum section);
~ProfilerScope();
@@ -84,4 +79,9 @@ class ProfilerScope
ProfilerScope(const ProfilerScope&&) = delete;
ProfilerScope& operator=(const ProfilerScope&) = delete;
ProfilerScope& operator=(const ProfilerScope&&) = delete;
+
+private:
+ Profiler& m_Profiler;
+ nvrhi::ICommandList* m_CommandList;
+ ProfilerSection::Enum m_Section;
};
diff --git a/src/ProfilerSections.h b/Samples/FullSample/Source/ProfilerSections.h
similarity index 100%
rename from src/ProfilerSections.h
rename to Samples/FullSample/Source/ProfilerSections.h
diff --git a/src/AccumulationPass.cpp b/Samples/FullSample/Source/RenderPasses/AccumulationPass.cpp
similarity index 80%
rename from src/AccumulationPass.cpp
rename to Samples/FullSample/Source/RenderPasses/AccumulationPass.cpp
index ac96911..4ca4b28 100644
--- a/src/AccumulationPass.cpp
+++ b/Samples/FullSample/Source/RenderPasses/AccumulationPass.cpp
@@ -9,7 +9,7 @@
**************************************************************************/
#include "AccumulationPass.h"
-#include "RenderTargets.h"
+#include "../RenderTargets.h"
#include
#include
@@ -17,7 +17,7 @@
#include
using namespace donut::math;
-#include "../shaders/ShaderParameters.h"
+#include "../../shaders/ShaderParameters.h"
using namespace donut::engine;
@@ -25,8 +25,8 @@ using namespace donut::engine;
AccumulationPass::AccumulationPass(
nvrhi::IDevice* device,
std::shared_ptr shaderFactory)
- : m_Device(device)
- , m_ShaderFactory(shaderFactory)
+ : m_device(device)
+ , m_shaderFactory(shaderFactory)
{
nvrhi::BindingLayoutDesc bindingLayoutDesc;
bindingLayoutDesc.visibility = nvrhi::ShaderType::Compute;
@@ -37,24 +37,24 @@ AccumulationPass::AccumulationPass(
nvrhi::BindingLayoutItem::PushConstants(0, sizeof(AccumulationConstants))
};
- m_BindingLayout = m_Device->createBindingLayout(bindingLayoutDesc);
+ m_bindingLayout = m_device->createBindingLayout(bindingLayoutDesc);
auto samplerDesc = nvrhi::SamplerDesc()
.setAllFilters(true);
- m_Sampler = m_Device->createSampler(samplerDesc);
+ m_sampler = m_device->createSampler(samplerDesc);
}
void AccumulationPass::CreatePipeline()
{
donut::log::debug("Initializing AccumulationPass...");
- m_ComputeShader = m_ShaderFactory->CreateShader("app/AccumulationPass.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
+ m_computeShader = m_shaderFactory->CreateShader("app/AccumulationPass.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
nvrhi::ComputePipelineDesc pipelineDesc;
- pipelineDesc.bindingLayouts = { m_BindingLayout };
- pipelineDesc.CS = m_ComputeShader;
- m_ComputePipeline = m_Device->createComputePipeline(pipelineDesc);
+ pipelineDesc.bindingLayouts = { m_bindingLayout };
+ pipelineDesc.CS = m_computeShader;
+ m_computePipeline = m_device->createComputePipeline(pipelineDesc);
}
void AccumulationPass::CreateBindingSet(const RenderTargets& renderTargets)
@@ -64,13 +64,13 @@ void AccumulationPass::CreateBindingSet(const RenderTargets& renderTargets)
bindingSetDesc.bindings = {
nvrhi::BindingSetItem::Texture_SRV(0, renderTargets.HdrColor),
nvrhi::BindingSetItem::Texture_UAV(0, renderTargets.AccumulatedColor),
- nvrhi::BindingSetItem::Sampler(0, m_Sampler),
+ nvrhi::BindingSetItem::Sampler(0, m_sampler),
nvrhi::BindingSetItem::PushConstants(0, sizeof(AccumulationConstants))
};
- m_BindingSet = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ m_bindingSet = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
- m_CompositedColor = renderTargets.HdrColor;
+ m_compositedColor = renderTargets.HdrColor;
}
void AccumulationPass::Render(
@@ -84,7 +84,7 @@ void AccumulationPass::Render(
const auto sourceViewport = sourceView.GetViewportState().viewports[0];
const auto upscaledViewport = upscaledView.GetViewportState().viewports[0];
- const auto& inputDesc = m_CompositedColor->getDesc();
+ const auto& inputDesc = m_compositedColor->getDesc();
AccumulationConstants constants = {};
constants.inputSize = float2(sourceViewport.width(), sourceViewport.height());
@@ -94,8 +94,8 @@ void AccumulationPass::Render(
constants.blendFactor = accumulationWeight;
nvrhi::ComputeState state;
- state.bindings = { m_BindingSet };
- state.pipeline = m_ComputePipeline;
+ state.bindings = { m_bindingSet };
+ state.pipeline = m_computePipeline;
commandList->setComputeState(state);
commandList->setPushConstants(&constants, sizeof(constants));
diff --git a/src/AccumulationPass.h b/Samples/FullSample/Source/RenderPasses/AccumulationPass.h
similarity index 76%
rename from src/AccumulationPass.h
rename to Samples/FullSample/Source/RenderPasses/AccumulationPass.h
index d295b68..aa3f0c4 100644
--- a/src/AccumulationPass.h
+++ b/Samples/FullSample/Source/RenderPasses/AccumulationPass.h
@@ -23,18 +23,6 @@ class RenderTargets;
class AccumulationPass
{
-private:
- nvrhi::DeviceHandle m_Device;
-
- nvrhi::ShaderHandle m_ComputeShader;
- nvrhi::ComputePipelineHandle m_ComputePipeline;
- nvrhi::BindingLayoutHandle m_BindingLayout;
- nvrhi::BindingSetHandle m_BindingSet;
- nvrhi::SamplerHandle m_Sampler;
- nvrhi::TextureHandle m_CompositedColor;
-
- std::shared_ptr m_ShaderFactory;
-
public:
AccumulationPass(
nvrhi::IDevice* device,
@@ -49,4 +37,16 @@ class AccumulationPass
const donut::engine::IView& sourceView,
const donut::engine::IView& upscaledView,
float accumulationWeight);
+
+private:
+ nvrhi::DeviceHandle m_device;
+
+ nvrhi::ShaderHandle m_computeShader;
+ nvrhi::ComputePipelineHandle m_computePipeline;
+ nvrhi::BindingLayoutHandle m_bindingLayout;
+ nvrhi::BindingSetHandle m_bindingSet;
+ nvrhi::SamplerHandle m_sampler;
+ nvrhi::TextureHandle m_compositedColor;
+
+ std::shared_ptr m_shaderFactory;
};
diff --git a/src/CompositingPass.cpp b/Samples/FullSample/Source/RenderPasses/CompositingPass.cpp
similarity index 81%
rename from src/CompositingPass.cpp
rename to Samples/FullSample/Source/RenderPasses/CompositingPass.cpp
index f516841..cf62570 100644
--- a/src/CompositingPass.cpp
+++ b/Samples/FullSample/Source/RenderPasses/CompositingPass.cpp
@@ -9,9 +9,9 @@
**************************************************************************/
#include "CompositingPass.h"
-#include "RenderTargets.h"
-#include "SampleScene.h"
-#include "UserInterface.h"
+#include "../RenderTargets.h"
+#include "../SampleScene.h"
+#include "../UserInterface.h"
#include
#include
@@ -23,7 +23,7 @@
#include
using namespace donut::math;
-#include "../shaders/ShaderParameters.h"
+#include "../../shaders/ShaderParameters.h"
using namespace donut::engine;
@@ -34,13 +34,13 @@ CompositingPass::CompositingPass(
std::shared_ptr commonPasses,
std::shared_ptr scene,
nvrhi::IBindingLayout* bindlessLayout)
- : m_Device(device)
- , m_BindlessLayout(bindlessLayout)
- , m_ShaderFactory(std::move(shaderFactory))
- , m_CommonPasses(std::move(commonPasses))
- , m_Scene(std::move(scene))
+ : m_device(device)
+ , m_bindlessLayout(bindlessLayout)
+ , m_shaderFactory(std::move(shaderFactory))
+ , m_commonPasses(std::move(commonPasses))
+ , m_scene(std::move(scene))
{
- m_ConstantBuffer = m_Device->createBuffer(nvrhi::utils::CreateVolatileConstantBufferDesc(sizeof(CompositingConstants), "CompositingConstants", 16));
+ m_constantBuffer = m_device->createBuffer(nvrhi::utils::CreateVolatileConstantBufferDesc(sizeof(CompositingConstants), "CompositingConstants", 16));
nvrhi::BindingLayoutDesc bindingLayoutDesc;
bindingLayoutDesc.visibility = nvrhi::ShaderType::Compute;
@@ -60,19 +60,19 @@ CompositingPass::CompositingPass(
nvrhi::BindingLayoutItem::VolatileConstantBuffer(0)
};
- m_BindingLayout = m_Device->createBindingLayout(bindingLayoutDesc);
+ m_bindingLayout = m_device->createBindingLayout(bindingLayoutDesc);
}
void CompositingPass::CreatePipeline()
{
donut::log::debug("Initializing CompositingPass...");
- m_ComputeShader = m_ShaderFactory->CreateShader("app/CompositingPass.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
+ m_computeShader = m_shaderFactory->CreateShader("app/CompositingPass.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
nvrhi::ComputePipelineDesc pipelineDesc;
- pipelineDesc.bindingLayouts = { m_BindingLayout, m_BindlessLayout };
- pipelineDesc.CS = m_ComputeShader;
- m_ComputePipeline = m_Device->createComputePipeline(pipelineDesc);
+ pipelineDesc.bindingLayouts = { m_bindingLayout, m_bindlessLayout };
+ pipelineDesc.CS = m_computeShader;
+ m_computePipeline = m_device->createComputePipeline(pipelineDesc);
}
void CompositingPass::CreateBindingSet(const RenderTargets& renderTargets)
@@ -93,18 +93,18 @@ void CompositingPass::CreateBindingSet(const RenderTargets& renderTargets)
nvrhi::BindingSetItem::Texture_SRV(8, renderTargets.DenoisedSpecularLighting),
nvrhi::BindingSetItem::Texture_UAV(0, renderTargets.HdrColor),
nvrhi::BindingSetItem::Texture_UAV(1, renderTargets.MotionVectors),
- nvrhi::BindingSetItem::Sampler(0, m_CommonPasses->m_LinearWrapSampler),
- nvrhi::BindingSetItem::ConstantBuffer(0, m_ConstantBuffer)
+ nvrhi::BindingSetItem::Sampler(0, m_commonPasses->m_LinearWrapSampler),
+ nvrhi::BindingSetItem::ConstantBuffer(0, m_constantBuffer)
};
- m_BindingSetEven = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ m_bindingSetEven = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
bindingSetDesc.bindings[0].resourceHandle = renderTargets.PrevDepth;
bindingSetDesc.bindings[1].resourceHandle = renderTargets.PrevGBufferNormals;
bindingSetDesc.bindings[2].resourceHandle = renderTargets.PrevGBufferDiffuseAlbedo;
bindingSetDesc.bindings[3].resourceHandle = renderTargets.PrevGBufferSpecularRough;
- m_BindingSetOdd = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ m_bindingSetOdd = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
}
void CompositingPass::Render(
@@ -131,11 +131,11 @@ void CompositingPass::Render(
constants.noiseMix = ui.noiseMix;
constants.noiseClampLow = ui.noiseClampLow;
constants.noiseClampHigh = ui.noiseClampHigh;
- commandList->writeBuffer(m_ConstantBuffer, &constants, sizeof(constants));
+ commandList->writeBuffer(m_constantBuffer, &constants, sizeof(constants));
nvrhi::ComputeState state;
- state.bindings = { m_BindingSetEven, m_Scene->GetDescriptorTable() };
- state.pipeline = m_ComputePipeline;
+ state.bindings = { m_bindingSetEven, m_scene->GetDescriptorTable() };
+ state.pipeline = m_computePipeline;
commandList->setComputeState(state);
commandList->dispatch(
@@ -148,5 +148,5 @@ void CompositingPass::Render(
void CompositingPass::NextFrame()
{
- std::swap(m_BindingSetEven, m_BindingSetOdd);
+ std::swap(m_bindingSetEven, m_bindingSetOdd);
}
diff --git a/src/CompositingPass.h b/Samples/FullSample/Source/RenderPasses/CompositingPass.h
similarity index 74%
rename from src/CompositingPass.h
rename to Samples/FullSample/Source/RenderPasses/CompositingPass.h
index f9e7b2e..ce7a380 100644
--- a/src/CompositingPass.h
+++ b/Samples/FullSample/Source/RenderPasses/CompositingPass.h
@@ -27,22 +27,6 @@ struct UIData;
class CompositingPass
{
-private:
- nvrhi::DeviceHandle m_Device;
-
- nvrhi::ShaderHandle m_ComputeShader;
- nvrhi::ComputePipelineHandle m_ComputePipeline;
- nvrhi::BindingLayoutHandle m_BindingLayout;
- nvrhi::BindingLayoutHandle m_BindlessLayout;
- nvrhi::BindingSetHandle m_BindingSetEven;
- nvrhi::BindingSetHandle m_BindingSetOdd;
-
- nvrhi::BufferHandle m_ConstantBuffer;
-
- std::shared_ptr m_ShaderFactory;
- std::shared_ptr m_CommonPasses;
- std::shared_ptr m_Scene;
-
public:
CompositingPass(
nvrhi::IDevice* device,
@@ -65,4 +49,20 @@ class CompositingPass
const EnvironmentLight& environmentLight);
void NextFrame();
+
+private:
+ nvrhi::DeviceHandle m_device;
+
+ nvrhi::ShaderHandle m_computeShader;
+ nvrhi::ComputePipelineHandle m_computePipeline;
+ nvrhi::BindingLayoutHandle m_bindingLayout;
+ nvrhi::BindingLayoutHandle m_bindlessLayout;
+ nvrhi::BindingSetHandle m_bindingSetEven;
+ nvrhi::BindingSetHandle m_bindingSetOdd;
+
+ nvrhi::BufferHandle m_constantBuffer;
+
+ std::shared_ptr m_shaderFactory;
+ std::shared_ptr m_commonPasses;
+ std::shared_ptr m_scene;
};
diff --git a/src/ConfidencePass.cpp b/Samples/FullSample/Source/RenderPasses/ConfidencePass.cpp
similarity index 80%
rename from src/ConfidencePass.cpp
rename to Samples/FullSample/Source/RenderPasses/ConfidencePass.cpp
index b281d3a..cb0e268 100644
--- a/src/ConfidencePass.cpp
+++ b/Samples/FullSample/Source/RenderPasses/ConfidencePass.cpp
@@ -10,7 +10,7 @@
#include "ConfidencePass.h"
#include "FilterGradientsPass.h"
-#include "RenderTargets.h"
+#include "../RenderTargets.h"
#include
#include
@@ -19,15 +19,15 @@
using namespace donut::math;
-#include "../shaders/ShaderParameters.h"
+#include "../../shaders/ShaderParameters.h"
using namespace donut::engine;
ConfidencePass::ConfidencePass(
nvrhi::IDevice* device,
std::shared_ptr shaderFactory)
- : m_Device(device)
- , m_ShaderFactory(shaderFactory)
+ : m_device(device)
+ , m_shaderFactory(shaderFactory)
{
nvrhi::BindingLayoutDesc bindingLayoutDesc;
bindingLayoutDesc.visibility = nvrhi::ShaderType::Compute;
@@ -42,26 +42,26 @@ ConfidencePass::ConfidencePass(
nvrhi::BindingLayoutItem::PushConstants(0, sizeof(ConfidenceConstants))
};
- m_BindingLayout = m_Device->createBindingLayout(bindingLayoutDesc);
+ m_bindingLayout = m_device->createBindingLayout(bindingLayoutDesc);
auto samplerDesc = nvrhi::SamplerDesc()
.setAllFilters(true)
.setAllAddressModes(nvrhi::SamplerAddressMode::ClampToBorder)
.setBorderColor(nvrhi::Color(0.f));
- m_Sampler = device->createSampler(samplerDesc);
+ m_sampler = device->createSampler(samplerDesc);
}
void ConfidencePass::CreatePipeline()
{
donut::log::debug("Initializing ConfidencePass...");
- m_ComputeShader = m_ShaderFactory->CreateShader("app/ConfidencePass.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
+ m_computeShader = m_shaderFactory->CreateShader("app/DenoisingPasses/ConfidencePass.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
nvrhi::ComputePipelineDesc pipelineDesc;
- pipelineDesc.bindingLayouts = { m_BindingLayout };
- pipelineDesc.CS = m_ComputeShader;
- m_ComputePipeline = m_Device->createComputePipeline(pipelineDesc);
+ pipelineDesc.bindingLayouts = { m_bindingLayout };
+ pipelineDesc.CS = m_computeShader;
+ m_computePipeline = m_device->createComputePipeline(pipelineDesc);
}
void ConfidencePass::CreateBindingSet(const RenderTargets& renderTargets)
@@ -77,18 +77,18 @@ void ConfidencePass::CreateBindingSet(const RenderTargets& renderTargets)
nvrhi::BindingSetItem::Texture_SRV(3, currentFrame ? renderTargets.PrevSpecularConfidence : renderTargets.SpecularConfidence),
nvrhi::BindingSetItem::Texture_UAV(0, currentFrame ? renderTargets.DiffuseConfidence : renderTargets.PrevDiffuseConfidence),
nvrhi::BindingSetItem::Texture_UAV(1, currentFrame ? renderTargets.SpecularConfidence : renderTargets.PrevSpecularConfidence),
- nvrhi::BindingSetItem::Sampler(0, m_Sampler),
+ nvrhi::BindingSetItem::Sampler(0, m_sampler),
nvrhi::BindingSetItem::PushConstants(0, sizeof(ConfidenceConstants))
};
- nvrhi::BindingSetHandle bindingSet = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ nvrhi::BindingSetHandle bindingSet = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
if (currentFrame)
- m_BindingSet = bindingSet;
+ m_bindingSet = bindingSet;
else
- m_PrevBindingSet = bindingSet;
+ m_prevBindingSet = bindingSet;
}
- m_GradientsTexture = renderTargets.Gradients;
+ m_gradientsTexture = renderTargets.Gradients;
}
void ConfidencePass::Render(
@@ -101,7 +101,7 @@ void ConfidencePass::Render(
{
commandList->beginMarker("Confidence");
- const auto& gradientsDesc = m_GradientsTexture->getDesc();
+ const auto& gradientsDesc = m_gradientsTexture->getDesc();
ConfidenceConstants constants = {};
constants.viewportSize = dm::uint2(view.GetViewExtent().width(), view.GetViewExtent().height());
@@ -114,8 +114,8 @@ void ConfidencePass::Render(
constants.inputBufferIndex = FilterGradientsPass::GetOutputBufferIndex();
nvrhi::ComputeState state;
- state.bindings = { m_BindingSet };
- state.pipeline = m_ComputePipeline;
+ state.bindings = { m_bindingSet };
+ state.pipeline = m_computePipeline;
commandList->setComputeState(state);
commandList->setPushConstants(&constants, sizeof(constants));
@@ -130,5 +130,5 @@ void ConfidencePass::Render(
void ConfidencePass::NextFrame()
{
- std::swap(m_BindingSet, m_PrevBindingSet);
+ std::swap(m_bindingSet, m_prevBindingSet);
}
diff --git a/src/ConfidencePass.h b/Samples/FullSample/Source/RenderPasses/ConfidencePass.h
similarity index 75%
rename from src/ConfidencePass.h
rename to Samples/FullSample/Source/RenderPasses/ConfidencePass.h
index 4f06a91..91e6000 100644
--- a/src/ConfidencePass.h
+++ b/Samples/FullSample/Source/RenderPasses/ConfidencePass.h
@@ -23,19 +23,6 @@ class RenderTargets;
class ConfidencePass
{
-private:
- nvrhi::DeviceHandle m_Device;
-
- nvrhi::ShaderHandle m_ComputeShader;
- nvrhi::ComputePipelineHandle m_ComputePipeline;
- nvrhi::BindingLayoutHandle m_BindingLayout;
- nvrhi::BindingSetHandle m_BindingSet;
- nvrhi::BindingSetHandle m_PrevBindingSet;
- nvrhi::TextureHandle m_GradientsTexture;
- nvrhi::SamplerHandle m_Sampler;
-
- std::shared_ptr m_ShaderFactory;
-
public:
ConfidencePass(
nvrhi::IDevice* device,
@@ -54,4 +41,17 @@ class ConfidencePass
bool checkerboard);
void NextFrame();
+
+private:
+ nvrhi::DeviceHandle m_device;
+
+ nvrhi::ShaderHandle m_computeShader;
+ nvrhi::ComputePipelineHandle m_computePipeline;
+ nvrhi::BindingLayoutHandle m_bindingLayout;
+ nvrhi::BindingSetHandle m_bindingSet;
+ nvrhi::BindingSetHandle m_prevBindingSet;
+ nvrhi::TextureHandle m_gradientsTexture;
+ nvrhi::SamplerHandle m_sampler;
+
+ std::shared_ptr m_shaderFactory;
};
diff --git a/src/FilterGradientsPass.cpp b/Samples/FullSample/Source/RenderPasses/FilterGradientsPass.cpp
similarity index 78%
rename from src/FilterGradientsPass.cpp
rename to Samples/FullSample/Source/RenderPasses/FilterGradientsPass.cpp
index 9ace989..b93f979 100644
--- a/src/FilterGradientsPass.cpp
+++ b/Samples/FullSample/Source/RenderPasses/FilterGradientsPass.cpp
@@ -9,7 +9,7 @@
**************************************************************************/
#include "FilterGradientsPass.h"
-#include "RenderTargets.h"
+#include "../RenderTargets.h"
#include
#include
@@ -17,7 +17,7 @@
#include
using namespace donut::math;
-#include "../shaders/ShaderParameters.h"
+#include "../../shaders/ShaderParameters.h"
using namespace donut::engine;
@@ -26,8 +26,8 @@ static const int c_NumFilterPasses = 4;
FilterGradientsPass::FilterGradientsPass(
nvrhi::IDevice* device,
std::shared_ptr shaderFactory)
- : m_Device(device)
- , m_ShaderFactory(shaderFactory)
+ : m_device(device)
+ , m_shaderFactory(shaderFactory)
{
nvrhi::BindingLayoutDesc bindingLayoutDesc;
bindingLayoutDesc.visibility = nvrhi::ShaderType::Compute;
@@ -36,19 +36,19 @@ FilterGradientsPass::FilterGradientsPass(
nvrhi::BindingLayoutItem::PushConstants(0, sizeof(FilterGradientsConstants))
};
- m_BindingLayout = m_Device->createBindingLayout(bindingLayoutDesc);
+ m_bindingLayout = m_device->createBindingLayout(bindingLayoutDesc);
}
void FilterGradientsPass::CreatePipeline()
{
donut::log::debug("Initializing FilterGradientsPass...");
- m_ComputeShader = m_ShaderFactory->CreateShader("app/FilterGradientsPass.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
+ m_computeShader = m_shaderFactory->CreateShader("app/DenoisingPasses/FilterGradientsPass.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
nvrhi::ComputePipelineDesc pipelineDesc;
- pipelineDesc.bindingLayouts = { m_BindingLayout };
- pipelineDesc.CS = m_ComputeShader;
- m_ComputePipeline = m_Device->createComputePipeline(pipelineDesc);
+ pipelineDesc.bindingLayouts = { m_bindingLayout };
+ pipelineDesc.CS = m_computeShader;
+ m_computePipeline = m_device->createComputePipeline(pipelineDesc);
}
void FilterGradientsPass::CreateBindingSet(const RenderTargets& renderTargets)
@@ -60,9 +60,9 @@ void FilterGradientsPass::CreateBindingSet(const RenderTargets& renderTargets)
nvrhi::BindingSetItem::PushConstants(0, sizeof(FilterGradientsConstants))
};
- m_BindingSet = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ m_bindingSet = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
- m_GradientsTexture = renderTargets.Gradients;
+ m_gradientsTexture = renderTargets.Gradients;
}
void FilterGradientsPass::Render(
@@ -78,8 +78,8 @@ void FilterGradientsPass::Render(
constants.checkerboard = checkerboard;
nvrhi::ComputeState state;
- state.bindings = { m_BindingSet };
- state.pipeline = m_ComputePipeline;
+ state.bindings = { m_bindingSet };
+ state.pipeline = m_computePipeline;
commandList->setComputeState(state);
for (int passIndex = 0; passIndex < c_NumFilterPasses; passIndex++)
@@ -92,7 +92,7 @@ void FilterGradientsPass::Render(
dm::div_ceil(view.GetViewExtent().height(), 8),
1);
- nvrhi::utils::TextureUavBarrier(commandList, m_GradientsTexture);
+ nvrhi::utils::TextureUavBarrier(commandList, m_gradientsTexture);
commandList->commitBarriers();
}
diff --git a/src/FilterGradientsPass.h b/Samples/FullSample/Source/RenderPasses/FilterGradientsPass.h
similarity index 78%
rename from src/FilterGradientsPass.h
rename to Samples/FullSample/Source/RenderPasses/FilterGradientsPass.h
index 290fe18..ebd0634 100644
--- a/src/FilterGradientsPass.h
+++ b/Samples/FullSample/Source/RenderPasses/FilterGradientsPass.h
@@ -23,17 +23,6 @@ class RenderTargets;
class FilterGradientsPass
{
-private:
- nvrhi::DeviceHandle m_Device;
-
- nvrhi::ShaderHandle m_ComputeShader;
- nvrhi::ComputePipelineHandle m_ComputePipeline;
- nvrhi::BindingLayoutHandle m_BindingLayout;
- nvrhi::BindingSetHandle m_BindingSet;
- nvrhi::TextureHandle m_GradientsTexture;
-
- std::shared_ptr m_ShaderFactory;
-
public:
FilterGradientsPass(
nvrhi::IDevice* device,
@@ -49,4 +38,15 @@ class FilterGradientsPass
bool checkerboard);
static int GetOutputBufferIndex();
+
+private:
+ nvrhi::DeviceHandle m_device;
+
+ nvrhi::ShaderHandle m_computeShader;
+ nvrhi::ComputePipelineHandle m_computePipeline;
+ nvrhi::BindingLayoutHandle m_bindingLayout;
+ nvrhi::BindingSetHandle m_bindingSet;
+ nvrhi::TextureHandle m_gradientsTexture;
+
+ std::shared_ptr m_shaderFactory;
};
diff --git a/src/GBufferPass.cpp b/Samples/FullSample/Source/RenderPasses/GBufferPass.cpp
similarity index 78%
rename from src/GBufferPass.cpp
rename to Samples/FullSample/Source/RenderPasses/GBufferPass.cpp
index e47f82f..587f132 100644
--- a/src/GBufferPass.cpp
+++ b/Samples/FullSample/Source/RenderPasses/GBufferPass.cpp
@@ -9,9 +9,9 @@
**************************************************************************/
#include "GBufferPass.h"
-#include "RenderTargets.h"
-#include "Profiler.h"
-#include "SampleScene.h"
+#include "../RenderTargets.h"
+#include "../Profiler.h"
+#include "../SampleScene.h"
#include
#include
@@ -24,7 +24,7 @@
#include
using namespace donut::math;
-#include "../shaders/ShaderParameters.h"
+#include "../../shaders/ShaderParameters.h"
using namespace donut::engine;
@@ -36,14 +36,14 @@ RaytracedGBufferPass::RaytracedGBufferPass(
std::shared_ptr scene,
std::shared_ptr profiler,
nvrhi::IBindingLayout* bindlessLayout)
- : m_Device(device)
- , m_BindlessLayout(bindlessLayout)
- , m_ShaderFactory(std::move(shaderFactory))
- , m_CommonPasses(std::move(commonPasses))
- , m_Scene(std::move(scene))
- , m_Profiler(std::move(profiler))
+ : m_device(device)
+ , m_bindlessLayout(bindlessLayout)
+ , m_shaderFactory(std::move(shaderFactory))
+ , m_commonPasses(std::move(commonPasses))
+ , m_scene(std::move(scene))
+ , m_profiler(std::move(profiler))
{
- m_ConstantBuffer = m_Device->createBuffer(nvrhi::utils::CreateVolatileConstantBufferDesc(sizeof(GBufferConstants), "GBufferPassConstants", 16));
+ m_constantBuffer = m_device->createBuffer(nvrhi::utils::CreateVolatileConstantBufferDesc(sizeof(GBufferConstants), "GBufferPassConstants", 16));
nvrhi::BindingLayoutDesc globalBindingLayoutDesc;
globalBindingLayoutDesc.visibility = nvrhi::ShaderType::Compute | nvrhi::ShaderType::AllRayTracing;
@@ -67,12 +67,12 @@ RaytracedGBufferPass::RaytracedGBufferPass(
nvrhi::BindingLayoutItem::Sampler(0)
};
- m_BindingLayout = m_Device->createBindingLayout(globalBindingLayoutDesc);
+ m_bindingLayout = m_device->createBindingLayout(globalBindingLayoutDesc);
}
void RaytracedGBufferPass::CreatePipeline(bool useRayQuery)
{
- m_Pass.Init(m_Device, *m_ShaderFactory, "app/RaytracedGBuffer.hlsl", {}, useRayQuery, 16, m_BindingLayout, nullptr, m_BindlessLayout);
+ m_pass.Init(m_device, *m_shaderFactory, "app/RaytracedGBuffer.hlsl", {}, useRayQuery, 16, m_bindingLayout, nullptr, m_bindlessLayout);
}
void RaytracedGBufferPass::CreateBindingSet(
@@ -92,23 +92,23 @@ void RaytracedGBufferPass::CreateBindingSet(
nvrhi::BindingSetItem::Texture_UAV(5, renderTargets.GBufferEmissive),
nvrhi::BindingSetItem::Texture_UAV(6, renderTargets.MotionVectors),
nvrhi::BindingSetItem::Texture_UAV(7, renderTargets.DeviceDepthUAV),
- nvrhi::BindingSetItem::TypedBuffer_UAV(8, m_Profiler->GetRayCountBuffer()),
+ nvrhi::BindingSetItem::TypedBuffer_UAV(8, m_profiler->GetRayCountBuffer()),
- nvrhi::BindingSetItem::ConstantBuffer(0, m_ConstantBuffer),
+ nvrhi::BindingSetItem::ConstantBuffer(0, m_constantBuffer),
nvrhi::BindingSetItem::PushConstants(1, sizeof(PerPassConstants)),
nvrhi::BindingSetItem::RayTracingAccelStruct(0, currentFrame ? topLevelAS : prevTopLevelAS),
- nvrhi::BindingSetItem::StructuredBuffer_SRV(1, m_Scene->GetInstanceBuffer()),
- nvrhi::BindingSetItem::StructuredBuffer_SRV(2, m_Scene->GetGeometryBuffer()),
- nvrhi::BindingSetItem::StructuredBuffer_SRV(3, m_Scene->GetMaterialBuffer()),
- nvrhi::BindingSetItem::Sampler(0, m_CommonPasses->m_AnisotropicWrapSampler)
+ nvrhi::BindingSetItem::StructuredBuffer_SRV(1, m_scene->GetInstanceBuffer()),
+ nvrhi::BindingSetItem::StructuredBuffer_SRV(2, m_scene->GetGeometryBuffer()),
+ nvrhi::BindingSetItem::StructuredBuffer_SRV(3, m_scene->GetMaterialBuffer()),
+ nvrhi::BindingSetItem::Sampler(0, m_commonPasses->m_AnisotropicWrapSampler)
};
- const nvrhi::BindingSetHandle bindingSet = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ const nvrhi::BindingSetHandle bindingSet = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
if (currentFrame)
- m_BindingSet = bindingSet;
+ m_bindingSet = bindingSet;
else
- m_PrevBindingSet = bindingSet;
+ m_prevBindingSet = bindingSet;
}
}
@@ -132,18 +132,18 @@ void RaytracedGBufferPass::Render(
constants.materialReadbackPosition = (settings.enableMaterialReadback) ? settings.materialReadbackPosition : int2(-1, -1);
constants.textureLodBias = settings.textureLodBias;
constants.textureGradientScale = powf(2.f, settings.textureLodBias);
- commandList->writeBuffer(m_ConstantBuffer, &constants, sizeof(constants));
+ commandList->writeBuffer(m_constantBuffer, &constants, sizeof(constants));
PerPassConstants pushConstants{};
pushConstants.rayCountBufferIndex = ProfilerSection::GBufferFill;
- m_Pass.Execute(
+ m_pass.Execute(
commandList,
view.GetViewExtent().width(),
view.GetViewExtent().height(),
- m_BindingSet,
+ m_bindingSet,
nullptr,
- m_Scene->GetDescriptorTable(),
+ m_scene->GetDescriptorTable(),
&pushConstants,
sizeof(pushConstants));
@@ -152,7 +152,7 @@ void RaytracedGBufferPass::Render(
void RaytracedGBufferPass::NextFrame()
{
- std::swap(m_BindingSet, m_PrevBindingSet);
+ std::swap(m_bindingSet, m_prevBindingSet);
}
RasterizedGBufferPass::RasterizedGBufferPass(
@@ -162,14 +162,14 @@ RasterizedGBufferPass::RasterizedGBufferPass(
std::shared_ptr scene,
std::shared_ptr profiler,
nvrhi::IBindingLayout* bindlessLayout)
- : m_Device(device)
- , m_BindlessLayout(bindlessLayout)
- , m_ShaderFactory(std::move(shaderFactory))
- , m_CommonPasses(std::move(commonPasses))
- , m_Scene(std::move(scene))
- , m_Profiler(std::move(profiler))
+ : m_device(device)
+ , m_bindlessLayout(bindlessLayout)
+ , m_shaderFactory(std::move(shaderFactory))
+ , m_commonPasses(std::move(commonPasses))
+ , m_scene(std::move(scene))
+ , m_profiler(std::move(profiler))
{
- m_ConstantBuffer = m_Device->createBuffer(nvrhi::utils::CreateVolatileConstantBufferDesc(sizeof(GBufferConstants), "GBufferPassConstants", 16));
+ m_constantBuffer = m_device->createBuffer(nvrhi::utils::CreateVolatileConstantBufferDesc(sizeof(GBufferConstants), "GBufferPassConstants", 16));
nvrhi::BindingLayoutDesc globalBindingLayoutDesc;
globalBindingLayoutDesc.visibility = nvrhi::ShaderType::Vertex | nvrhi::ShaderType::Pixel;
@@ -183,7 +183,7 @@ RasterizedGBufferPass::RasterizedGBufferPass(
nvrhi::BindingLayoutItem::TypedBuffer_UAV(0)
};
- m_BindingLayout = m_Device->createBindingLayout(globalBindingLayoutDesc);
+ m_bindingLayout = m_device->createBindingLayout(globalBindingLayoutDesc);
}
@@ -192,16 +192,16 @@ void RasterizedGBufferPass::CreateBindingSet()
nvrhi::BindingSetDesc bindingSetDesc;
bindingSetDesc.bindings = {
- nvrhi::BindingSetItem::ConstantBuffer(0, m_ConstantBuffer),
+ nvrhi::BindingSetItem::ConstantBuffer(0, m_constantBuffer),
nvrhi::BindingSetItem::PushConstants(1, sizeof(uint2)),
- nvrhi::BindingSetItem::StructuredBuffer_SRV(0, m_Scene->GetInstanceBuffer()),
- nvrhi::BindingSetItem::StructuredBuffer_SRV(1, m_Scene->GetGeometryBuffer()),
- nvrhi::BindingSetItem::StructuredBuffer_SRV(2, m_Scene->GetMaterialBuffer()),
- nvrhi::BindingSetItem::Sampler(0, m_CommonPasses->m_AnisotropicWrapSampler),
- nvrhi::BindingSetItem::TypedBuffer_UAV(0, m_Profiler->GetRayCountBuffer())
+ nvrhi::BindingSetItem::StructuredBuffer_SRV(0, m_scene->GetInstanceBuffer()),
+ nvrhi::BindingSetItem::StructuredBuffer_SRV(1, m_scene->GetGeometryBuffer()),
+ nvrhi::BindingSetItem::StructuredBuffer_SRV(2, m_scene->GetMaterialBuffer()),
+ nvrhi::BindingSetItem::Sampler(0, m_commonPasses->m_AnisotropicWrapSampler),
+ nvrhi::BindingSetItem::TypedBuffer_UAV(0, m_profiler->GetRayCountBuffer())
};
- m_BindingSet = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ m_bindingSet = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
}
void RasterizedGBufferPass::CreatePipeline(const RenderTargets& renderTargets)
@@ -212,9 +212,9 @@ void RasterizedGBufferPass::CreatePipeline(const RenderTargets& renderTargets)
nvrhi::GraphicsPipelineDesc pipelineDesc;
- pipelineDesc.bindingLayouts = { m_BindingLayout, m_BindlessLayout };
- pipelineDesc.VS = m_ShaderFactory->CreateShader("app/RasterizedGBuffer.hlsl", "vs_main", nullptr, nvrhi::ShaderType::Vertex);
- pipelineDesc.PS = m_ShaderFactory->CreateShader("app/RasterizedGBuffer.hlsl", "ps_main", ¯os, nvrhi::ShaderType::Pixel);
+ pipelineDesc.bindingLayouts = { m_bindingLayout, m_bindlessLayout };
+ pipelineDesc.VS = m_shaderFactory->CreateShader("app/RasterizedGBuffer.hlsl", "vs_main", nullptr, nvrhi::ShaderType::Vertex);
+ pipelineDesc.PS = m_shaderFactory->CreateShader("app/RasterizedGBuffer.hlsl", "ps_main", ¯os, nvrhi::ShaderType::Pixel);
pipelineDesc.primType = nvrhi::PrimitiveType::TriangleList;
pipelineDesc.renderState.rasterState.frontCounterClockwise = true;
pipelineDesc.renderState.rasterState.cullMode = nvrhi::RasterCullMode::Back;
@@ -223,13 +223,13 @@ void RasterizedGBufferPass::CreatePipeline(const RenderTargets& renderTargets)
auto* framebuffer = renderTargets.GBufferFramebuffer->GetFramebuffer(nvrhi::AllSubresources);
- m_OpaquePipeline = m_Device->createGraphicsPipeline(pipelineDesc, framebuffer);
+ m_opaquePipeline = m_device->createGraphicsPipeline(pipelineDesc, framebuffer);
macros[0].definition = "1"; // ALPHA_TESTED
- pipelineDesc.PS = m_ShaderFactory->CreateShader("app/RasterizedGBuffer.hlsl", "ps_main", ¯os, nvrhi::ShaderType::Pixel);
+ pipelineDesc.PS = m_shaderFactory->CreateShader("app/RasterizedGBuffer.hlsl", "ps_main", ¯os, nvrhi::ShaderType::Pixel);
pipelineDesc.renderState.rasterState.cullMode = nvrhi::RasterCullMode::None;
- m_AlphaTestedPipeline = m_Device->createGraphicsPipeline(pipelineDesc, framebuffer);
+ m_alphaTestedPipeline = m_device->createGraphicsPipeline(pipelineDesc, framebuffer);
}
void RasterizedGBufferPass::Render(
@@ -255,7 +255,7 @@ void RasterizedGBufferPass::Render(
constants.textureGradientScale = powf(2.f, settings.textureLodBias);
constants.materialReadbackBufferIndex = ProfilerSection::MaterialReadback * 2;
constants.materialReadbackPosition = (settings.enableMaterialReadback) ? settings.materialReadbackPosition : int2(-1, -1);
- commandList->writeBuffer(m_ConstantBuffer, &constants, sizeof(constants));
+ commandList->writeBuffer(m_constantBuffer, &constants, sizeof(constants));
nvrhi::IFramebuffer* framebuffer = renderTargets.GBufferFramebuffer->GetFramebuffer(nvrhi::AllSubresources);
@@ -263,7 +263,7 @@ void RasterizedGBufferPass::Render(
commandList->setResourceStatesForFramebuffer(framebuffer);
commandList->commitBarriers();
- const auto& instances = m_Scene->GetSceneGraph()->GetMeshInstances();
+ const auto& instances = m_scene->GetSceneGraph()->GetMeshInstances();
const auto viewFrustum = view.GetViewFrustum();
@@ -273,8 +273,8 @@ void RasterizedGBufferPass::Render(
break;
nvrhi::GraphicsState state;
- state.pipeline = alphaTested ? m_AlphaTestedPipeline : m_OpaquePipeline;
- state.bindings = { m_BindingSet, m_Scene->GetDescriptorTable() };
+ state.pipeline = alphaTested ? m_alphaTestedPipeline : m_opaquePipeline;
+ state.bindings = { m_bindingSet, m_scene->GetDescriptorTable() };
state.framebuffer = framebuffer;
state.viewport = view.GetViewportState();
commandList->setGraphicsState(state);
@@ -317,8 +317,8 @@ void RasterizedGBufferPass::Render(
}
PostprocessGBufferPass::PostprocessGBufferPass(nvrhi::IDevice* device, std::shared_ptr shaderFactory)
- : m_Device(device)
- , m_ShaderFactory(std::move(shaderFactory))
+ : m_device(device)
+ , m_shaderFactory(std::move(shaderFactory))
{
nvrhi::BindingLayoutDesc globalBindingLayoutDesc;
globalBindingLayoutDesc.visibility = nvrhi::ShaderType::Compute;
@@ -330,18 +330,18 @@ PostprocessGBufferPass::PostprocessGBufferPass(nvrhi::IDevice* device, std::shar
nvrhi::BindingLayoutItem::Texture_SRV(1)
};
- m_BindingLayout = m_Device->createBindingLayout(globalBindingLayoutDesc);
+ m_bindingLayout = m_device->createBindingLayout(globalBindingLayoutDesc);
}
void PostprocessGBufferPass::CreatePipeline()
{
- m_ComputeShader = m_ShaderFactory->CreateShader("app/PostprocessGBuffer.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
+ m_computeShader = m_shaderFactory->CreateShader("app/PostprocessGBuffer.hlsl", "main", nullptr, nvrhi::ShaderType::Compute);
auto pipelineDesc = nvrhi::ComputePipelineDesc()
- .setComputeShader(m_ComputeShader)
- .addBindingLayout(m_BindingLayout);
+ .setComputeShader(m_computeShader)
+ .addBindingLayout(m_bindingLayout);
- m_ComputePipeline = m_Device->createComputePipeline(pipelineDesc);
+ m_computePipeline = m_device->createComputePipeline(pipelineDesc);
}
void PostprocessGBufferPass::CreateBindingSet(const RenderTargets& renderTargets)
@@ -357,20 +357,20 @@ void PostprocessGBufferPass::CreateBindingSet(const RenderTargets& renderTargets
nvrhi::BindingSetItem::Texture_SRV(1, currentFrame ? renderTargets.Depth : renderTargets.PrevDepth)
};
- const nvrhi::BindingSetHandle bindingSet = m_Device->createBindingSet(bindingSetDesc, m_BindingLayout);
+ const nvrhi::BindingSetHandle bindingSet = m_device->createBindingSet(bindingSetDesc, m_bindingLayout);
if (currentFrame)
- m_BindingSet = bindingSet;
+ m_bindingSet = bindingSet;
else
- m_PrevBindingSet = bindingSet;
+ m_prevBindingSet = bindingSet;
}
}
void PostprocessGBufferPass::Render(nvrhi::ICommandList* commandList, const donut::engine::IView& view)
{
auto state = nvrhi::ComputeState()
- .setPipeline(m_ComputePipeline)
- .addBindingSet(m_BindingSet);
+ .setPipeline(m_computePipeline)
+ .addBindingSet(m_bindingSet);
commandList->setComputeState(state);
commandList->dispatch(
@@ -380,5 +380,5 @@ void PostprocessGBufferPass::Render(nvrhi::ICommandList* commandList, const donu
void PostprocessGBufferPass::NextFrame()
{
- std::swap(m_BindingSet, m_PrevBindingSet);
+ std::swap(m_bindingSet, m_prevBindingSet);
}
diff --git a/src/GBufferPass.h b/Samples/FullSample/Source/RenderPasses/GBufferPass.h
similarity index 69%
rename from src/GBufferPass.h
rename to Samples/FullSample/Source/RenderPasses/GBufferPass.h
index c480188..87ef5f7 100644
--- a/src/GBufferPass.h
+++ b/Samples/FullSample/Source/RenderPasses/GBufferPass.h
@@ -47,24 +47,7 @@ struct GBufferSettings
class RaytracedGBufferPass
{
-private:
- nvrhi::DeviceHandle m_Device;
-
- RayTracingPass m_Pass;
- nvrhi::BindingLayoutHandle m_BindingLayout;
- nvrhi::BindingLayoutHandle m_BindlessLayout;
- nvrhi::BindingSetHandle m_BindingSet;
- nvrhi::BindingSetHandle m_PrevBindingSet;
-
- nvrhi::BufferHandle m_ConstantBuffer;
-
- std::shared_ptr m_ShaderFactory;
- std::shared_ptr m_CommonPasses;
- std::shared_ptr m_Scene;
- std::shared_ptr m_Profiler;
-
public:
-
RaytracedGBufferPass(
nvrhi::IDevice* device,
std::shared_ptr shaderFactory,
@@ -87,25 +70,26 @@ class RaytracedGBufferPass
const GBufferSettings& settings);
void NextFrame();
-};
-class RasterizedGBufferPass
-{
private:
- nvrhi::DeviceHandle m_Device;
+ nvrhi::DeviceHandle m_device;
+
+ RayTracingPass m_pass;
+ nvrhi::BindingLayoutHandle m_bindingLayout;
+ nvrhi::BindingLayoutHandle m_bindlessLayout;
+ nvrhi::BindingSetHandle m_bindingSet;
+ nvrhi::BindingSetHandle m_prevBindingSet;
- nvrhi::GraphicsPipelineHandle m_OpaquePipeline;
- nvrhi::GraphicsPipelineHandle m_AlphaTestedPipeline;
- nvrhi::BindingLayoutHandle m_BindingLayout;
- nvrhi::BindingLayoutHandle m_BindlessLayout;
- nvrhi::BindingSetHandle m_BindingSet;
+ nvrhi::BufferHandle m_constantBuffer;
- nvrhi::BufferHandle m_ConstantBuffer;
+ std::shared_ptr m_shaderFactory;
+ std::shared_ptr m_commonPasses;
+ std::shared_ptr m_scene;
+ std::shared_ptr m_profiler;
+};
- std::shared_ptr m_ShaderFactory;
- std::shared_ptr m_CommonPasses;
- std::shared_ptr m_Scene;
- std::shared_ptr m_Profiler;
+class RasterizedGBufferPass
+{
public:
RasterizedGBufferPass(
nvrhi::IDevice* device,
@@ -125,24 +109,27 @@ class RasterizedGBufferPass
const donut::engine::IView& viewPrev,
const RenderTargets& renderTargets,
const GBufferSettings& settings);
+
+private:
+ nvrhi::DeviceHandle m_device;
+
+ nvrhi::GraphicsPipelineHandle m_opaquePipeline;
+ nvrhi::GraphicsPipelineHandle m_alphaTestedPipeline;
+ nvrhi::BindingLayoutHandle m_bindingLayout;
+ nvrhi::BindingLayoutHandle m_bindlessLayout;
+ nvrhi::BindingSetHandle m_bindingSet;
+
+ nvrhi::BufferHandle m_constantBuffer;
+
+ std::shared_ptr m_shaderFactory;
+ std::shared_ptr m_commonPasses;
+ std::shared_ptr m_scene;
+ std::shared_ptr m_profiler;
};
class PostprocessGBufferPass
{
-private:
- nvrhi::DeviceHandle m_Device;
-
- nvrhi::ShaderHandle m_ComputeShader;
- nvrhi::ComputePipelineHandle m_ComputePipeline;
- nvrhi::BindingLayoutHandle m_BindingLayout;
- nvrhi::BindingLayoutHandle m_BindlessLayout;
- nvrhi::BindingSetHandle m_BindingSet;
- nvrhi::BindingSetHandle m_PrevBindingSet;
-
- std::shared_ptr m_ShaderFactory;
-
public:
-
PostprocessGBufferPass(
nvrhi::IDevice* device,
std::shared_ptr shaderFactory);
@@ -157,4 +144,16 @@ class PostprocessGBufferPass
const donut::engine::IView& view);
void NextFrame();
+
+private:
+ nvrhi::DeviceHandle m_device;
+
+ nvrhi::ShaderHandle m_computeShader;
+ nvrhi::ComputePipelineHandle m_computePipeline;
+ nvrhi::BindingLayoutHandle m_bindingLayout;
+ nvrhi::BindingLayoutHandle m_bindlessLayout;
+ nvrhi::BindingSetHandle m_bindingSet;
+ nvrhi::BindingSetHandle m_prevBindingSet;
+
+ std::shared_ptr m_shaderFactory;
};
\ No newline at end of file
diff --git a/src/GenerateMipsPass.cpp b/Samples/FullSample/Source/RenderPasses/GenerateMipsPass.cpp
similarity index 86%
rename from src/GenerateMipsPass.cpp
rename to Samples/FullSample/Source/RenderPasses/GenerateMipsPass.cpp
index b362b8c..7c4c56c 100644
--- a/src/GenerateMipsPass.cpp
+++ b/Samples/FullSample/Source/RenderPasses/GenerateMipsPass.cpp
@@ -17,19 +17,19 @@
using namespace donut::math;
-#include "../shaders/ShaderParameters.h"
+#include "../../shaders/ShaderParameters.h"
GenerateMipsPass::GenerateMipsPass(
nvrhi::IDevice* device,
std::shared_ptr shaderFactory,
nvrhi::ITexture* sourceEnvironmentMap,
nvrhi::ITexture* destinationTexture)
- : m_SourceTexture(sourceEnvironmentMap)
- , m_DestinationTexture(destinationTexture)
+ : m_sourceTexture(sourceEnvironmentMap)
+ , m_destinationTexture(destinationTexture)
{
donut::log::debug("Initializing GenerateMipsPass...");
- const auto& destinationDesc = m_DestinationTexture->getDesc();
+ const auto& destinationDesc = m_destinationTexture->getDesc();
nvrhi::BindingSetDesc bindingSetDesc;
bindingSetDesc.bindings = {
@@ -45,14 +45,14 @@ GenerateMipsPass::GenerateMipsPass(
{
bindingSetDesc.bindings.push_back(nvrhi::BindingSetItem::Texture_UAV(
mipLevel,
- m_DestinationTexture,
+ m_destinationTexture,
nvrhi::Format::UNKNOWN,
nvrhi::TextureSubresourceSet(mipLevel, 1, 0, 1)));
}
nvrhi::BindingLayoutHandle bindingLayout;
nvrhi::utils::CreateBindingSetAndLayout(device, nvrhi::ShaderType::Compute, 0,
- bindingSetDesc, bindingLayout, m_BindingSet);
+ bindingSetDesc, bindingLayout, m_bindingSet);
std::vector