From e7681551a2b85fb0949090fe2cb55463d0baeafb Mon Sep 17 00:00:00 2001 From: dzhdan Date: Thu, 14 Nov 2024 10:49:12 +0800 Subject: [PATCH] v4.11.2: HIGHLIGHTS: - NRD: improved robustness - REBLUR: improvements DETAILS: - NRD: clarified importance and valid usage of "CommonSettings::frameIndex" - NRD: added more debug checks for user provided "CommonSettings" - NRD: "SetCommonSettings" returns "INVALID_ARGUMENT" if validation of user provided "commonSettings" fails. It happens only at the end of the function. The return code is informational and doesn't affect function body. In debug builds a failed check invokes "assert" with a description of the problem - REBLUR: HistoryFix-ed data should not sneak into fast history for low roughness specular (test 115) - REBLUR: roughness based confidence should affect "vmb" max accumulated frames (actually it's a NOP due to fallback to "smb" logic) - Integration: logging goes into files instead of "stdout" - updated deps --- External/MathLib | 2 +- Include/NRD.h | 4 +- Include/NRDSettings.h | 11 ++-- Integration/NRDIntegration.h | 8 ++- Integration/NRDIntegration.hpp | 57 ++++++++++++++----- README.md | 2 +- Resources/Version.h | 2 +- Shaders/Include/REBLUR_HistoryFix.hlsli | 11 +++- .../Include/REBLUR_TemporalAccumulation.hlsli | 16 +++--- Source/InstanceImpl.cpp | 56 +++++++++++++----- 10 files changed, 118 insertions(+), 51 deletions(-) diff --git a/External/MathLib b/External/MathLib index 368dd254..a497a61e 160000 --- a/External/MathLib +++ b/External/MathLib @@ -1 +1 @@ -Subproject commit 368dd2547aa62e4bff38ae923a846b13f7fed68e +Subproject commit a497a61e64ff5f7d78ad988a5565ffdbedbdc894 diff --git a/Include/NRD.h b/Include/NRD.h index 350b0d04..3062f9aa 100644 --- a/Include/NRD.h +++ b/Include/NRD.h @@ -29,8 +29,8 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define NRD_VERSION_MAJOR 4 #define NRD_VERSION_MINOR 11 -#define NRD_VERSION_BUILD 1 -#define NRD_VERSION_DATE "5 November 2024" +#define NRD_VERSION_BUILD 2 +#define NRD_VERSION_DATE "14 November 2024" #if defined(_WIN32) #define NRD_CALL __stdcall diff --git a/Include/NRDSettings.h b/Include/NRDSettings.h index 94956380..32ebf879 100644 --- a/Include/NRDSettings.h +++ b/Include/NRDSettings.h @@ -30,7 +30,7 @@ namespace nrd return (uint32_t)(accumulationTime * fps); } - // Internally, NRD uses the following sequence based on "CommonSettings::frameIndex": + // Sequence is based on "CommonSettings::frameIndex": // Even frame (0) Odd frame (1) ... // B W W B // W B B W @@ -138,7 +138,7 @@ namespace nrd // [0.01; 0.02] - two samples considered occluded if relative distance difference is greater than this slope-scaled threshold float disocclusionThreshold = 0.01f; - // [0.02; 0.2] - an alternative disocclusion threshold, which is mixed to based on: + // (Optional) [0.02; 0.2] - an alternative disocclusion threshold, which is mixed to based on: // - "strandThickness", if there is "strandMaterialID" match // - IN_DISOCCLUSION_THRESHOLD_MIX texture, if "isDisocclusionThresholdMixAvailable = true" (has higher priority and ignores "strandMaterialID") float disocclusionThresholdAlternate = 0.05f; @@ -166,10 +166,13 @@ namespace nrd // IN_DISOCCLUSION_THRESHOLD_MIX and IN_BASECOLOR_METALNESS. Must be manually enabled via NRD_USE_VIEWPORT_OFFSET macro switch uint32_t rectOrigin[2] = {}; - // A consecutive number + // A consecutively growing number. Valid usage: + // - must be incremented by 1 each frame + // - sequence can be restarted after passing "AccumulationMode != CONTINUE" + // - must be in sync with "CheckerboardMode" (if not OFF) uint32_t frameIndex = 0; - // To reset history set to RESTART / CLEAR_AND_RESTART for one frame + // To reset history set to RESTART or CLEAR_AND_RESTART for one frame AccumulationMode accumulationMode = AccumulationMode::CONTINUE; // If "true" IN_MV is 3D motion in world-space (0 should be everywhere if the scene is static, camera motion must not be included), diff --git a/Integration/NRDIntegration.h b/Integration/NRDIntegration.h index 386500ba..ce9ec3c2 100644 --- a/Integration/NRDIntegration.h +++ b/Integration/NRDIntegration.h @@ -21,10 +21,11 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #include #include #include +#include #define NRD_INTEGRATION_MAJOR 1 -#define NRD_INTEGRATION_MINOR 13 -#define NRD_INTEGRATION_DATE "7 October 2024" +#define NRD_INTEGRATION_MINOR 14 +#define NRD_INTEGRATION_DATE "14 November 2024" #define NRD_INTEGRATION 1 // Debugging @@ -138,6 +139,7 @@ class Integration nri::Device* m_Device = nullptr; nri::Buffer* m_ConstantBuffer = nullptr; nri::Descriptor* m_ConstantBufferView = nullptr; + FILE* m_Log = nullptr; Instance* m_Instance = nullptr; uint64_t m_PermanentPoolSize = 0; uint64_t m_TransientPoolSize = 0; @@ -145,7 +147,7 @@ class Integration uint32_t m_ConstantBufferViewSize = 0; uint32_t m_ConstantBufferOffset = 0; uint32_t m_DescriptorPoolIndex = 0; - uint32_t m_FrameIndex = 0; + uint32_t m_FrameIndex = uint32_t(-1); // 0 needed after 1st "NewFrame" uint8_t m_BufferedFramesNum = 0; char m_Name[32] = {}; bool m_ReloadShaders = false; diff --git a/Integration/NRDIntegration.hpp b/Integration/NRDIntegration.hpp index 7bb28169..1f00b1d8 100644 --- a/Integration/NRDIntegration.hpp +++ b/Integration/NRDIntegration.hpp @@ -124,6 +124,14 @@ bool Integration::Initialize(const IntegrationCreationDesc& integrationDesc, con strncpy(m_Name, integrationDesc.name, sizeof(m_Name)); +#if( NRD_INTEGRATION_DEBUG_LOGGING == 1 ) + char filename[128]; + snprintf(filename, sizeof(filename), "NRD-%s.log", m_Name); + m_Log = fopen(filename, "w"); + if (m_Log) + fprintf(m_Log, "Resource size = %u x %u\n", integrationDesc.resourceWidth, integrationDesc.resourceHeight); +#endif + CreatePipelines(); CreateResources(integrationDesc.resourceWidth, integrationDesc.resourceHeight); @@ -316,7 +324,7 @@ void Integration::CreateResources(uint16_t resourceWidth, uint16_t resourceHeigh uint16_t w = DivideUp(resourceWidth, nrdTextureDesc.downsampleFactor); uint16_t h = DivideUp(resourceHeight, nrdTextureDesc.downsampleFactor); - + nri::TextureDesc textureDesc = {}; textureDesc.type = nri::TextureType::TEXTURE_2D; textureDesc.usage = nri::TextureUsageBits::SHADER_RESOURCE | nri::TextureUsageBits::SHADER_RESOURCE_STORAGE; @@ -330,9 +338,9 @@ void Integration::CreateResources(uint16_t resourceWidth, uint16_t resourceHeigh char name[128]; if (i < instanceDesc.permanentPoolSize) - snprintf(name, sizeof(name), "%s::PermamentPool%u", m_Name, i); + snprintf(name, sizeof(name), "%s::P(%u)", m_Name, i); else - snprintf(name, sizeof(name), "%s::TransientPool%u", m_Name, i - instanceDesc.permanentPoolSize); + snprintf(name, sizeof(name), "%s::T(%u)", m_Name, i - instanceDesc.permanentPoolSize); m_NRI->SetTextureDebugName(*texture, name); // Construct NRD texture @@ -349,12 +357,14 @@ void Integration::CreateResources(uint16_t resourceWidth, uint16_t resourceHeigh m_TransientPoolSize += memoryDesc.size; #if( NRD_INTEGRATION_DEBUG_LOGGING == 1 ) - printf("%s format=%u downsampleFactor=%u\n", name, nrdTextureDesc.format, nrdTextureDesc.downsampleFactor); + if (m_Log) + fprintf(m_Log, "%s\n\tformat=%u downsampleFactor=%u\n", name, nrdTextureDesc.format, nrdTextureDesc.downsampleFactor); #endif } #if( NRD_INTEGRATION_DEBUG_LOGGING == 1 ) - printf("%s: %.1f Mb (permanent), %.1f Mb (transient)\n\n", m_Name, double(m_PermanentPoolSize) / (1024.0f * 1024.0f), double(m_TransientPoolSize) / (1024.0f * 1024.0f)); + if (m_Log) + fprintf(m_Log, "%.1f Mb (permanent), %.1f Mb (transient)\n\n", double(m_PermanentPoolSize) / (1024.0f * 1024.0f), double(m_TransientPoolSize) / (1024.0f * 1024.0f)); #endif // Samplers @@ -407,6 +417,11 @@ void Integration::CreateResources(uint16_t resourceWidth, uint16_t resourceHeigh m_DescriptorSetSamplers.push_back(nullptr); m_DescriptorsInFlight.push_back({}); } + +#if( NRD_INTEGRATION_DEBUG_LOGGING == 1 ) + if (m_Log) + fflush(m_Log); +#endif } void Integration::AllocateAndBindMemory() @@ -440,8 +455,12 @@ void Integration::NewFrame() NRD_INTEGRATION_ASSERT(m_Instance, "Uninitialized! Did you forget to call 'Initialize'?"); #if( NRD_INTEGRATION_DEBUG_LOGGING == 1 ) - printf("%s (frame %u) ==============================================================================\n\n", m_Name, m_FrameIndex); - #endif + if (m_Log) + { + fflush(m_Log); + fprintf(m_Log, "(frame %u) ==============================================================================\n\n", m_FrameIndex); + } +#endif m_DescriptorPoolIndex = m_FrameIndex % m_BufferedFramesNum; nri::DescriptorPool* descriptorPool = m_DescriptorPools[m_DescriptorPoolIndex]; @@ -491,7 +510,7 @@ void Integration::Denoise(const Identifier* denoisers, uint32_t denoisersNum, nr const nri::Texture* normalRoughnessTexture = userPool[(size_t)ResourceType::IN_NORMAL_ROUGHNESS]->texture; const nri::TextureDesc& normalRoughnessDesc = m_NRI->GetTextureDesc(*normalRoughnessTexture); const LibraryDesc& nrdLibraryDesc = GetLibraryDesc(); - + bool isNormalRoughnessFormatValid = false; switch(nrdLibraryDesc.normalEncoding) { @@ -685,24 +704,27 @@ void Integration::Dispatch(nri::CommandBuffer& commandBuffer, nri::DescriptorPoo m_NRI->CmdDispatch(commandBuffer, {dispatchDesc.gridWidth, dispatchDesc.gridHeight, 1}); // Debug logging - #if( NRD_INTEGRATION_DEBUG_LOGGING == 1 ) - printf("Pipeline #%u : %s\n\t", dispatchDesc.pipelineIndex, dispatchDesc.name); +#if( NRD_INTEGRATION_DEBUG_LOGGING == 1 ) + if (m_Log) + { + fprintf(m_Log, "Pipeline #%u : %s\n\t", dispatchDesc.pipelineIndex, dispatchDesc.name); for( uint32_t i = 0; i < dispatchDesc.resourcesNum; i++ ) { const ResourceDesc& r = dispatchDesc.resources[i]; if( r.type == ResourceType::PERMANENT_POOL ) - printf("P(%u) ", r.indexInPool); + fprintf(m_Log, "P(%u) ", r.indexInPool); else if( r.type == ResourceType::TRANSIENT_POOL ) - printf("T(%u) ", r.indexInPool); + fprintf(m_Log, "T(%u) ", r.indexInPool); else { const char* s = GetResourceTypeString(r.type); - printf("%s ", s); + fprintf(m_Log, "%s ", s); } } - printf("\n\n"); - #endif + fprintf(m_Log, "\n\n"); + } +#endif } void Integration::Destroy() @@ -764,6 +786,11 @@ void Integration::Destroy() m_FrameIndex = 0; m_ReloadShaders = false; m_EnableDescriptorCaching = false; + +#if( NRD_INTEGRATION_DEBUG_LOGGING == 1 ) + if (m_Log) + fclose(m_Log); +#endif } } diff --git a/README.md b/README.md index 2e167fa4..0c374a1a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NVIDIA REAL-TIME DENOISERS v4.11.1 (NRD) +# NVIDIA REAL-TIME DENOISERS v4.11.2 (NRD) [![Build NRD SDK](https://github.com/NVIDIAGameWorks/RayTracingDenoiser/actions/workflows/build.yml/badge.svg)](https://github.com/NVIDIAGameWorks/RayTracingDenoiser/actions/workflows/build.yml) diff --git a/Resources/Version.h b/Resources/Version.h index bde8e627..01212754 100644 --- a/Resources/Version.h +++ b/Resources/Version.h @@ -23,6 +23,6 @@ Versioning rules: #define VERSION_MAJOR 4 #define VERSION_MINOR 11 -#define VERSION_BUILD 1 +#define VERSION_BUILD 2 #define VERSION_STRING STR(VERSION_MAJOR.VERSION_MINOR.VERSION_BUILD encoding=NRD_NORMAL_ENCODING.NRD_ROUGHNESS_ENCODING) diff --git a/Shaders/Include/REBLUR_HistoryFix.hlsli b/Shaders/Include/REBLUR_HistoryFix.hlsli index 164c6334..17c73190 100644 --- a/Shaders/Include/REBLUR_HistoryFix.hlsli +++ b/Shaders/Include/REBLUR_HistoryFix.hlsli @@ -100,6 +100,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Diffuse #ifdef REBLUR_DIFFUSE + { REBLUR_TYPE diff = gIn_Diff[ pixelPos ]; #ifdef REBLUR_SH float4 diffSh = gIn_DiffSh[ pixelPos ]; @@ -207,7 +208,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float diffM1 = diffCenter; float diffM2 = diffM1 * diffM1; - diffCenter = lerp( GetLuma( diff ), diffCenter, saturate( frameNum.x / ( gHistoryFixFrameNum + NRD_EPS ) ) ); + float f = saturate( frameNum.x / ( gHistoryFixFrameNum + NRD_EPS ) ); + diffCenter = lerp( GetLuma( diff ), diffCenter, f ); gOut_DiffFast[ pixelPos ] = diffCenter; [unroll] @@ -288,10 +290,12 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #ifdef REBLUR_SH gOut_DiffSh[ pixelPos ] = diffSh; #endif + } #endif // Specular #ifdef REBLUR_SPECULAR + { REBLUR_TYPE spec = gIn_Spec[ pixelPos ]; #ifdef REBLUR_SH float4 specSh = gIn_SpecSh[ pixelPos ]; @@ -403,7 +407,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float specM1 = specCenter; float specM2 = specM1 * specM1; - specCenter = lerp( GetLuma( spec ), specCenter, saturate( frameNum.y / ( gHistoryFixFrameNum + NRD_EPS ) ) ); + float f = saturate( frameNum.y / ( gHistoryFixFrameNum + NRD_EPS ) ); + f = lerp( 1.0, f, smc ); // HistoryFix-ed data is undesired in fast history for low roughness ( test 115 ) + specCenter = lerp( GetLuma( spec ), specCenter, f ); gOut_SpecFast[ pixelPos ] = specCenter; [unroll] @@ -484,5 +490,6 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #ifdef REBLUR_SH gOut_SpecSh[ pixelPos ] = specSh; #endif + } #endif } diff --git a/Shaders/Include/REBLUR_TemporalAccumulation.hlsli b/Shaders/Include/REBLUR_TemporalAccumulation.hlsli index bf1c0d60..952ca946 100644 --- a/Shaders/Include/REBLUR_TemporalAccumulation.hlsli +++ b/Shaders/Include/REBLUR_TemporalAccumulation.hlsli @@ -543,9 +543,10 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : normalWeight = lerp( Math::SmoothStep( 1.0, 0.0, vmbPixelsTraveled ), 1.0, normalWeight ); // jitter friendly virtualHistoryNormalBasedConfidence = min( virtualHistoryNormalBasedConfidence, normalWeight ); - // Virtual history amount - normal confidence ( tests 9e, 65, 66, 107, 111, 132 ) - // IMPORTANT: this is currently needed for bumpy surfaces, because virtual motion gets ruined by big curvature - float virtualHistoryAmount = virtualHistoryNormalBasedConfidence; + // Virtual history amount + // Tests 65, 66, 103, 107, 111, 132, e9, e11 + float virtualHistoryAmount = Math::SmoothStep( 0.05, 0.95, Dfactor ); + virtualHistoryAmount *= virtualHistoryNormalBasedConfidence; // helps on bumpy surfaces, because virtual motion gets ruined by big curvature // Virtual motion - virtual parallax difference // Tests 3, 6, 8, 11, 14, 100, 103, 104, 106, 109, 110, 114, 120, 127, 130, 131, 132, 138, 139 and 9e @@ -600,6 +601,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float virtualHistoryConfidenceForSmbRelaxation = virtualHistoryNormalBasedConfidence * virtualHistoryRoughnessBasedConfidence; float virtualHistoryConfidence = virtualHistoryNormalBasedConfidence * virtualHistoryRoughnessBasedConfidence * virtualHistoryParallaxBasedConfidence; + virtualHistoryAmount *= virtualHistoryRoughnessBasedConfidence; // helps to preserve roughness details, which lies on surfaces + // Sample surface history REBLUR_TYPE smbSpecHistory; REBLUR_FAST_TYPE smbSpecFastHistory; @@ -664,8 +667,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Virtual motion: max allowed frames float vmbMaxFrameNum = gMaxAccumulatedFrameNum; - vmbMaxFrameNum *= virtualHistoryParallaxBasedConfidence; - vmbMaxFrameNum *= virtualHistoryNormalBasedConfidence; + vmbMaxFrameNum *= virtualHistoryConfidence; // previously was just "virtualHistoryParallaxBasedConfidence * virtualHistoryNormalBasedConfidence" vmbMaxFrameNum = min( vmbMaxFrameNum, maxResponsiveFrameNum.y ); // Limit number of accumulated frames @@ -673,10 +675,6 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : smbSpecAccumSpeed = min( smbSpecAccumSpeed, smbMaxFrameNum ); vmbSpecAccumSpeed = min( vmbSpecAccumSpeed, vmbMaxFrameNum ); - // Virtual history amount - other ( tests 65, 66, 103, 111, 132, e9, e11 ) - virtualHistoryAmount *= Math::SmoothStep( 0.05, 0.95, Dfactor ); - virtualHistoryAmount *= virtualHistoryRoughnessBasedConfidence; - // Fallback to "smb" if "vmb" history is short // *** // Interactive comparison of two methods: https://www.desmos.com/calculator/syocjyk9wc // TODO: the amount gets shifted heavily towards "smb" if "smb" > "vmb" even by 5 frames diff --git a/Source/InstanceImpl.cpp b/Source/InstanceImpl.cpp index ad846c02..86d0aef0 100644 --- a/Source/InstanceImpl.cpp +++ b/Source/InstanceImpl.cpp @@ -268,18 +268,48 @@ nrd::Result nrd::InstanceImpl::Create(const InstanceCreationDesc& instanceCreati nrd::Result nrd::InstanceImpl::SetCommonSettings(const CommonSettings& commonSettings) { - // TODO: matrix verifications? return INVALID_ARGUMENT? - assert("'viewZScale' can't be <= 0" && commonSettings.viewZScale > 0.0f); - assert("'resourceSize' can't be 0" && commonSettings.resourceSize[0] != 0 && commonSettings.resourceSize[1] != 0); - assert("'resourceSizePrev' can't be 0" && commonSettings.resourceSizePrev[0] != 0 && commonSettings.resourceSizePrev[1] != 0); - assert("'rectSize' can't be 0" && commonSettings.rectSize[0] != 0 && commonSettings.rectSize[1] != 0); - assert("'rectSizePrev' can't be 0" && commonSettings.rectSizePrev[0] != 0 && commonSettings.rectSizePrev[1] != 0); - assert("'mvScale.xy' can't be 0" && ((commonSettings.motionVectorScale[0] != 0.0f && commonSettings.motionVectorScale[1] != 0.0f) || commonSettings.isMotionVectorInWorldSpace)); - assert("'cameraJitter' must be in range [-0.5; 0.5]" && commonSettings.cameraJitter[0] >= -0.5f && commonSettings.cameraJitter[0] <= 0.5f && commonSettings.cameraJitter[1] >= -0.5f && commonSettings.cameraJitter[1] <= 0.5f); - assert("'cameraJitterPrev' must be in range [-0.5; 0.5]" && commonSettings.cameraJitterPrev[0] >= -0.5f && commonSettings.cameraJitterPrev[0] <= 0.5f && commonSettings.cameraJitterPrev[1] >= -0.5f && commonSettings.cameraJitterPrev[1] <= 0.5f); - assert("'denoisingRange' must be >= 0" && commonSettings.denoisingRange > 0.0f); - assert("'disocclusionThreshold' must be > 0" && commonSettings.disocclusionThreshold > 0.0f); - assert("'disocclusionThresholdAlternate' must be > 0" && commonSettings.disocclusionThresholdAlternate > 0.0f); + // TODO: matrix verifications? + bool isValid = commonSettings.viewZScale > 0.0f; + assert("'viewZScale' can't be <= 0" && isValid); + + isValid &= commonSettings.resourceSize[0] != 0 && commonSettings.resourceSize[1] != 0; + assert("'resourceSize' can't be 0" && isValid); + + isValid &= commonSettings.resourceSizePrev[0] != 0 && commonSettings.resourceSizePrev[1] != 0; + assert("'resourceSizePrev' can't be 0" && isValid); + + isValid &= commonSettings.rectSize[0] != 0 && commonSettings.rectSize[1] != 0; + assert("'rectSize' can't be 0" && isValid); + + isValid &= commonSettings.rectSizePrev[0] != 0 && commonSettings.rectSizePrev[1] != 0; + assert("'rectSizePrev' can't be 0" && isValid); + + isValid &= ((commonSettings.motionVectorScale[0] != 0.0f && commonSettings.motionVectorScale[1] != 0.0f) || commonSettings.isMotionVectorInWorldSpace); + assert("'mvScale.xy' can't be 0" && isValid); + + isValid &= commonSettings.cameraJitter[0] >= -0.5f && commonSettings.cameraJitter[0] <= 0.5f && commonSettings.cameraJitter[1] >= -0.5f && commonSettings.cameraJitter[1] <= 0.5f; + assert("'cameraJitter' must be in range [-0.5; 0.5]" && isValid); + + isValid &= commonSettings.cameraJitterPrev[0] >= -0.5f && commonSettings.cameraJitterPrev[0] <= 0.5f && commonSettings.cameraJitterPrev[1] >= -0.5f && commonSettings.cameraJitterPrev[1] <= 0.5f; + assert("'cameraJitterPrev' must be in range [-0.5; 0.5]" && isValid); + + isValid &= commonSettings.denoisingRange > 0.0f; + assert("'denoisingRange' must be >= 0" && isValid); + + isValid &= commonSettings.disocclusionThreshold > 0.0f; + assert("'disocclusionThreshold' must be > 0" && isValid); + + isValid &= commonSettings.disocclusionThresholdAlternate > 0.0f; + assert("'disocclusionThresholdAlternate' must be > 0" && isValid); + + isValid &= commonSettings.accumulationMode != AccumulationMode::CONTINUE || commonSettings.frameIndex == m_CommonSettings.frameIndex + 1 || m_IsFirstUse; + assert("'frameIndex' must be a consecutively growing number" && isValid); + + isValid &= commonSettings.strandMaterialID != 0.0f || GetLibraryDesc().normalEncoding == NormalEncoding::R10_G10_B10_A2_UNORM; + assert("'strandMaterialID' can't be 0 if material ID is not supported by encoding" && isValid); + + isValid &= commonSettings.cameraAttachedReflectionMaterialID != 0.0f || GetLibraryDesc().normalEncoding == NormalEncoding::R10_G10_B10_A2_UNORM; + assert("'cameraAttachedReflectionMaterialID' can't be 0 if material ID is not supported by encoding" && isValid); memcpy(&m_CommonSettings, &commonSettings, sizeof(commonSettings)); @@ -425,7 +455,7 @@ nrd::Result nrd::InstanceImpl::SetCommonSettings(const CommonSettings& commonSet float nonLinearAccumSpeed = FPS * 0.25f / (1.0f + FPS * 0.25f); m_CheckerboardResolveAccumSpeed = lerp(nonLinearAccumSpeed, 0.5f, m_JitterDelta); - return Result::SUCCESS; + return isValid ? Result::SUCCESS : Result::INVALID_ARGUMENT; } nrd::Result nrd::InstanceImpl::SetDenoiserSettings(Identifier identifier, const void* denoiserSettings)