diff --git a/.args b/.args index f2d9fa4..9f30d59 100644 --- a/.args +++ b/.args @@ -97,7 +97,19 @@ }, { "Command": "--scene=Kitchen/Kitchen.gltf" - } + }, + { + "Command": "--scene=Bistro2/bistro.gltf" + }, + { + "Command": "--scene=LivingRoom/living_room.gltf" + }, + { + "Command": "--scene=TransparentMachines/transparent-machines-pt1.gltf" + }, + { + "Command": "--scene=CornellBox/cornellBox.gltf" + }, ] }, { diff --git a/External/NRD b/External/NRD index ebf92ab..b680731 160000 --- a/External/NRD +++ b/External/NRD @@ -1 +1 @@ -Subproject commit ebf92abd17ec423ca5ef4d7387025c31a9b1b5eb +Subproject commit b68073106b2ef135b826aae772ab5d8aad776d49 diff --git a/External/NRIFramework b/External/NRIFramework index e02328d..92ebca2 160000 --- a/External/NRIFramework +++ b/External/NRIFramework @@ -1 +1 @@ -Subproject commit e02328dbed1d52439bdb3a051316ce8117060d27 +Subproject commit 92ebca20a4419cf896673f6eff9722393d0b5aff diff --git a/Shaders/DlssAfter.cs.hlsl b/Shaders/DlssAfter.cs.hlsl index 8263233..543d253 100644 --- a/Shaders/DlssAfter.cs.hlsl +++ b/Shaders/DlssAfter.cs.hlsl @@ -23,9 +23,8 @@ void main( uint2 pixelPos : SV_DispatchThreadId ) float3 color = gOut_Image[ pixelPos ]; - bool isSrgb = gIsSrgb && ( gOnScreen == SHOW_FINAL || gOnScreen == SHOW_BASE_COLOR ); color = ApplyTonemap( color ); - if( isSrgb ) + if( gIsSrgb ) color = Color::ToSrgb( saturate( color ) ); // Output diff --git a/Shaders/Final.cs.hlsl b/Shaders/Final.cs.hlsl index ef988c0..d998c54 100644 --- a/Shaders/Final.cs.hlsl +++ b/Shaders/Final.cs.hlsl @@ -31,9 +31,8 @@ void main( uint2 pixelPos : SV_DispatchThreadId ) // Noisy input float3 input = gIn_PreAA.SampleLevel( gNearestSampler, pixelUv * gRectSize * gInvRenderSize, 0 ).xyz; - bool isSrgb = gIsSrgb && ( gOnScreen == SHOW_FINAL || gOnScreen == SHOW_BASE_COLOR ); input = ApplyTonemap( input ); - if( isSrgb ) + if( gIsSrgb ) input = Color::ToSrgb( saturate( input ) ); // Split screen - noisy input / denoised output @@ -43,7 +42,7 @@ void main( uint2 pixelPos : SV_DispatchThreadId ) Rng::Hash::Initialize( pixelPos, gFrameIndex ); float rnd = Rng::Hash::GetFloat( ); - result += ( rnd - 0.5 ) / ( isSrgb ? 256.0 : 1024.0 ); + result += ( rnd - 0.5 ) / ( gIsSrgb ? 256.0 : 1024.0 ); // Split screen - vertical line float verticalLine = saturate( 1.0 - abs( pixelUv.x - gSeparator ) * gWindowSize.x / 3.5 ); diff --git a/Shaders/Include/RaytracingShared.hlsli b/Shaders/Include/RaytracingShared.hlsli index 17b50c2..97e9788 100644 --- a/Shaders/Include/RaytracingShared.hlsli +++ b/Shaders/Include/RaytracingShared.hlsli @@ -30,7 +30,7 @@ struct GeometryProps float3 N; float2 uv; float mip; - float tmin; + float hitT; float curvature; uint textureOffsetAndFlags; uint instanceIndex; @@ -53,7 +53,7 @@ struct GeometryProps { return ( ( textureOffsetAndFlags >> 2 ) & 0x1 ) ? float3( 1.0, 0.0, 0.0 ) : float3( 0.0, 1.0, 0.0 ); } bool IsSky( ) - { return tmin == INF; } + { return hitT == INF; } }; float2 GetConeAngleFromAngularRadius( float mip, float tanConeAngle ) @@ -118,12 +118,14 @@ float3 GetSamplingCoords( uint textureIndex, float2 uv, float mip, int mode ) if( instanceData.textureOffsetAndFlags & ( FLAG_STATIC << FLAG_FIRST_BIT ) ) \ mObjectToWorld = ( float3x3 )mOverloaded; \ \ - float flip = Math::Sign( instanceData.invScale ) * ( rayQuery.CandidateTriangleFrontFace( ) ? -1.0 : 1.0 ); \ + float flip = Math::Sign( instanceData.scale ) * ( rayQuery.CandidateTriangleFrontFace( ) ? -1.0 : 1.0 ); \ \ /* Primitive */ \ uint primitiveIndex = instanceData.primitiveOffset + rayQuery.CandidatePrimitiveIndex( ); \ PrimitiveData primitiveData = gIn_PrimitiveData[ primitiveIndex ]; \ \ + float worldArea = primitiveData.worldArea * instanceData.scale * instanceData.scale; \ + \ /* Barycentrics */ \ float3 barycentrics; \ barycentrics.yz = rayQuery.CandidateTriangleBarycentrics( ); \ @@ -141,12 +143,12 @@ float3 GetSamplingCoords( uint textureIndex, float2 uv, float mip, int mode ) N = Geometry::RotateVector( mObjectToWorld, N ); \ N = normalize( N * flip ); \ \ - /* Mip level ( TODO: doesn't take into account integrated AO / SO - i.e. diffuse = lowest mip, but what if we see the sky through a tiny hole? ) */ \ - float NoR = abs( dot( rayQuery.WorldRayDirection( ), N ) ); \ + /* Mip level */ \ + float NoRay = abs( dot( rayQuery.WorldRayDirection( ), N ) ); \ float a = rayQuery.CandidateTriangleRayT( ); \ a *= mipAndCone.y; \ - a *= Math::PositiveRcp( NoR ); \ - a *= primitiveData.worldToUvUnits * abs( instanceData.invScale ); \ + a *= Math::PositiveRcp( NoRay ); \ + a *= sqrt( primitiveData.uvArea / worldArea ); \ \ float mip = log2( a ); \ mip += MAX_MIP_LEVEL; \ @@ -210,19 +212,19 @@ GeometryProps CastRay( float3 origin, float3 direction, float Tmin, float Tmax, while( rayQuery.Proceed( ) ) CheckNonOpaqueTriangle( rayQuery, mipAndCone ); - // TODO: reuse data if committed == candidate (use T to check) + // TODO: reuse data if committed == candidate ( use T to check ) GeometryProps props = ( GeometryProps )0; props.mip = mipAndCone.x; if( rayQuery.CommittedStatus( ) == COMMITTED_NOTHING ) { - props.tmin = INF; - props.X = origin + direction * props.tmin; + props.hitT = INF; + props.X = origin + direction * props.hitT; props.Xprev = props.X; } else { - props.tmin = rayQuery.CommittedRayT( ); + props.hitT = rayQuery.CommittedRayT( ); // Instance uint instanceIndex = rayQuery.CommittedInstanceID( ) + rayQuery.CommittedGeometryIndex( ); @@ -240,12 +242,14 @@ GeometryProps CastRay( float3 origin, float3 direction, float Tmin, float Tmax, if( props.Has( FLAG_STATIC ) ) mObjectToWorld = ( float3x3 )mOverloaded; - float flip = Math::Sign( instanceData.invScale ) * ( rayQuery.CommittedTriangleFrontFace( ) ? -1.0 : 1.0 ); + float flip = Math::Sign( instanceData.scale ) * ( rayQuery.CommittedTriangleFrontFace( ) ? -1.0 : 1.0 ); // Primitive uint primitiveIndex = instanceData.primitiveOffset + rayQuery.CommittedPrimitiveIndex( ); PrimitiveData primitiveData = gIn_PrimitiveData[ primitiveIndex ]; + float worldArea = primitiveData.worldArea * instanceData.scale * instanceData.scale; + // Barycentrics float3 barycentrics; barycentrics.yz = rayQuery.CommittedTriangleBarycentrics( ); @@ -262,14 +266,17 @@ GeometryProps CastRay( float3 origin, float3 direction, float Tmin, float Tmax, props.N = -N; // TODO: why negated? // Curvature - props.curvature = barycentrics.x * primitiveData.curvature0_curvature1.x + barycentrics.y * primitiveData.curvature0_curvature1.y + barycentrics.z * primitiveData.curvature2_bitangentSign.x; - props.curvature /= abs( instanceData.invScale ); - - // Mip level (TODO: doesn't take into account integrated AO / SO - i.e. diffuse = lowest mip, but what if we see the sky through a tiny hole?) - float NoR = abs( dot( direction, props.N ) ); - float a = props.tmin * mipAndCone.y; - a *= Math::PositiveRcp( NoR ); - a *= primitiveData.worldToUvUnits * abs( instanceData.invScale ); + float dnSq0 = Math::LengthSquared( n0 - n1 ); + float dnSq1 = Math::LengthSquared( n1 - n2 ); + float dnSq2 = Math::LengthSquared( n2 - n0 ); + float dnSq = max( dnSq0, max( dnSq1, dnSq2 ) ); + props.curvature = sqrt( dnSq / worldArea ); + + // Mip level + float NoRay = abs( dot( direction, props.N ) ); + float a = props.hitT * mipAndCone.y; + a *= Math::PositiveRcp( NoRay ); + a *= sqrt( primitiveData.uvArea / worldArea ); float mip = log2( a ); mip += MAX_MIP_LEVEL; @@ -287,9 +294,9 @@ GeometryProps CastRay( float3 origin, float3 direction, float Tmin, float Tmax, float3 T = barycentrics.x * t0 + barycentrics.y * t1 + barycentrics.z * t2; T = Geometry::RotateVector( mObjectToWorld, T ); T = normalize( T ); - props.T = float4( T, primitiveData.curvature2_bitangentSign.y ); + props.T = float4( T, primitiveData.bitangentSign_unused.x ); - props.X = origin + direction * props.tmin; + props.X = origin + direction * props.hitT; if( props.Has( FLAG_DEFORMABLE ) ) { MorphedPrimitivePrevPositions prev = gIn_MorphedPrimitivePrevPositions[ instanceData.morphedPrimitiveOffset + rayQuery.CommittedPrimitiveIndex( ) ]; @@ -361,7 +368,10 @@ MaterialProps GetMaterialProps( GeometryProps geometryProps, bool viewIndependen float3 T = geometryProps.T.xyz; // Estimate curvature - float curvature = length( Geometry::UnpackLocalNormal( packedNormal ).xy ) * float( gUseNormalMap ); + float viewZ = Geometry::AffineTransform( gWorldToView, geometryProps.X ).z; + float pixelSize = gUnproject * lerp( abs( viewZ ), 1.0, abs( gOrthoMode ) ); + float localCurvature = length( Geometry::UnpackLocalNormal( packedNormal ).xy ) * float( gUseNormalMap ); + localCurvature /= pixelSize; // Emission coords = GetSamplingCoords( baseTexture + 3, geometryProps.uv, geometryProps.mip, MIP_VISIBILITY ); @@ -501,7 +511,7 @@ MaterialProps GetMaterialProps( GeometryProps geometryProps, bool viewIndependen props.baseColor = baseColor; props.roughness = roughness; props.metalness = metalness; - props.curvature = geometryProps.curvature + curvature; + props.curvature = geometryProps.curvature + localCurvature; return props; } diff --git a/Shaders/Include/Shared.hlsli b/Shaders/Include/Shared.hlsli index 80e48b9..e00d044 100644 --- a/Shaders/Include/Shared.hlsli +++ b/Shaders/Include/Shared.hlsli @@ -200,9 +200,9 @@ struct PrimitiveData float16_t2 t1; float16_t2 t2; - float16_t2 curvature0_curvature1; - float16_t2 curvature2_bitangentSign; - float worldToUvUnits; + float16_t2 bitangentSign_unused; + float worldArea; + float uvArea; }; struct InstanceData @@ -223,7 +223,7 @@ struct InstanceData // TODO: handling object scale embedded into the transformation matrix (assuming uniform scale) // TODO: sign represents triangle winding - float invScale; + float scale; }; //=============================================================== @@ -385,6 +385,11 @@ float GetSpecMagicCurve( float roughness ) return f; } +float ApplyThinLensEquation( float hitDist, float curvature ) +{ + return hitDist / ( 2.0 * curvature * hitDist + 1.0 ); +} + // Returns 3D motion in world space or 2.5D motion in screen space float3 GetMotion( float3 X, float3 Xprev ) { diff --git a/Shaders/SharcUpdate.cs.hlsl b/Shaders/SharcUpdate.cs.hlsl index 71a00f7..67e88ad 100644 --- a/Shaders/SharcUpdate.cs.hlsl +++ b/Shaders/SharcUpdate.cs.hlsl @@ -37,6 +37,16 @@ float3 GetAmbientBRDF( GeometryProps geometryProps, MaterialProps materialProps, [numthreads( 16, 16, 1 )] void main( uint2 pixelPos : SV_DispatchThreadId ) { + /* + TODO: modify SHARC to support: + - material de-modulation + - 2 levels of detail: fine and coarse ( large voxels ) + - firefly suppression + - anti-lag + - dynamic "sceneScale" + - auto "sceneScale" adjustment to guarantee desired number of samples in voxels on average + */ + // Initialize RNG Rng::Hash::Initialize( pixelPos, gFrameIndex ); @@ -86,8 +96,7 @@ void main( uint2 pixelPos : SV_DispatchThreadId ) sharcHitData.normalWorld = normalize( geometryProps.N + ( Rng::Hash::GetFloat4( ).xyz - 0.5 ) * SHARC_NORMAL_DITHER ); SharcSetThroughput( sharcState, 1.0 ); - - if( !SharcUpdateHit( sharcState, sharcHitData, L, Rng::Hash::GetFloat( ) ) ) + if( !SharcUpdateHit( sharcState, sharcHitData, L, 1.0 ) ) return; } @@ -246,7 +255,6 @@ void main( uint2 pixelPos : SV_DispatchThreadId ) sharcHitData.normalWorld = normalize( geometryProps.N + ( Rng::Hash::GetFloat4( ).xyz - 0.5 ) * SHARC_NORMAL_DITHER ); SharcSetThroughput( sharcState, throughput ); - if( geometryProps.IsSky( ) ) SharcUpdateMiss( sharcState, L ); else if( !SharcUpdateHit( sharcState, sharcHitData, L, Rng::Hash::GetFloat( ) ) ) diff --git a/Shaders/Taa.cs.hlsl b/Shaders/Taa.cs.hlsl index aa04314..b2b1c46 100644 --- a/Shaders/Taa.cs.hlsl +++ b/Shaders/Taa.cs.hlsl @@ -129,8 +129,7 @@ void main( int2 threadPos : SV_GroupThreadId, int2 pixelPos : SV_DispatchThreadI history.xyz = max( history.xyz, 0.0 ); // yes, not "saturate" // Remove transfer - bool isSrgb = gIsSrgb && ( gOnScreen == SHOW_FINAL || gOnScreen == SHOW_BASE_COLOR ); - if( isSrgb ) + if( gIsSrgb ) history.xyz = Color::FromSrgb( history.xyz ); // Update mix rate @@ -160,7 +159,7 @@ void main( int2 threadPos : SV_GroupThreadId, int2 pixelPos : SV_DispatchThreadI float3 result = lerp( clampedHistory, input, mixRate ); // Apply transfer - if( isSrgb ) + if( gIsSrgb ) result = Color::ToSrgb( result ); // Output diff --git a/Shaders/TraceOpaque.cs.hlsl b/Shaders/TraceOpaque.cs.hlsl index 5adbecb..409a8d9 100644 --- a/Shaders/TraceOpaque.cs.hlsl +++ b/Shaders/TraceOpaque.cs.hlsl @@ -74,7 +74,7 @@ float4 GetRadianceFromPreviousFrame( GeometryProps geometryProps, MaterialProps float diffuseProbabilityBiased = EstimateDiffuseProbability( geometryProps, materialProps, true ); float3 prevLsum = prevLdiff + prevLspec * diffuseProbabilityBiased; - float diffuseLikeMotion = lerp( diffuseProbabilityBiased, 1.0, Math::Sqrt01( materialProps.curvature ) ); + float diffuseLikeMotion = lerp( diffuseProbabilityBiased, 1.0, Math::Sqrt01( materialProps.curvature ) ); // TODO: review prevFrameWeight *= isDiffuse ? 1.0 : diffuseLikeMotion; float a = Color::Luminance( prevLdiff ); @@ -168,7 +168,7 @@ TraceOpaqueResult TraceOpaque( inout TraceOpaqueDesc desc ) MaterialProps materialProps = desc.materialProps; float accumulatedHitDist = 0.0; - float accumulatedPseudoCurvature = 0.0; // TODO: is there a less empirical solution? + float accumulatedCurvature = 0.0; bool isPSR = false; [loop] @@ -177,10 +177,10 @@ TraceOpaqueResult TraceOpaque( inout TraceOpaqueDesc desc ) isPSR = true; // Origin point - float curvature = materialProps.curvature; - accumulatedPseudoCurvature += Math::Pow01( abs( curvature ), 0.25 ); - { + // Accumulate curvature + accumulatedCurvature += materialProps.curvature; // yes, before hit + // Accumulate mirror matrix mirrorMatrix = mul( Geometry::GetMirrorMatrix( materialProps.N ), mirrorMatrix ); @@ -211,9 +211,7 @@ TraceOpaqueResult TraceOpaque( inout TraceOpaqueDesc desc ) // Hit point { // Accumulate hit distance representing virtual point position ( see "README/NOISY INPUTS" ) - // TODO: this heuristic works best so far - float hitDistFocused = geometryProps.tmin / ( 2.0 * curvature * geometryProps.tmin + 1.0 ); - accumulatedHitDist += hitDistFocused * Math::SmoothStep( 0.2, 0.0, accumulatedPseudoCurvature ); + accumulatedHitDist += ApplyThinLensEquation( geometryProps.hitT, accumulatedCurvature ) ; } desc.bounceNum--; @@ -261,7 +259,7 @@ TraceOpaqueResult TraceOpaque( inout TraceOpaqueDesc desc ) sharcState.voxelDataBuffer = gInOut_SharcVoxelDataBuffer; bool isSharcAllowed = gSHARC && NRD_MODE < OCCLUSION; // trivial - isSharcAllowed &= geometryProps.tmin > voxelSize; // voxel angular size is acceptable + isSharcAllowed &= geometryProps.hitT > voxelSize; // voxel angular size is acceptable isSharcAllowed &= Rng::Hash::GetFloat( ) > Lpsr.w; // probabilistically estimate the need isSharcAllowed &= desc.bounceNum == 0; // allow only for the last bounce for PSR @@ -328,6 +326,7 @@ TraceOpaqueResult TraceOpaque( inout TraceOpaqueDesc desc ) float accumulatedHitDist = 0; float accumulatedDiffuseLikeMotion = 0; + float accumulatedCurvature = 0; bool isDiffusePath = gTracingMode == RESOLUTION_HALF ? desc.checkerboard : ( path & 0x1 ); uint2 blueNoisePos = desc.pixelPos + uint2( Sequence::Weyl2D( 0.0, path ) * ( BLUE_NOISE_SPATIAL_DIM - 1 ) ); @@ -611,7 +610,7 @@ TraceOpaqueResult TraceOpaque( inout TraceOpaqueDesc desc ) sharcState.voxelDataBuffer = gInOut_SharcVoxelDataBuffer; bool isSharcAllowed = gSHARC && NRD_MODE < OCCLUSION; // trivial - isSharcAllowed &= geometryProps.tmin > voxelSize; // voxel angular size is acceptable + isSharcAllowed &= geometryProps.hitT > voxelSize; // voxel angular size is acceptable isSharcAllowed &= Rng::Hash::GetFloat( ) > Lcached.w; // probabilistically estimate the need isSharcAllowed &= isDiffuse || Rng::Hash::GetFloat( ) < smc || bounce == desc.bounceNum; // allowed for diffuse-like events or last bounce @@ -640,21 +639,6 @@ TraceOpaqueResult TraceOpaque( inout TraceOpaqueDesc desc ) pathThroughput *= 1.0 - Lcached.w; // Accumulate path length for NRD ( see "README/NOISY INPUTS" ) - /* - REQUIREMENTS: - - hitT for the bounce after the primary hit or PSR must be provided "as is" - - hitT for subsequent bounces and for bounces before PSR must be adjusted by curvature and lobe energy dissipation on the application side - - IDEAL SOLUTION ( after PSR ): - hitDist = 0; - for( uint bounce = N; bounce > PSR + 1; bounce-- ) - { - hitDist += hitT[ bounce ]; - hitDist = ApplyThinLensEquation( hitDist, curvature[ bounce - 1 ] ); - hitDist = ApplyLobeSpread( hitDist, bounce, isDiffuse ? 1.0 : roughness ); - } - hitDist += hitT[ PSR + 1 ]; - */ float a = Color::Luminance( L ); float b = Color::Luminance( Lsum ); // already includes L float importance = a / ( b + 1e-6 ); @@ -662,11 +646,11 @@ TraceOpaqueResult TraceOpaque( inout TraceOpaqueDesc desc ) importance *= 1.0 - Color::Luminance( materialProps.Lemi ) / ( a + 1e-6 ); float diffuseLikeMotion = EstimateDiffuseProbability( geometryProps, materialProps, true ); - diffuseLikeMotion = lerp( diffuseLikeMotion, 1.0, Math::Sqrt01( materialProps.curvature ) ); diffuseLikeMotion = isDiffuse ? 1.0 : diffuseLikeMotion; - accumulatedHitDist += geometryProps.tmin * Math::SmoothStep( 0.2, 0.0, accumulatedDiffuseLikeMotion ); + accumulatedHitDist += ApplyThinLensEquation( geometryProps.hitT, accumulatedCurvature ) * Math::SmoothStep( 0.2, 0.0, accumulatedDiffuseLikeMotion ); accumulatedDiffuseLikeMotion += 1.0 - importance * ( 1.0 - diffuseLikeMotion ); + accumulatedCurvature += materialProps.curvature; // yes, after hit } } @@ -891,11 +875,11 @@ void main( uint2 pixelPos : SV_DispatchThreadId ) else if( gOnScreen == SHOW_UV ) materialProps0.Ldirect = float3( frac( geometryProps0.uv ), 0 ); else if( gOnScreen == SHOW_CURVATURE ) - materialProps0.Ldirect = sqrt( abs( materialProps0.curvature ) ); + materialProps0.Ldirect = sqrt(abs(materialProps0.curvature)) * 0.1; else if( gOnScreen == SHOW_MIP_PRIMARY ) { float mipNorm = Math::Sqrt01( geometryProps0.mip / MAX_MIP_LEVEL ); - materialProps0.Ldirect = Color::ColorizeZucconi( mipNorm ); + materialProps0.Ldirect = Color::ColorizeZucconi(mipNorm); } // Unshadowed sun lighting and emission @@ -948,7 +932,7 @@ void main( uint2 pixelPos : SV_DispatchThreadId ) GeometryProps geometryPropsShadow = CastRay( Xoffset, sunDirection, 0.0, INF, mipAndCone, gWorldTlas, GEOMETRY_ALL, 0 ); // Update hit dist - shadowHitDist += geometryPropsShadow.tmin; + shadowHitDist += geometryPropsShadow.hitT; // Terminate on miss ( before updating translucency! ) if( geometryPropsShadow.IsSky( ) ) @@ -959,7 +943,7 @@ void main( uint2 pixelPos : SV_DispatchThreadId ) shadowTranslucency *= lerp( geometryPropsShadow.Has( FLAG_TRANSPARENT ) ? 0.9 : 0.0, 0.0, Math::Pow01( 1.0 - NoV, 2.5 ) ); // Go to the next hit - Xoffset += sunDirection * ( geometryPropsShadow.tmin + 0.001 ); + Xoffset += sunDirection * ( geometryPropsShadow.hitT + 0.001 ); } float penumbra = SIGMA_FrontEnd_PackPenumbra( shadowHitDist, gTanSunAngularRadius ); diff --git a/Shaders/TraceTransparent.cs.hlsl b/Shaders/TraceTransparent.cs.hlsl index d77a88b..21c65fe 100644 --- a/Shaders/TraceTransparent.cs.hlsl +++ b/Shaders/TraceTransparent.cs.hlsl @@ -66,16 +66,15 @@ float3 TraceTransparent( TraceTransparentDesc desc ) pathThroughput *= isReflection ? F : 1.0 - F; else { - float rnd = Sequence::Bayer4x4( desc.pixelPos, gFrameIndex + bounce ); - if( gDenoiserType == DENOISER_REFERENCE || gRR ) - rnd = Rng::Hash::GetFloat( ); + float rndBayer = Sequence::Bayer4x4( desc.pixelPos, gFrameIndex + bounce ); + float rndWhite = Rng::Hash::GetFloat( ); + float rnd = ( gDenoiserType == DENOISER_REFERENCE || gRR ) ? rndWhite : rndBayer + rndWhite / 16.0; isReflection = rnd < F; } // Compute ray float3 ray = reflect( -geometryProps.V, geometryProps.N ); - if( !isReflection ) { float3 I = -geometryProps.V; @@ -141,7 +140,7 @@ float3 TraceTransparent( TraceTransparentDesc desc ) sharcState.voxelDataBuffer = gInOut_SharcVoxelDataBuffer; bool isSharcAllowed = gSHARC && NRD_MODE < OCCLUSION; // trivial - isSharcAllowed &= geometryProps.tmin > voxelSize; // voxel angular size is acceptable + isSharcAllowed &= geometryProps.hitT > voxelSize; // voxel angular size is acceptable isSharcAllowed &= Rng::Hash::GetFloat( ) > Lcached.w; // probabilistically estimate the need float3 sharcRadiance; @@ -200,17 +199,14 @@ void main( int2 pixelPos : SV_DispatchThreadId ) GeometryProps geometryPropsT = CastRay( cameraRayOrigin, cameraRayDirection, 0.0, tmin0, GetConeAngleFromRoughness( 0.0, 0.0 ), gWorldTlas, gTransparent ? GEOMETRY_ONLY_TRANSPARENT : 0, 0 ); // Trace delta events - if( !geometryPropsT.IsSky( ) && geometryPropsT.tmin < tmin0 ) + if( !geometryPropsT.IsSky( ) && geometryPropsT.hitT < tmin0 ) { // Patch motion vectors replacing MV for the background with MV for the closest glass layer. // IMPORTANT: surface-based motion can be used only if the object is curved. // TODO: let's use the simplest heuristic for now, but better switch to some "smart" interpolation between // MVs for the primary opaque surface hit and the primary glass surface hit. - if( geometryPropsT.curvature != 0.0 ) - { - float3 motion = GetMotion( geometryPropsT.X, geometryPropsT.Xprev ); - gInOut_Mv[ pixelPos ] = motion.xyzz; // .w - don't care - } + float3 mvT = GetMotion( geometryPropsT.X, geometryPropsT.Xprev ); + gInOut_Mv[ pixelPos ] = mvT.xyzz; // .w - don't care // Trace transparent stuff TraceTransparentDesc desc = ( TraceTransparentDesc )0; @@ -221,10 +217,12 @@ void main( int2 pixelPos : SV_DispatchThreadId ) // IMPORTANT: use 1 reflection path and 1 refraction path at the primary glass hit to significantly reduce noise // TODO: use probabilistic split at the primary glass hit when denoising becomes available desc.isReflection = true; - Lsum = TraceTransparent( desc ); + float3 reflection = TraceTransparent( desc ); + Lsum = reflection; desc.isReflection = false; - Lsum += TraceTransparent( desc ); + float3 refraction = TraceTransparent( desc ); + Lsum += refraction; } // Apply exposure diff --git a/Source/NRDSample.cpp b/Source/NRDSample.cpp index d17bc6f..ec7ea19 100644 --- a/Source/NRDSample.cpp +++ b/Source/NRDSample.cpp @@ -48,6 +48,8 @@ constexpr bool ALLOW_BLAS_MERGING = true; constexpr bool ALLOW_HDR = false; // use "WIN + ALT + B" to switch HDR mode constexpr bool USE_LOW_PRECISION_FP_FORMATS = true; // saves a bit of memory and performance constexpr bool NRD_ALLOW_DESCRIPTOR_CACHING = true; +constexpr bool NRD_PROMOTE_FLOAT16_TO_32 = false; +constexpr bool NRD_DEMOTE_FLOAT32_TO_16 = false; constexpr int32_t MAX_HISTORY_FRAME_NUM = (int32_t)std::min(60u, std::min(nrd::REBLUR_MAX_HISTORY_FRAME_NUM, nrd::RELAX_MAX_HISTORY_FRAME_NUM)); constexpr uint32_t TEXTURES_PER_MATERIAL = 4; constexpr uint32_t MAX_TEXTURE_TRANSITIONS_NUM = 32; @@ -404,7 +406,7 @@ struct Settings bool adaptiveAccumulation = true; bool usePrevFrame = true; bool windowAlignment = true; - bool unused2 = false; + bool boost = false; bool SR = false; bool RR = false; }; @@ -461,8 +463,7 @@ struct AnimatedInstance class Sample : public SampleBase { public: - Sample() : - m_NRD(BUFFERED_FRAME_MAX_NUM, NRD_ALLOW_DESCRIPTOR_CACHING, "NRD") + inline Sample() {} ~Sample(); @@ -568,16 +569,16 @@ class Sample : public SampleBase void CreateResources(nri::Format swapChainFormat); void CreateDescriptorSets(); void CreateTexture(std::vector& descriptorDescs, const char* debugName, nri::Format format, nri::Dim_t width, nri::Dim_t height, nri::Mip_t mipNum, nri::Dim_t arraySize, nri::TextureUsageBits usage, nri::AccessBits state); - void CreateBuffer(std::vector& descriptorDescs, const char* debugName, uint64_t elements, uint32_t stride, nri::BufferUsageBits usage, nri::Format format = nri::Format::UNKNOWN); + void CreateBuffer(std::vector& descriptorDescs, const char* debugName, nri::Format format, uint64_t elements, uint32_t stride, nri::BufferUsageBits usage); void UploadStaticData(); - void UpdateConstantBuffer(uint32_t frameIndex, float otherMaxAccumulatedFrameNum); + void UpdateConstantBuffer(uint32_t frameIndex, float resetHistoryFactor); void RestoreBindings(nri::CommandBuffer& commandBuffer, bool isEven); void GatherInstanceData(); uint16_t BuildOptimizedTransitions(const TextureState* states, uint32_t stateNum, std::array& transitions); private: // NRD - NrdIntegration m_NRD; + nrd::Integration m_NRD = {}; nrd::CommonSettings m_CommonSettings = {}; nrd::RelaxSettings m_RelaxSettings = {}; nrd::ReblurSettings m_ReblurSettings = {}; @@ -734,7 +735,7 @@ bool Sample::Initialize(nri::GraphicsAPI graphicsAPI) streamerDesc.constantBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; streamerDesc.constantBufferSize = DYNAMIC_CONSTANT_BUFFER_SIZE; streamerDesc.dynamicBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; - streamerDesc.dynamicBufferUsageBits = nri::BufferUsageBits::VERTEX_BUFFER | nri::BufferUsageBits::INDEX_BUFFER | nri::BufferUsageBits::ACCELERATION_STRUCTURE_BUILD_READ; + streamerDesc.dynamicBufferUsageBits = nri::BufferUsageBits::VERTEX_BUFFER | nri::BufferUsageBits::INDEX_BUFFER | nri::BufferUsageBits::ACCELERATION_STRUCTURE_BUILD_INPUT; streamerDesc.frameInFlightNum = BUFFERED_FRAME_MAX_NUM + 1; // TODO: "+1" for just in case? NRI_ABORT_ON_FAILURE( NRI.CreateStreamer(*m_Device, streamerDesc, m_Streamer) ); @@ -834,10 +835,19 @@ bool Sample::Initialize(nri::GraphicsAPI graphicsAPI) instanceCreationDesc.denoisers = denoisersDescs; instanceCreationDesc.denoisersNum = helper::GetCountOf(denoisersDescs); + nrd::IntegrationCreationDesc desc = {}; + desc.name = "NRD"; + desc.bufferedFramesNum = BUFFERED_FRAME_MAX_NUM; + desc.enableDescriptorCaching = NRD_ALLOW_DESCRIPTOR_CACHING; + desc.promoteFloat16to32 = NRD_PROMOTE_FLOAT16_TO_32; + desc.demoteFloat32to16 = NRD_DEMOTE_FLOAT32_TO_16; + desc.resourceWidth = (uint16_t)m_RenderResolution.x; + desc.resourceHeight = (uint16_t)m_RenderResolution.y; + nri::VideoMemoryInfo videoMemoryInfo1 = {}; NRI.QueryVideoMemoryInfo(*m_Device, nri::MemoryLocation::DEVICE, videoMemoryInfo1); - NRI_ABORT_ON_FALSE( m_NRD.Initialize((uint16_t)m_RenderResolution.x, (uint16_t)m_RenderResolution.y, instanceCreationDesc, *m_Device, NRI, NRI) ); + NRI_ABORT_ON_FALSE( m_NRD.Initialize(desc, instanceCreationDesc, *m_Device, NRI, NRI) ); nri::VideoMemoryInfo videoMemoryInfo2 = {}; NRI.QueryVideoMemoryInfo(*m_Device, nri::MemoryLocation::DEVICE, videoMemoryInfo2); @@ -880,7 +890,7 @@ bool Sample::Initialize(nri::GraphicsAPI graphicsAPI) instanceCreationDesc.denoisers = &denoiserDesc; instanceCreationDesc.denoisersNum = 1; - NrdIntegration instance(BUFFERED_FRAME_MAX_NUM, NRD_ALLOW_DESCRIPTOR_CACHING, "Unused"); + nrd::Integration instance(BUFFERED_FRAME_MAX_NUM, NRD_ALLOW_DESCRIPTOR_CACHING, "Unused"); NRI_ABORT_ON_FALSE( instance.Initialize(w, h, instanceCreationDesc, *m_Device, NRI, NRI) ); printf("| %10s | %36s | %16.2f | %16.2f | %16.2f |\n", i == 0 ? resolution : "", methodName, instance.GetTotalMemoryUsageInMb(), instance.GetPersistentMemoryUsageInMb(), instance.GetAliasableMemoryUsageInMb()); @@ -1092,7 +1102,10 @@ void Sample::PrepareFrame(uint32_t frameIndex) ImGui::SameLine(); } ImGui::SetNextItemWidth( ImGui::CalcItemWidth() - ImGui::GetCursorPosX() + ImGui::GetStyle().ItemSpacing.x ); - ImGui::SliderFloat("Resolution scale (%)", &m_Settings.resolutionScale, m_MinResolutionScale, 1.0f, "%.3f"); + if (m_Settings.RR) + m_Settings.resolutionScale = 1.0f; + else + ImGui::SliderFloat("Resolution scale (%)", &m_Settings.resolutionScale, m_MinResolutionScale, 1.0f, "%.3f"); ImGui::SliderFloat("Aperture (cm)", &m_DofAperture, 0.0f, 100.0f, "%.2f"); ImGui::SliderFloat("Focal distance (m)", &m_DofFocalDistance, NEAR_Z, 10.0f, "%.3f"); @@ -1272,9 +1285,9 @@ void Sample::PrepareFrame(uint32_t frameIndex) ImGui::Combo("Resolution", &m_Settings.tracingMode, resolution, helper::GetCountOf(resolution)); ImGui::PopStyleColor(); - ImGui::Checkbox("Diffuse", &m_Settings.indirectDiffuse); + ImGui::Checkbox("Diff", &m_Settings.indirectDiffuse); ImGui::SameLine(); - ImGui::Checkbox("Specular", &m_Settings.indirectSpecular); + ImGui::Checkbox("Spec", &m_Settings.indirectSpecular); ImGui::SameLine(); ImGui::Checkbox("Trim lobe", &m_Settings.specularLobeTrimming); ImGui::SameLine(); @@ -1282,23 +1295,20 @@ void Sample::PrepareFrame(uint32_t frameIndex) #if( NRD_MODE < OCCLUSION ) const float3& sunDirection = GetSunDirection(); + ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Text, sunDirection.z > 0.0f ? UI_DEFAULT : (m_Settings.importanceSampling ? UI_GREEN : UI_YELLOW)); ImGui::Checkbox("IS", &m_Settings.importanceSampling); ImGui::PopStyleColor(); - ImGui::SameLine(); - ImGui::Checkbox("Use prev frame", &m_Settings.usePrevFrame); + ImGui::Checkbox("L1 (prev frame)", &m_Settings.usePrevFrame); ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Text, m_Settings.SHARC ? UI_GREEN : UI_YELLOW); - ImGui::Checkbox("SHARC", &m_Settings.SHARC); + ImGui::Checkbox("L2 (SHARC)", &m_Settings.SHARC); ImGui::PopStyleColor(); - - if (m_Settings.tracingMode != RESOLUTION_HALF) - ImGui::SameLine(); #endif - if (m_Settings.tracingMode != RESOLUTION_HALF) { + ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Text, m_Settings.PSR ? UI_GREEN : UI_YELLOW); ImGui::Checkbox("PSR", &m_Settings.PSR); ImGui::PopStyleColor(); @@ -1446,6 +1456,11 @@ void Sample::PrepareFrame(uint32_t frameIndex) ImGui::Checkbox("Anti-firefly", &m_ReblurSettings.enableAntiFirefly); ImGui::Checkbox("Performance mode", &m_ReblurSettings.enablePerformanceMode); + if (m_Settings.SHARC) + { + ImGui::SameLine(); + ImGui::Checkbox("SHARC boost", &m_Settings.boost); + } #if( NRD_MODE == SH || NRD_MODE == DIRECTIONAL_OCCLUSION ) ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Text, m_Resolve ? UI_GREEN : UI_RED); @@ -1599,7 +1614,12 @@ void Sample::PrepareFrame(uint32_t frameIndex) ImGui::Checkbox("Anti-firefly", &m_RelaxSettings.enableAntiFirefly); ImGui::Checkbox("Roughness edge stopping", &m_RelaxSettings.enableRoughnessEdgeStopping); - #if( NRD_MODE == SH) + if (m_Settings.SHARC) + { + ImGui::SameLine(); + ImGui::Checkbox("SHARC boost", &m_Settings.boost); + } + #if( NRD_MODE == SH ) ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Text, m_Resolve ? UI_GREEN : UI_RED); ImGui::Checkbox("Resolve", &m_Resolve); @@ -2203,7 +2223,8 @@ void Sample::PrepareFrame(uint32_t frameIndex) bool isFastHistoryEnabled = m_Settings.maxAccumulatedFrameNum > m_Settings.maxFastAccumulatedFrameNum; float fps = 1000.0f / m_Timer.GetSmoothedFrameTime(); - float maxAccumulatedFrameNum = clamp(ACCUMULATION_TIME * fps, 5.0f, float(MAX_HISTORY_FRAME_NUM)); + float maxAccumulatedFrameNum = fps * ACCUMULATION_TIME * ((m_Settings.boost && m_Settings.SHARC) ? 0.667f : 1.0f); + maxAccumulatedFrameNum = min(maxAccumulatedFrameNum, float(MAX_HISTORY_FRAME_NUM)); float maxFastAccumulatedFrameNum = isFastHistoryEnabled ? (maxAccumulatedFrameNum / 5.0f) : float(MAX_HISTORY_FRAME_NUM); m_Settings.maxAccumulatedFrameNum = int32_t(maxAccumulatedFrameNum + 0.5f); @@ -2269,11 +2290,7 @@ void Sample::PrepareFrame(uint32_t frameIndex) m_NRD.NewFrame(); m_NRD.SetCommonSettings(m_CommonSettings); - float fps = 1000.0f / m_Timer.GetSmoothedFrameTime(); - float otherMaxAccumulatedFrameNum = clamp(ACCUMULATION_TIME * fps, 5.0f, float(MAX_HISTORY_FRAME_NUM)); - otherMaxAccumulatedFrameNum *= resetHistoryFactor; - - UpdateConstantBuffer(frameIndex, otherMaxAccumulatedFrameNum); + UpdateConstantBuffer(frameIndex, resetHistoryFactor); GatherInstanceData(); NRI.CopyStreamerUpdateRequests(*m_Streamer); @@ -2699,7 +2716,7 @@ void Sample::CreateAccelerationStructures() nri::Buffer* uploadBuffer = nullptr; { nri::AllocateBufferDesc allocateBufferDesc = {}; - allocateBufferDesc.desc = {uploadSize, 0, nri::BufferUsageBits::ACCELERATION_STRUCTURE_BUILD_READ}; + allocateBufferDesc.desc = {uploadSize, 0, nri::BufferUsageBits::ACCELERATION_STRUCTURE_BUILD_INPUT}; allocateBufferDesc.memoryLocation = nri::MemoryLocation::HOST_UPLOAD; NRI_ABORT_ON_FAILURE(NRI.AllocateBuffer(*m_Device, allocateBufferDesc, uploadBuffer)); @@ -2866,7 +2883,7 @@ void Sample::CreateAccelerationStructures() parameters.push_back( {accelerationStructure, scratchSize, (uint32_t)geometryObjectBase, geometryObjectsNum, allocateAccelerationStructureDesc.desc.flags} ); uint64_t size = NRI.GetAccelerationStructureBuildScratchBufferSize(*accelerationStructure); - scratchSize += helper::Align(size, deviceDesc.rayTracingScratchAlignment); + scratchSize += helper::Align(size, deviceDesc.scratchBufferOffsetAlignment); } else { @@ -2934,12 +2951,12 @@ void Sample::CreateAccelerationStructures() parameters.push_back( {accelerationStructure, scratchSize, (uint32_t)(geometryObjects.size() - 1), 1, allocateAccelerationStructureDesc.desc.flags } ); uint64_t buildSize = NRI.GetAccelerationStructureBuildScratchBufferSize(*accelerationStructure); - scratchSize += helper::Align(buildSize, deviceDesc.rayTracingScratchAlignment); + scratchSize += helper::Align(buildSize, deviceDesc.scratchBufferOffsetAlignment); if (mesh.HasMorphTargets()) { uint64_t updateSize = NRI.GetAccelerationStructureUpdateScratchBufferSize(*accelerationStructure); - m_MorphMeshScratchSize += helper::Align(max(buildSize, updateSize), deviceDesc.rayTracingScratchAlignment); + m_MorphMeshScratchSize += helper::Align(max(buildSize, updateSize), deviceDesc.scratchBufferOffsetAlignment); } // Update geometry offset @@ -2951,7 +2968,7 @@ void Sample::CreateAccelerationStructures() nri::Buffer* scratchBuffer = nullptr; { nri::AllocateBufferDesc allocateBufferDesc = {}; - allocateBufferDesc.desc = {scratchSize, 0, nri::BufferUsageBits::RAY_TRACING_BUFFER}; + allocateBufferDesc.desc = {scratchSize, 0, nri::BufferUsageBits::SCRATCH_BUFFER}; allocateBufferDesc.memoryLocation = nri::MemoryLocation::DEVICE; NRI_ABORT_ON_FAILURE(NRI.AllocateBuffer(*m_Device, allocateBufferDesc, scratchBuffer)); @@ -3114,23 +3131,36 @@ void Sample::CreateResources(nri::Format swapChainFormat) m_LightTlasData.resize(instanceNum); // Buffers (DEVICE, read-only) - CreateBuffer(descriptorDescs, "Buffer::InstanceData", instanceDataSize / sizeof(InstanceData), sizeof(InstanceData), nri::BufferUsageBits::SHADER_RESOURCE, nri::Format::UNKNOWN); - CreateBuffer(descriptorDescs, "Buffer::MorphMeshIndices", m_Scene.morphMeshTotalIndicesNum, sizeof(utils::Index), nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::ACCELERATION_STRUCTURE_BUILD_READ, nri::Format::UNKNOWN); - CreateBuffer(descriptorDescs, "Buffer::MorphMeshVertices", m_Scene.morphVertices.size(), sizeof(utils::MorphVertex), nri::BufferUsageBits::SHADER_RESOURCE, nri::Format::UNKNOWN); + CreateBuffer(descriptorDescs, "Buffer::InstanceData", nri::Format::UNKNOWN, instanceDataSize / sizeof(InstanceData), sizeof(InstanceData), + nri::BufferUsageBits::SHADER_RESOURCE); + CreateBuffer(descriptorDescs, "Buffer::MorphMeshIndices", nri::Format::UNKNOWN, m_Scene.morphMeshTotalIndicesNum, sizeof(utils::Index), + nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::ACCELERATION_STRUCTURE_BUILD_INPUT); + CreateBuffer(descriptorDescs, "Buffer::MorphMeshVertices", nri::Format::UNKNOWN, m_Scene.morphVertices.size(), sizeof(utils::MorphVertex), + nri::BufferUsageBits::SHADER_RESOURCE); // Buffers (DEVICE) - CreateBuffer(descriptorDescs, "Buffer::MorphedPositions", m_Scene.morphedVerticesNum * MAX_ANIMATION_HISTORY_FRAME_NUM, sizeof(float16_t4), nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::SHADER_RESOURCE_STORAGE | nri::BufferUsageBits::ACCELERATION_STRUCTURE_BUILD_READ, nri::Format::UNKNOWN); - CreateBuffer(descriptorDescs, "Buffer::MorphedAttributes", m_Scene.morphedVerticesNum, sizeof(MorphedAttributes), nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::SHADER_RESOURCE_STORAGE, nri::Format::UNKNOWN); - CreateBuffer(descriptorDescs, "Buffer::MorphedPrimitivePrevPositions", m_Scene.morphedPrimitivesNum, sizeof(MorphedPrimitivePrevPositions), nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::SHADER_RESOURCE_STORAGE, nri::Format::UNKNOWN); - CreateBuffer(descriptorDescs, "Buffer::PrimitiveData", m_Scene.totalInstancedPrimitivesNum, sizeof(PrimitiveData), nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::SHADER_RESOURCE_STORAGE, nri::Format::UNKNOWN); - CreateBuffer(descriptorDescs, "Buffer::SharcHashEntries", SHARC_CAPACITY, sizeof(uint64_t), nri::BufferUsageBits::SHADER_RESOURCE_STORAGE, nri::Format::UNKNOWN); - CreateBuffer(descriptorDescs, "Buffer::SharcHashCopyOffset", SHARC_CAPACITY, sizeof(uint32_t), nri::BufferUsageBits::SHADER_RESOURCE_STORAGE, nri::Format::UNKNOWN); - CreateBuffer(descriptorDescs, "Buffer::SharcVoxelDataPing", SHARC_CAPACITY, sizeof(uint32_t) * 4, nri::BufferUsageBits::SHADER_RESOURCE_STORAGE, nri::Format::UNKNOWN); - CreateBuffer(descriptorDescs, "Buffer::SharcVoxelDataPong", SHARC_CAPACITY, sizeof(uint32_t) * 4, nri::BufferUsageBits::SHADER_RESOURCE_STORAGE, nri::Format::UNKNOWN); - - CreateBuffer(descriptorDescs, "Buffer::WorldScratch", worldScratchBufferSize, 1, nri::BufferUsageBits::RAY_TRACING_BUFFER); - CreateBuffer(descriptorDescs, "Buffer::LightScratch", lightScratchBufferSize, 1, nri::BufferUsageBits::RAY_TRACING_BUFFER); - CreateBuffer(descriptorDescs, "Buffer::MorphMeshScratch", m_MorphMeshScratchSize, 1, nri::BufferUsageBits::RAY_TRACING_BUFFER); + CreateBuffer(descriptorDescs, "Buffer::MorphedPositions", nri::Format::UNKNOWN, m_Scene.morphedVerticesNum * MAX_ANIMATION_HISTORY_FRAME_NUM, sizeof(float16_t4), + nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::SHADER_RESOURCE_STORAGE | nri::BufferUsageBits::ACCELERATION_STRUCTURE_BUILD_INPUT); + CreateBuffer(descriptorDescs, "Buffer::MorphedAttributes", nri::Format::UNKNOWN, m_Scene.morphedVerticesNum, sizeof(MorphedAttributes), + nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::SHADER_RESOURCE_STORAGE); + CreateBuffer(descriptorDescs, "Buffer::MorphedPrimitivePrevPositions", nri::Format::UNKNOWN, m_Scene.morphedPrimitivesNum, sizeof(MorphedPrimitivePrevPositions), + nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::SHADER_RESOURCE_STORAGE); + CreateBuffer(descriptorDescs, "Buffer::PrimitiveData", nri::Format::UNKNOWN, m_Scene.totalInstancedPrimitivesNum, sizeof(PrimitiveData), + nri::BufferUsageBits::SHADER_RESOURCE | nri::BufferUsageBits::SHADER_RESOURCE_STORAGE); + CreateBuffer(descriptorDescs, "Buffer::SharcHashEntries", nri::Format::UNKNOWN, SHARC_CAPACITY, sizeof(uint64_t), + nri::BufferUsageBits::SHADER_RESOURCE_STORAGE); + CreateBuffer(descriptorDescs, "Buffer::SharcHashCopyOffset", nri::Format::UNKNOWN, SHARC_CAPACITY, sizeof(uint32_t), + nri::BufferUsageBits::SHADER_RESOURCE_STORAGE); + CreateBuffer(descriptorDescs, "Buffer::SharcVoxelDataPing", nri::Format::UNKNOWN, SHARC_CAPACITY, sizeof(uint32_t) * 4, + nri::BufferUsageBits::SHADER_RESOURCE_STORAGE); + CreateBuffer(descriptorDescs, "Buffer::SharcVoxelDataPong", nri::Format::UNKNOWN, SHARC_CAPACITY, sizeof(uint32_t) * 4, + nri::BufferUsageBits::SHADER_RESOURCE_STORAGE); + CreateBuffer(descriptorDescs, "Buffer::WorldScratch", nri::Format::UNKNOWN, worldScratchBufferSize, 1, + nri::BufferUsageBits::SCRATCH_BUFFER); + CreateBuffer(descriptorDescs, "Buffer::LightScratch", nri::Format::UNKNOWN, lightScratchBufferSize, 1, + nri::BufferUsageBits::SCRATCH_BUFFER); + CreateBuffer(descriptorDescs, "Buffer::MorphMeshScratch", nri::Format::UNKNOWN, m_MorphMeshScratchSize, 1, + nri::BufferUsageBits::SCRATCH_BUFFER); // Textures (DEVICE) CreateTexture(descriptorDescs, "Texture::ViewZ", nri::Format::R32_SFLOAT, w, h, 1, 1, @@ -3233,20 +3263,17 @@ void Sample::CreateResources(nri::Format swapChainFormat) { NRI.SetBufferDebugName(*(nri::Buffer*)desc.resource, desc.debugName); - if (!(desc.bufferUsage & nri::BufferUsageBits::RAY_TRACING_BUFFER)) + if (desc.bufferUsage & nri::BufferUsageBits::SHADER_RESOURCE) { - if (desc.bufferUsage & nri::BufferUsageBits::SHADER_RESOURCE) - { - const nri::BufferViewDesc viewDesc = { (nri::Buffer*)desc.resource, nri::BufferViewType::SHADER_RESOURCE, desc.format }; - NRI_ABORT_ON_FAILURE(NRI.CreateBufferView(viewDesc, descriptor)); - m_Descriptors.push_back(descriptor); - } - if (desc.bufferUsage & nri::BufferUsageBits::SHADER_RESOURCE_STORAGE) - { - const nri::BufferViewDesc viewDesc = { (nri::Buffer*)desc.resource, nri::BufferViewType::SHADER_RESOURCE_STORAGE, desc.format }; - NRI_ABORT_ON_FAILURE(NRI.CreateBufferView(viewDesc, descriptor)); - m_Descriptors.push_back(descriptor); - } + const nri::BufferViewDesc viewDesc = { (nri::Buffer*)desc.resource, nri::BufferViewType::SHADER_RESOURCE, desc.format }; + NRI_ABORT_ON_FAILURE(NRI.CreateBufferView(viewDesc, descriptor)); + m_Descriptors.push_back(descriptor); + } + if (desc.bufferUsage & nri::BufferUsageBits::SHADER_RESOURCE_STORAGE) + { + const nri::BufferViewDesc viewDesc = { (nri::Buffer*)desc.resource, nri::BufferViewType::SHADER_RESOURCE_STORAGE, desc.format }; + NRI_ABORT_ON_FAILURE(NRI.CreateBufferView(viewDesc, descriptor)); + m_Descriptors.push_back(descriptor); } } } @@ -3724,7 +3751,7 @@ void Sample::CreateTexture(std::vector& descriptorDescs, const c { nri::AllocateTextureDesc allocateTextureDesc = {}; allocateTextureDesc.desc.type = nri::TextureType::TEXTURE_2D; - allocateTextureDesc.desc.usageMask = usage; + allocateTextureDesc.desc.usage = usage; allocateTextureDesc.desc.format = format; allocateTextureDesc.desc.width = width; allocateTextureDesc.desc.height = height; @@ -3756,22 +3783,23 @@ void Sample::CreateTexture(std::vector& descriptorDescs, const c descriptorDescs.push_back( {debugName, texture, format, usage, nri::BufferUsageBits::NONE, arraySize > 1} ); } -void Sample::CreateBuffer(std::vector& descriptorDescs, const char* debugName, uint64_t elements, uint32_t stride, nri::BufferUsageBits usage, nri::Format format) +void Sample::CreateBuffer(std::vector& descriptorDescs, const char* debugName, nri::Format format, uint64_t elements, uint32_t stride, nri::BufferUsageBits usage) { if (!elements) elements = 1; nri::AllocateBufferDesc allocateBufferDesc = {}; allocateBufferDesc.desc.size = elements * stride; - allocateBufferDesc.desc.structureStride = (format == nri::Format::UNKNOWN && stride != 1) ? stride : 0; - allocateBufferDesc.desc.usageMask = usage; + allocateBufferDesc.desc.structureStride = format == nri::Format::UNKNOWN ? stride : 0; + allocateBufferDesc.desc.usage = usage; allocateBufferDesc.memoryLocation = nri::MemoryLocation::DEVICE; nri::Buffer* buffer = nullptr; NRI_ABORT_ON_FAILURE( NRI.AllocateBuffer(*m_Device, allocateBufferDesc, buffer) ); m_Buffers.push_back(buffer); - descriptorDescs.push_back( {debugName, buffer, format, nri::TextureUsageBits::NONE, usage} ); + if (!(usage & nri::BufferUsageBits::SCRATCH_BUFFER)) + descriptorDescs.push_back( {debugName, buffer, format, nri::TextureUsageBits::NONE, usage, false} ); } void Sample::UploadStaticData() @@ -3813,11 +3841,11 @@ void Sample::UploadStaticData() data.t1 = Packing::float2_to_float16_t2( float2(t1.x, t1.y) ); data.t2 = Packing::float2_to_float16_t2( float2(t2.x, t2.y) ); - data.curvature0_curvature1 = Packing::float2_to_float16_t2( float2(v0.curvature, v1.curvature) ); - data.curvature2_bitangentSign = Packing::float2_to_float16_t2( float2(v2.curvature, v0.T[3]) ); + data.bitangentSign_unused = Packing::float2_to_float16_t2( float2(v0.T[3], 0.0f) ); const utils::Primitive& primitive = m_Scene.primitives[staticPrimitiveIndex]; - data.worldToUvUnits = primitive.worldToUvUnits; + data.worldArea = primitive.worldArea; + data.uvArea = primitive.uvArea; } } @@ -4086,7 +4114,7 @@ void Sample::GatherInstanceData() instanceData.textureOffsetAndFlags = baseTextureIndex | ( flags << FLAG_FIRST_BIT ); instanceData.primitiveOffset = meshInstance.primitiveOffset; instanceData.morphedPrimitiveOffset = meshInstance.morphedPrimitiveOffset; - instanceData.invScale = (isLeftHanded ? -1.0f : 1.0f) / max(scale.x, max(scale.y, scale.z)); + instanceData.scale = (isLeftHanded ? -1.0f : 1.0f) * max(scale.x, max(scale.y, scale.z)); // Add dynamic geometry if (instance.allowUpdate) @@ -4145,7 +4173,7 @@ void GetBasis(float3 N, float3& T, float3& B) B = float3(b, N.y * ya - sz, N.y); } -void Sample::UpdateConstantBuffer(uint32_t frameIndex, float otherMaxAccumulatedFrameNum) +void Sample::UpdateConstantBuffer(uint32_t frameIndex, float resetHistoryFactor) { float3 sunDirection = GetSunDirection(); float3 sunT, sunB; @@ -4172,7 +4200,14 @@ void Sample::UpdateConstantBuffer(uint32_t frameIndex, float otherMaxAccumulated float nearZ = (m_PositiveZ ? 1.0f : -1.0f) * NEAR_Z * m_Settings.meterToUnitsMultiplier; float mipBias = baseMipBias + log2f(renderSize.x / outputSize.x); - uint32_t sharcMaxAccumulatedFrameNum = (uint32_t)otherMaxAccumulatedFrameNum; + uint32_t onScreen = m_Settings.onScreen + (NRD_MODE >= OCCLUSION ? SHOW_AMBIENT_OCCLUSION : 0); // preserve original mapping + + float fps = 1000.0f / m_Timer.GetSmoothedFrameTime(); + float otherMaxAccumulatedFrameNum = fps * ACCUMULATION_TIME; + otherMaxAccumulatedFrameNum = min(otherMaxAccumulatedFrameNum, float(MAX_HISTORY_FRAME_NUM)); + otherMaxAccumulatedFrameNum *= resetHistoryFactor; + + uint32_t sharcMaxAccumulatedFrameNum = (uint32_t)(otherMaxAccumulatedFrameNum * (m_Settings.boost ? 0.667f : 1.0f) + 0.5f); float taaMaxAccumulatedFrameNum = otherMaxAccumulatedFrameNum * 0.5f; float prevFrameMaxAccumulatedFrameNum = otherMaxAccumulatedFrameNum * 0.3f; @@ -4262,9 +4297,9 @@ void Sample::UpdateConstantBuffer(uint32_t frameIndex, float otherMaxAccumulated constants.gIndirectDiffuse = m_Settings.indirectDiffuse ? 1.0f : 0.0f; constants.gIndirectSpecular = m_Settings.indirectSpecular ? 1.0f : 0.0f; constants.gTanSunAngularRadius = tan( radians( m_Settings.sunAngularDiameter * 0.5f ) ); - constants.gTanPixelAngularRadius = tan( 0.5f * radians(m_Settings.camFov) / outputSize.x ); + constants.gTanPixelAngularRadius = tan( 0.5f * radians(m_Settings.camFov) / rectSize.x ); constants.gDebug = m_Settings.debug; - constants.gPrevFrameConfidence = (m_Settings.usePrevFrame && NRD_MODE < OCCLUSION) ? prevFrameMaxAccumulatedFrameNum / (1.0f + prevFrameMaxAccumulatedFrameNum) : 0.0f; + constants.gPrevFrameConfidence = (m_Settings.usePrevFrame && NRD_MODE < OCCLUSION && !m_Settings.RR) ? prevFrameMaxAccumulatedFrameNum / (1.0f + prevFrameMaxAccumulatedFrameNum) : 0.0f; constants.gMinProbability = minProbability; constants.gUnproject = 1.0f / (0.5f * rectH * project[1]); constants.gAperture = m_DofAperture * 0.01f; @@ -4275,11 +4310,11 @@ void Sample::UpdateConstantBuffer(uint32_t frameIndex, float otherMaxAccumulated constants.gExposure = m_Settings.exposure; constants.gMipBias = mipBias; constants.gOrthoMode = orthoMode; - constants.gTransparent = (m_HasTransparent && NRD_MODE < OCCLUSION && (m_Settings.onScreen == 0 || m_Settings.onScreen == 2)) ? 1 : 0; + constants.gTransparent = (m_HasTransparent && NRD_MODE < OCCLUSION && onScreen == SHOW_FINAL) ? 1 : 0; constants.gSharcMaxAccumulatedFrameNum = sharcMaxAccumulatedFrameNum; constants.gDenoiserType = (uint32_t)m_Settings.denoiser; constants.gDisableShadowsAndEnableImportanceSampling = (sunDirection.z < 0.0f && m_Settings.importanceSampling && NRD_MODE < OCCLUSION) ? 1 : 0; - constants.gOnScreen = m_Settings.onScreen + (NRD_MODE >= OCCLUSION ? 3 : 0); // preserve original mapping + constants.gOnScreen = onScreen; constants.gFrameIndex = frameIndex; constants.gForcedMaterial = m_Settings.forcedMaterial; constants.gUseNormalMap = m_Settings.normalMap ? 1 : 0; @@ -4292,9 +4327,9 @@ void Sample::UpdateConstantBuffer(uint32_t frameIndex, float otherMaxAccumulated constants.gSHARC = m_Settings.SHARC; constants.gValidation = m_ShowValidationOverlay && m_Settings.denoiser != DENOISER_REFERENCE && m_Settings.separator != 1.0f; constants.gTrimLobe = m_Settings.specularLobeTrimming ? 1 : 0; - constants.gSR = m_Settings.SR ? 1 : 0; + constants.gSR = (m_Settings.SR && !m_Settings.RR) ? 1 : 0; constants.gRR = m_Settings.RR ? 1 : 0; - constants.gIsSrgb = m_IsSrgb ? 1 : 0; + constants.gIsSrgb = (m_IsSrgb && (onScreen == SHOW_FINAL || onScreen == SHOW_BASE_COLOR)) ? 1 : 0; constants.gNisDetectRatio = config.kDetectRatio; constants.gNisDetectThres = config.kDetectThres; constants.gNisMinContrastRatio = config.kMinContrastRatio; @@ -4373,69 +4408,69 @@ void Sample::RenderFrame(uint32_t frameIndex) uint32_t windowGridH = (GetWindowResolution().y + 15) / 16; // NRD user pool - NrdUserPool userPool = {}; + nrd::UserPool userPool = {}; { // Common - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_MV, {&GetState(Texture::Mv), GetFormat(Texture::Mv)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_NORMAL_ROUGHNESS, {&GetState(Texture::Normal_Roughness), GetFormat(Texture::Normal_Roughness)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_VIEWZ, {&GetState(Texture::ViewZ), GetFormat(Texture::ViewZ)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_MV, &GetState(Texture::Mv)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_NORMAL_ROUGHNESS, &GetState(Texture::Normal_Roughness)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_VIEWZ, &GetState(Texture::ViewZ)); // (Optional) Needed to allow IN_MV modification on the NRD side - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_BASECOLOR_METALNESS, {&GetState(Texture::BaseColor_Metalness), GetFormat(Texture::BaseColor_Metalness)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_BASECOLOR_METALNESS, &GetState(Texture::BaseColor_Metalness)); // (Optional) Validation - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_VALIDATION, {&GetState(Texture::Validation), GetFormat(Texture::Validation)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_VALIDATION, &GetState(Texture::Validation)); // Diffuse - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_DIFF_RADIANCE_HITDIST, {&GetState(Texture::Unfiltered_Diff), GetFormat(Texture::Unfiltered_Diff)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_RADIANCE_HITDIST, {&GetState(Texture::Diff), GetFormat(Texture::Diff)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_DIFF_RADIANCE_HITDIST, &GetState(Texture::Unfiltered_Diff)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_RADIANCE_HITDIST, &GetState(Texture::Diff)); // Diffuse occlusion #if( NRD_MODE == OCCLUSION ) - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_DIFF_HITDIST, {&GetState(Texture::Unfiltered_Diff), GetFormat(Texture::Unfiltered_Diff)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_HITDIST, {&GetState(Texture::Diff), GetFormat(Texture::Diff)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_DIFF_HITDIST, &GetState(Texture::Unfiltered_Diff)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_HITDIST, &GetState(Texture::Diff)); #endif // Diffuse SH #if( NRD_MODE == SH ) - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_DIFF_SH0, {&GetState(Texture::Unfiltered_Diff), GetFormat(Texture::Unfiltered_Diff)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_DIFF_SH1, {&GetState(Texture::Unfiltered_DiffSh), GetFormat(Texture::Unfiltered_DiffSh)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_SH0, {&GetState(Texture::Diff), GetFormat(Texture::Diff)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_SH1, {&GetState(Texture::DiffSh), GetFormat(Texture::DiffSh)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_DIFF_SH0, &GetState(Texture::Unfiltered_Diff)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_DIFF_SH1, &GetState(Texture::Unfiltered_DiffSh)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_SH0, &GetState(Texture::Diff)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_SH1, &GetState(Texture::DiffSh)); #endif // Diffuse directional occlusion #if( NRD_MODE == DIRECTIONAL_OCCLUSION ) - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_DIFF_DIRECTION_HITDIST, {&GetState(Texture::Unfiltered_Diff), GetFormat(Texture::Unfiltered_Diff)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_DIRECTION_HITDIST, {&GetState(Texture::Diff), GetFormat(Texture::Diff)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_DIFF_DIRECTION_HITDIST, &GetState(Texture::Unfiltered_Diff)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_DIFF_DIRECTION_HITDIST, &GetState(Texture::Diff)); #endif // Specular - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_SPEC_RADIANCE_HITDIST, {&GetState(Texture::Unfiltered_Spec), GetFormat(Texture::Unfiltered_Spec)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_SPEC_RADIANCE_HITDIST, {&GetState(Texture::Spec), GetFormat(Texture::Spec)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_SPEC_RADIANCE_HITDIST, &GetState(Texture::Unfiltered_Spec)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_SPEC_RADIANCE_HITDIST, &GetState(Texture::Spec)); // Specular occlusion #if( NRD_MODE == OCCLUSION ) - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_SPEC_HITDIST, {&GetState(Texture::Unfiltered_Spec), GetFormat(Texture::Unfiltered_Spec)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_SPEC_HITDIST, {&GetState(Texture::Spec), GetFormat(Texture::Spec)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_SPEC_HITDIST, &GetState(Texture::Unfiltered_Spec)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_SPEC_HITDIST, &GetState(Texture::Spec)); #endif // Specular SH #if( NRD_MODE == SH ) - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_SPEC_SH0, {&GetState(Texture::Unfiltered_Spec), GetFormat(Texture::Unfiltered_Spec)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_SPEC_SH1, {&GetState(Texture::Unfiltered_SpecSh), GetFormat(Texture::Unfiltered_SpecSh)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_SPEC_SH0, {&GetState(Texture::Spec), GetFormat(Texture::Spec)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_SPEC_SH1, {&GetState(Texture::SpecSh), GetFormat(Texture::SpecSh)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_SPEC_SH0, &GetState(Texture::Unfiltered_Spec)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_SPEC_SH1, &GetState(Texture::Unfiltered_SpecSh)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_SPEC_SH0, &GetState(Texture::Spec)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_SPEC_SH1, &GetState(Texture::SpecSh)); #endif // SIGMA - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_PENUMBRA, {&GetState(Texture::Unfiltered_Penumbra), GetFormat(Texture::Unfiltered_Penumbra)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_TRANSLUCENCY, {&GetState(Texture::Unfiltered_Translucency), GetFormat(Texture::Unfiltered_Translucency)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_SHADOW_TRANSLUCENCY, {&GetState(Texture::Shadow), GetFormat(Texture::Shadow)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_PENUMBRA, &GetState(Texture::Unfiltered_Penumbra)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_TRANSLUCENCY, &GetState(Texture::Unfiltered_Translucency)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_SHADOW_TRANSLUCENCY, &GetState(Texture::Shadow)); // REFERENCE - NrdIntegration_SetResource(userPool, nrd::ResourceType::IN_SIGNAL, {&GetState(Texture::Composed), GetFormat(Texture::Composed)}); - NrdIntegration_SetResource(userPool, nrd::ResourceType::OUT_SIGNAL, {&GetState(Texture::Composed), GetFormat(Texture::Composed)}); + nrd::Integration_SetResource(userPool, nrd::ResourceType::IN_SIGNAL, &GetState(Texture::Composed)); + nrd::Integration_SetResource(userPool, nrd::ResourceType::OUT_SIGNAL, &GetState(Texture::Composed)); } const uint32_t dummyDynamicConstantOffset = 0; @@ -4477,7 +4512,7 @@ void Sample::RenderFrame(uint32_t frameIndex) {Get(Buffer::MorphedAttributes), {nri::AccessBits::SHADER_RESOURCE}, {nri::AccessBits::SHADER_RESOURCE_STORAGE}}, }; - nri::BarrierGroupDesc transitionBarriers = { nullptr, bufferTransitions, nullptr, 0, (uint16_t)helper::GetCountOf(bufferTransitions), 0}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, bufferTransitions, helper::GetCountOf(bufferTransitions), nullptr, 0}; NRI.CmdBarrier(commandBuffer, transitionBarriers); } @@ -4529,7 +4564,7 @@ void Sample::RenderFrame(uint32_t frameIndex) {Get(Buffer::MorphedPrimitivePrevPositions), {nri::AccessBits::SHADER_RESOURCE}, {nri::AccessBits::SHADER_RESOURCE_STORAGE}}, }; - nri::BarrierGroupDesc transitionBarriers = { nullptr, bufferTransitions, nullptr, 0, (uint16_t)helper::GetCountOf(bufferTransitions), 0 }; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, bufferTransitions, helper::GetCountOf(bufferTransitions), nullptr, 0}; NRI.CmdBarrier(commandBuffer, transitionBarriers); } } @@ -4596,14 +4631,14 @@ void Sample::RenderFrame(uint32_t frameIndex) NRI.CmdBuildBottomLevelAccelerationStructure(commandBuffer, 1, &geometryObject, BLAS_DEFORMABLE_MESH_BUILD_BITS, accelerationStructure, *Get(Buffer::MorphMeshScratch), scratchOffset); uint64_t size = NRI.GetAccelerationStructureBuildScratchBufferSize(accelerationStructure); - scratchOffset += helper::Align(size, deviceDesc.rayTracingScratchAlignment);; + scratchOffset += helper::Align(size, deviceDesc.scratchBufferOffsetAlignment);; } else { NRI.CmdUpdateBottomLevelAccelerationStructure(commandBuffer, 1, &geometryObject, BLAS_DEFORMABLE_MESH_BUILD_BITS, accelerationStructure, accelerationStructure, *Get(Buffer::MorphMeshScratch), scratchOffset); uint64_t size = NRI.GetAccelerationStructureUpdateScratchBufferSize(accelerationStructure); - scratchOffset += helper::Align(size, deviceDesc.rayTracingScratchAlignment);; + scratchOffset += helper::Align(size, deviceDesc.scratchBufferOffsetAlignment);; } } @@ -4614,7 +4649,7 @@ void Sample::RenderFrame(uint32_t frameIndex) {Get(Buffer::MorphedPrimitivePrevPositions), {nri::AccessBits::SHADER_RESOURCE_STORAGE}, {nri::AccessBits::SHADER_RESOURCE}}, }; - nri::BarrierGroupDesc transitionBarriers = { nullptr, bufferTransitions, nullptr, 0, (uint16_t)helper::GetCountOf(bufferTransitions), 0 }; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, bufferTransitions, helper::GetCountOf(bufferTransitions), nullptr, 0}; NRI.CmdBarrier(commandBuffer, transitionBarriers); } } @@ -4727,7 +4762,7 @@ void Sample::RenderFrame(uint32_t frameIndex) {Texture::Unfiltered_SpecSh, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, #endif }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, optimizedTransitions.data(), 0, 0, BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, optimizedTransitions.data(), BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); NRI.CmdSetPipeline(commandBuffer, *Get(Pipeline::TraceOpaque)); @@ -4859,7 +4894,7 @@ void Sample::RenderFrame(uint32_t frameIndex) {Texture::ComposedDiff, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, {Texture::ComposedSpec_ViewZ, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, optimizedTransitions.data(), 0, 0, BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, optimizedTransitions.data(), BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); NRI.CmdSetPipeline(commandBuffer, *Get(Pipeline::Composition)); @@ -4880,7 +4915,7 @@ void Sample::RenderFrame(uint32_t frameIndex) {Texture::Composed, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, {Texture::Mv, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, optimizedTransitions.data(), 0, 0, BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, optimizedTransitions.data(), BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); NRI.CmdSetPipeline(commandBuffer, *Get(Pipeline::TraceTransparent)); @@ -4922,7 +4957,7 @@ void Sample::RenderFrame(uint32_t frameIndex) {Texture::ViewZ, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, {Texture::Mv, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, optimizedTransitions.data(), 0, 0, BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, optimizedTransitions.data(), BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); NRI.CmdSetPipeline(commandBuffer, *Get(Pipeline::DlssBefore)); @@ -4943,7 +4978,7 @@ void Sample::RenderFrame(uint32_t frameIndex) // Output {Texture::DlssOutput, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, optimizedTransitions.data(), 0, 0, BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, optimizedTransitions.data(), BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); DlssDispatchDesc dlssDesc = {}; @@ -4971,7 +5006,7 @@ void Sample::RenderFrame(uint32_t frameIndex) // Output {Texture::DlssOutput, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, optimizedTransitions.data(), 0, 0, BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, optimizedTransitions.data(), BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); NRI.CmdSetPipeline(commandBuffer, *Get(Pipeline::DlssAfter)); @@ -4994,7 +5029,7 @@ void Sample::RenderFrame(uint32_t frameIndex) // Output {taaDst, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, optimizedTransitions.data(), 0, 0, BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, optimizedTransitions.data(), BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); NRI.CmdSetPipeline(commandBuffer, *Get(Pipeline::Taa)); @@ -5013,7 +5048,7 @@ void Sample::RenderFrame(uint32_t frameIndex) // Output {Texture::PreFinal, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, optimizedTransitions.data(), 0, 0, BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, optimizedTransitions.data(), BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); NRI.CmdSetPipeline(commandBuffer, *Get(Pipeline::Nis)); @@ -5044,7 +5079,7 @@ void Sample::RenderFrame(uint32_t frameIndex) // Output {Texture::Final, nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}, }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, optimizedTransitions.data(), 0, 0, BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, optimizedTransitions.data(), BuildOptimizedTransitions(transitions, helper::GetCountOf(transitions), optimizedTransitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); NRI.CmdSetPipeline(commandBuffer, *Get(Pipeline::Final)); @@ -5064,7 +5099,7 @@ void Sample::RenderFrame(uint32_t frameIndex) nri::TextureBarrierFromState(GetState(Texture::Final), {nri::AccessBits::COPY_SOURCE, nri::Layout::COPY_SOURCE}), nri::TextureBarrierFromUnknown(backBuffer->texture, {nri::AccessBits::COPY_DESTINATION, nri::Layout::COPY_DESTINATION}), }; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, transitions, 0, 0, (uint16_t)helper::GetCountOf(transitions)}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, transitions, (uint16_t)helper::GetCountOf(transitions)}; NRI.CmdBarrier(commandBuffer, transitionBarriers); NRI.CmdCopyTexture(commandBuffer, *backBuffer->texture, nullptr, *Get(Texture::Final), nullptr); @@ -5076,7 +5111,7 @@ void Sample::RenderFrame(uint32_t frameIndex) before.before = {nri::AccessBits::COPY_DESTINATION, nri::Layout::COPY_DESTINATION, nri::StageBits::COPY}; before.after = {nri::AccessBits::COLOR_ATTACHMENT, nri::Layout::COLOR_ATTACHMENT, nri::StageBits::COLOR_ATTACHMENT}; - nri::BarrierGroupDesc transitionBarriers = {nullptr, nullptr, &before, 0, 0, 1}; + nri::BarrierGroupDesc transitionBarriers = {nullptr, 0, nullptr, 0, &before, 1}; NRI.CmdBarrier(commandBuffer, transitionBarriers); nri::AttachmentsDesc desc = {}; @@ -5088,7 +5123,7 @@ void Sample::RenderFrame(uint32_t frameIndex) NRI.CmdEndRendering(commandBuffer); const nri::TextureBarrierDesc after = nri::TextureBarrierFromState(before, {nri::AccessBits::UNKNOWN, nri::Layout::PRESENT, nri::StageBits::ALL}); - transitionBarriers = {nullptr, nullptr, &after, 0, 0, 1}; + transitionBarriers = {nullptr, 0, nullptr, 0, &after, 1}; NRI.CmdBarrier(commandBuffer, transitionBarriers); } } diff --git a/Tests/BistroExterior.bin b/Tests/BistroExterior.bin index 2cff20f..1302ee9 100644 Binary files a/Tests/BistroExterior.bin and b/Tests/BistroExterior.bin differ diff --git a/Tests/BistroInterior.bin b/Tests/BistroInterior.bin index 56574ee..e0498ee 100644 Binary files a/Tests/BistroInterior.bin and b/Tests/BistroInterior.bin differ diff --git a/Tests/CornellBox.bin b/Tests/CornellBox.bin new file mode 100644 index 0000000..e3659ca Binary files /dev/null and b/Tests/CornellBox.bin differ diff --git a/Tests/Hair.bin b/Tests/Hair.bin index 1dda991..6a6812d 100644 Binary files a/Tests/Hair.bin and b/Tests/Hair.bin differ diff --git a/Tests/Kitchen.bin b/Tests/Kitchen.bin index a752da0..e63297d 100644 Binary files a/Tests/Kitchen.bin and b/Tests/Kitchen.bin differ diff --git a/Tests/ShaderBalls.bin b/Tests/ShaderBalls.bin index 1cd99dc..9115eb2 100644 Binary files a/Tests/ShaderBalls.bin and b/Tests/ShaderBalls.bin differ diff --git a/Tests/bistro.bin b/Tests/bistro.bin new file mode 100644 index 0000000..c1d7edb Binary files /dev/null and b/Tests/bistro.bin differ diff --git a/Tests/transparent-machines-pt1.bin b/Tests/transparent-machines-pt1.bin new file mode 100644 index 0000000..5a968cd Binary files /dev/null and b/Tests/transparent-machines-pt1.bin differ