Skip to content

Commit fcab2ee

Browse files
committed
Merge branch 'pkristof/nrcEmissives' into 'main'
[REMIX-5073][REMIX-3471][REMIX-3686][GH:128] Added Boost Emissives option to NRC to fix missing emissive lighting on indirect bounces with NRC Direct Lighting enabled See merge request lightspeedrtx/dxvk-remix-nv!2022
2 parents a03c16d + 38c93b9 commit fcab2ee

5 files changed

Lines changed: 30 additions & 3 deletions

File tree

RtxOptions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ This file is auto-generated by RTX Remix. To regenerate it, run Remix with `DXVK
394394
|rtx.neeCache.uniformSamplingProbability|float|0.1|||Uniform sampling probability\.|
395395
|rtx.neuralRadianceCache.allowRussianRouletteOnUpdate|bool|False||||
396396
|rtx.neuralRadianceCache.averageTrainingBouncesPerPath|float|2.15|||Average number of bounces per path used to calculate max training dimensions\.<br>Lower values result in higher max training dimensions and higher memory requirements by NRC\.<br>Lower values boost training dimensions to allows for more training records to get generated in scenes with very few / 1\-2 bounces<br>\(i\.e\. most of the view being into the sky with small geometric footprint on\-screen\)\.<br>|
397+
|rtx.neuralRadianceCache.boostEmissives|bool|True|||Preserves emissive lighting on indirect bounces where NRC would otherwise terminate the path before evaluating it\.<br>When Include Direct Lighting is enabled, NRC terminates paths immediately on cache hit, skipping emissive evaluation\.<br>The cache cannot accurately represent sharp emissive features, so this option defers termination<br>until after MIS\-weighted emissive accumulation\. May cause minor double\-counting in rare cases\.|
397398
|rtx.neuralRadianceCache.clearBuffersOnFrameStart|bool|False|||Clears buffers for NRC before they are written to by the the Pathtracer\.|
398399
|rtx.neuralRadianceCache.debugResolveMode|int|0|||Debug Visualization Mode\.|
399400
|rtx.neuralRadianceCache.enableAdaptiveTrainingDimensions|bool|True|||Enables adaptive training dimensions that scale based off pathtracer's execution behavior on a given scene\.|

src/dxvk/rtx_render/rtx_neural_radiance_cache.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ namespace dxvk {
285285

286286
RemixGui::Checkbox("Learn Irradiance", &NrcOptions::learnIrradianceObject());
287287
RemixGui::Checkbox("Include Direct Lighting", &NrcOptions::includeDirectLightingObject());
288+
RemixGui::Checkbox("Boost Emissives", &NrcOptions::boostEmissivesObject());
288289

289290
RemixGui::DragInt("Max Number of Training Iterations", &NrcOptions::maxNumTrainingIterationsObject(), 1.f, 1, 16, "%d", ImGuiSliderFlags_AlwaysClamp);
290291
RemixGui::DragInt("Target Number of Training Iterations", &NrcOptions::targetNumTrainingIterationsObject(), 1.f, 1, 16, "%d", ImGuiSliderFlags_AlwaysClamp);
@@ -488,6 +489,8 @@ namespace dxvk {
488489
}
489490

490491
nrcArgs.trainingLuminanceClamp = NrcOptions::luminanceClampMultiplier() * NrcOptions::maxExpectedAverageRadianceValue();
492+
493+
nrcArgs.boostEmissives = NrcOptions::boostEmissives();
491494
}
492495

493496
const Vector2& NeuralRadianceCache::getNumQueryPixelsPerTrainingPixel() const {

src/dxvk/rtx_render/rtx_neural_radiance_cache.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ namespace dxvk {
5252

5353
RTX_OPTION("rtx.neuralRadianceCache", bool, learnIrradiance, true, "");
5454
RTX_OPTION_ENV("rtx.neuralRadianceCache", bool, includeDirectLighting, true, "RTX_NRC_INCLUDE_DIRECT_LIGHTING", "");
55+
RTX_OPTION("rtx.neuralRadianceCache", bool, boostEmissives, true,
56+
"Preserves emissive lighting on indirect bounces where NRC would otherwise terminate the path before evaluating it.\n"
57+
"When Include Direct Lighting is enabled, NRC terminates paths immediately on cache hit, skipping emissive evaluation.\n"
58+
"The cache cannot accurately represent sharp emissive features, so this option defers termination\n"
59+
"until after MIS-weighted emissive accumulation. May cause minor double-counting in rare cases.");
5560
RTX_OPTION("rtx.neuralRadianceCache", bool, resetHistory, false, "");
5661
RTX_OPTION("rtx.neuralRadianceCache", bool, allowRussianRouletteOnUpdate, false, "");
5762
RTX_OPTION_ARGS("rtx.neuralRadianceCache", uint32_t, targetNumTrainingIterations, 4,

src/dxvk/shaders/rtx/algorithm/integrator_indirect.slangh

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,8 @@ void integratePathVertex(
396396
{
397397
nrcProgressState = updateNrcOnHit(pathState, surfaceInteraction, polymorphicSurfaceMaterialInteraction);
398398

399-
if (nrcProgressState == NrcProgressState::TerminateImmediately)
399+
// Terminate prior to resolving surface's emissive contribution if NRC indicates so and boostEmissives is not enabled.
400+
if (nrcProgressState == NrcProgressState::TerminateImmediately && !cb.nrcArgs.boostEmissives)
400401
{
401402
pathState.continuePath = false;
402403
return;
@@ -434,8 +435,10 @@ void integratePathVertex(
434435
}
435436

436437
// If the camera index changed then this ray passed through a render target. Cast a ray from the new camera.
437-
if (cb.enableRaytracedRenderTarget && isRaytracedRenderTarget && pathState.bounceIteration == 1)
438-
{
438+
// Note: NRC TerminateImmediately with boostEmissives must take priority as a query record has already been created
439+
if (cb.enableRaytracedRenderTarget && isRaytracedRenderTarget && pathState.bounceIteration == 1
440+
&& !(ENABLE_NRC && nrcProgressState == NrcProgressState::TerminateImmediately))
441+
{
439442
Ray newRay = rayCreateRenderTarget(cb.renderTargetCamera, surfaceInteraction.textureCoordinates, ray);
440443
pathState.origin = newRay.origin;
441444
pathState.direction = newRay.direction;
@@ -513,6 +516,16 @@ void integratePathVertex(
513516
accumulateRadiance(pathState, emissiveLightRadiance);
514517
}
515518

519+
// When boostEmissives is enabled, defer TerminateImmediately until after emissive accumulation
520+
// so that the hit surface's emissive self-emission is properly MIS-weighted.
521+
// Without this, emissive lighting is lost on TerminateImmediately paths (includeDirectLighting=true)
522+
// because NRC's irradiance cache poorly captures sharp emissive features.
523+
if (ENABLE_NRC && nrcProgressState == NrcProgressState::TerminateImmediately && cb.nrcArgs.boostEmissives)
524+
{
525+
pathState.continuePath = false;
526+
return;
527+
}
528+
516529
// We don't need to sample lights or surface rays in the portal closest hit shader
517530
#if (SURFACE_MATERIAL_RESOLVE_TYPE_ACTIVE_MASK & SURFACE_MATERIAL_RESOLVE_TYPE_RAY_PORTAL) != 0
518531
if (materialType == surfaceMaterialTypeOpaque || materialType == surfaceMaterialTypeTranslucent)

src/dxvk/shaders/rtx/pass/nrc_args.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,9 @@ struct NrcArgs {
4646

4747
vec3 sceneBoundsMax;
4848
float trainingLuminanceClamp;
49+
50+
uint boostEmissives;
51+
uint pad0;
52+
uint pad1;
53+
uint pad2;
4954
};

0 commit comments

Comments
 (0)