diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index 767837b89..996426b8c 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -302,6 +302,10 @@ namespace dxvk { || !required.vulkan11Features.shaderDrawParameters) && (m_deviceFeatures.vulkan12Features.hostQueryReset || !required.vulkan12Features.hostQueryReset) + && (m_deviceFeatures.vulkan12Features.scalarBlockLayout + || !required.vulkan12Features.scalarBlockLayout) + && (m_deviceFeatures.vulkan12Features.uniformBufferStandardLayout + || !required.vulkan12Features.uniformBufferStandardLayout) && (m_deviceFeatures.ext4444Formats.formatA4R4G4B4 || !required.ext4444Formats.formatA4R4G4B4) && (m_deviceFeatures.ext4444Formats.formatA4B4G4R4 @@ -490,7 +494,9 @@ namespace dxvk { enabledFeatures.khrAccelerationStructureFeatures.accelerationStructure = m_deviceFeatures.khrAccelerationStructureFeatures.accelerationStructure; enabledFeatures.khrRayQueryFeatures.rayQuery = m_deviceFeatures.khrRayQueryFeatures.rayQuery; enabledFeatures.khrDeviceRayTracingPipelineFeatures.rayTracingPipeline = m_deviceFeatures.khrDeviceRayTracingPipelineFeatures.rayTracingPipeline; - + enabledFeatures.vulkan12Features.scalarBlockLayout = m_deviceFeatures.vulkan12Features.scalarBlockLayout; + enabledFeatures.vulkan12Features.uniformBufferStandardLayout = m_deviceFeatures.vulkan12Features.uniformBufferStandardLayout; + enabledFeatures.vulkan12Features.shaderInt8 = VK_TRUE; enabledFeatures.vulkan12Features.storageBuffer8BitAccess = VK_TRUE; enabledFeatures.vulkan12Features.uniformAndStorageBuffer8BitAccess = VK_TRUE; @@ -1200,6 +1206,10 @@ namespace dxvk { "\n shaderInt64 : ", features.core.features.shaderInt64 ? "1" : "0", "\n variableMultisampleRate : ", features.core.features.variableMultisampleRate ? "1" : "0", "\n hostQueryReset : ", features.vulkan12Features.hostQueryReset ? "1" : "0", + // NV-DXVK + "\n scalarBlockLayout : ", features.vulkan12Features.scalarBlockLayout ? "1" : "0", + "\n uniformBufferStandardLayout : ", features.vulkan12Features.uniformBufferStandardLayout ? "1" : "0", + // NV-DXVK end "\n", VK_EXT_4444_FORMATS_EXTENSION_NAME, "\n formatA4R4G4B4 : ", features.ext4444Formats.formatA4R4G4B4 ? "1" : "0", "\n formatA4B4G4R4 : ", features.ext4444Formats.formatA4B4G4R4 ? "1" : "0", diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index eeef66746..a2d7452b0 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -340,6 +340,13 @@ namespace dxvk { Rc clone(); // NV-DXVK end + + // NV-DXVK start: get access to VkDeviceMemory + const DxvkBufferHandle& getBufferHandle() { + return m_buffer; + } + // NV-DXVK end + protected: DxvkDevice* m_device; DxvkBufferCreateInfo m_info; diff --git a/src/dxvk/imgui/dxvk_imgui.cpp b/src/dxvk/imgui/dxvk_imgui.cpp index 56f7abb28..9aac39a84 100644 --- a/src/dxvk/imgui/dxvk_imgui.cpp +++ b/src/dxvk/imgui/dxvk_imgui.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -297,8 +297,8 @@ namespace dxvk { {UpscalerType::TAAU, "TAA-U"}, } }); - ImGui::ComboWithKey secondPlusRussianRouletteModeCombo { - "2nd+ Russian Roulette Mode", + ImGui::ComboWithKey secondPlusBounceRussianRouletteModeCombo { + "2nd+ Bounce Russian Roulette Mode", ImGui::ComboWithKey::ComboEntries { { {RussianRouletteMode::ThroughputBased, "Throughput Based"}, {RussianRouletteMode::SpecularBased, "Specular Based"} @@ -2637,7 +2637,7 @@ namespace dxvk { ImGui::DragFloat("1st bounce: Min Continue Probability", &RtxOptions::Get()->russianRoulette1stBounceMinContinueProbabilityObject(), 0.01f, 0.0f, 1.0f, "%.3f", sliderFlags); ImGui::DragFloat("1st bounce: Max Continue Probability", &RtxOptions::Get()->russianRoulette1stBounceMaxContinueProbabilityObject(), 0.01f, 0.0f, 1.0f, "%.3f", sliderFlags); - secondPlusRussianRouletteModeCombo.getKey(&RtxOptions::Get()->russianRouletteModeObject()); + secondPlusBounceRussianRouletteModeCombo.getKey(&RtxOptions::Get()->russianRouletteModeObject()); if (RtxOptions::Get()->russianRouletteMode() == RussianRouletteMode::ThroughputBased) { ImGui::DragFloat("2nd+ bounce: Max Continue Probability", &RtxOptions::Get()->russianRouletteMaxContinueProbabilityObject(), 0.01f, 0.0f, 1.0f, "%.3f", sliderFlags); diff --git a/src/dxvk/rtx_render/rtx_context.cpp b/src/dxvk/rtx_render/rtx_context.cpp index 2466fc14a..a175c9fcf 100644 --- a/src/dxvk/rtx_render/rtx_context.cpp +++ b/src/dxvk/rtx_render/rtx_context.cpp @@ -446,7 +446,7 @@ namespace dxvk { const bool isRaytracingEnabled = RtxOptions::Get()->enableRaytracing(); - if(isRaytracingEnabled && isCameraValid) { + if (isRaytracingEnabled && isCameraValid) { if (targetImage == nullptr) { targetImage = m_state.om.renderTargets.color[0].view->image(); } @@ -455,7 +455,7 @@ namespace dxvk { const bool captureScreenImage = s_triggerScreenshot || (captureTestScreenshot && !s_capturePrePresentTestScreenshot); const bool captureDebugImage = RtxOptions::Get()->shouldCaptureDebugImage(); - if(s_triggerUsdCapture) { + if (s_triggerUsdCapture) { s_triggerUsdCapture = false; m_common->capturer()->triggerNewCapture(); } @@ -522,6 +522,7 @@ namespace dxvk { // Path Tracing dispatchPathTracing(rtOutput); + // RTXDI confidence m_common->metaRtxdiRayQuery().dispatchConfidence(this, rtOutput); // ReSTIR GI @@ -1338,8 +1339,9 @@ namespace dxvk { denoiseInput.frameTimeMs = frameTimeMilliseconds; denoiseInput.reset = m_resetHistory; - if(RtxOptions::Get()->useRTXDI() && m_common->metaRtxdiRayQuery().getEnableDenoiserConfidence()) + if (RtxOptions::Get()->useRTXDI() && m_common->metaRtxdiRayQuery().getEnableDenoiserConfidence()) { denoiseInput.confidence = &rtOutput.getCurrentRtxdiConfidence().resource(Resources::AccessType::Read); + } DxvkDenoise::Output denoiseOutput; denoiseOutput.diffuse_hitT = &rtOutput.m_primaryDirectDiffuseRadiance.resource(Resources::AccessType::Write); @@ -1479,7 +1481,7 @@ namespace dxvk { // The tone curve shouldn't be too different between raytracing modes, // but the reset of denoised buffers causes wide tone curve differences // until it converges and thus making comparison of raytracing mode outputs more difficult - if(RtxOptions::Get()->tonemappingMode() == TonemappingMode::Global) { + if (RtxOptions::Get()->tonemappingMode() == TonemappingMode::Global) { DxvkToneMapping& toneMapper = m_common->metaToneMapping(); toneMapper.dispatch(this, getResourceManager().getSampler(VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER), diff --git a/src/dxvk/rtx_render/rtx_debug_view.cpp b/src/dxvk/rtx_render/rtx_debug_view.cpp index 70c6a756f..c99fb0226 100644 --- a/src/dxvk/rtx_render/rtx_debug_view.cpp +++ b/src/dxvk/rtx_render/rtx_debug_view.cpp @@ -244,13 +244,13 @@ namespace dxvk { {DEBUG_VIEW_NOISY_DEMODULATED_SECONDARY_COMBINED_SPECULAR_RADIANCE,"Secondary Combined Specular: Demodulated Noisy Color"}, {DEBUG_VIEW_DENOISED_SECONDARY_COMBINED_SPECULAR_RADIANCE, "Secondary Combined Specular: Denoised Color"}, - { DEBUG_VIEW_NOISY_PRIMARY_DIRECT_RADIANCE, "Primary Direct: Noisy Color" }, - { DEBUG_VIEW_NOISY_PRIMARY_INDIRECT_RADIANCE, "Primary Indirect: Noisy Color" }, - { DEBUG_VIEW_NOISY_PRIMARY_RADIANCE, "Primary: Noisy Color" }, - { DEBUG_VIEW_NOISY_SECONDARY_DIRECT_RADIANCE, "Secondary Direct: Noisy Color" }, - { DEBUG_VIEW_NOISY_SECONDARY_INDIRECT_RADIANCE, "Secondary Indirect: Noisy Color" }, - { DEBUG_VIEW_NOISY_SECONDARY_RADIANCE, "Secondary: Noisy Color" }, - { DEBUG_VIEW_NOISY_RADIANCE, "Primary + Secondary: Noisy Color" }, + {DEBUG_VIEW_NOISY_PRIMARY_DIRECT_RADIANCE, "Primary Direct: Noisy Color" }, + {DEBUG_VIEW_NOISY_PRIMARY_INDIRECT_RADIANCE, "Primary Indirect: Noisy Color" }, + {DEBUG_VIEW_NOISY_PRIMARY_RADIANCE, "Primary: Noisy Color" }, + {DEBUG_VIEW_NOISY_SECONDARY_DIRECT_RADIANCE, "Secondary Direct: Noisy Color" }, + {DEBUG_VIEW_NOISY_SECONDARY_INDIRECT_RADIANCE, "Secondary Indirect: Noisy Color" }, + {DEBUG_VIEW_NOISY_SECONDARY_RADIANCE, "Secondary: Noisy Color" }, + {DEBUG_VIEW_NOISY_RADIANCE, "Primary + Secondary: Noisy Color" }, {DEBUG_VIEW_INSTRUMENTATION_THREAD_DIVERGENCE, "Thread Divergence(Debug Knob.x)"}, {DEBUG_VIEW_NAN, "Inf/NaN Check"}, @@ -488,7 +488,7 @@ namespace dxvk { } } - void DebugView::processOutputStatistics(Rc& ctx) { + void DebugView::processOutputStatistics(Rc& ctx) { if (m_showOutputStatistics) { const uint32_t frameIdx = ctx->getDevice()->getCurrentFrameId(); @@ -853,8 +853,6 @@ namespace dxvk { ctx->clearColorImage(m_instrumentation.image, clearColor, subRange); } } - - processOutputStatistics(ctx); } DebugViewArgs DebugView::getCommonDebugViewArgs( @@ -998,6 +996,9 @@ namespace dxvk { const Resources::RaytracingOutput& rtOutput) { ScopedGpuProfileZone(ctx, "Debug View"); + // Process output statistics now before we schedule a debug view dispatch that updates them + processOutputStatistics(ctx); + // Inputs ctx->bindResourceView(DEBUG_VIEW_BINDING_DENOISED_PRIMARY_DIRECT_DIFFUSE_RADIANCE_HIT_T_INPUT, rtOutput.m_primaryDirectDiffuseRadiance.view(Resources::AccessType::Read), nullptr); diff --git a/src/dxvk/rtx_render/rtx_debug_view.h b/src/dxvk/rtx_render/rtx_debug_view.h index 5dbdcf87f..d56e527d1 100644 --- a/src/dxvk/rtx_render/rtx_debug_view.h +++ b/src/dxvk/rtx_render/rtx_debug_view.h @@ -85,7 +85,7 @@ namespace dxvk { virtual void onFrameBegin(Rc& ctx, const VkExtent3D& downscaledExtent, const VkExtent3D& targetExtent) override; private: - void processOutputStatistics(Rc& ctx); + void processOutputStatistics(Rc& ctx); void showOutputStatistics(); bool shouldDebugViewDispatch() const; void createConstantsBuffer(); diff --git a/src/dxvk/rtx_render/rtx_options.h b/src/dxvk/rtx_render/rtx_options.h index d76c3aa27..61e791654 100644 --- a/src/dxvk/rtx_render/rtx_options.h +++ b/src/dxvk/rtx_render/rtx_options.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -1434,9 +1434,9 @@ namespace dxvk { // General bool getCaptureShowMenuOnHotkey() const { return m_captureShowMenuOnHotkey.getValue(); } bool getCaptureInstances() const { - if(m_captureNoInstance.getValue() != m_captureNoInstance.getDefaultValue()) { + if (m_captureNoInstance.getValue() != m_captureNoInstance.getDefaultValue()) { Logger::warn("rtx.captureNoInstance has been deprecated, but will still be respected for the time being, unless rtx.captureInstances is set."); - if(m_captureInstances.getValue() != m_captureInstances.getDefaultValue()) { + if (m_captureInstances.getValue() != m_captureInstances.getDefaultValue()) { return m_captureInstances; } return !m_captureNoInstance; diff --git a/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp b/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp index d0b10ab84..ca9d7e902 100644 --- a/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp +++ b/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp @@ -173,7 +173,9 @@ namespace dxvk { } } - void DxvkPathtracerGbuffer::dispatch(RtxContext* ctx, const Resources::RaytracingOutput& rtOutput) { + void DxvkPathtracerGbuffer::dispatch( + RtxContext* ctx, + const Resources::RaytracingOutput& rtOutput) { ScopedGpuProfileZone(ctx, "Gbuffer Raytracing"); // Bind resources @@ -348,11 +350,12 @@ namespace dxvk { } } - DxvkRaytracingPipelineShaders DxvkPathtracerGbuffer::getPipelineShaders(const bool isPSRPass, - const bool useRayQuery, - const bool serEnabled, - const bool ommEnabled, - const bool includePortals) { + DxvkRaytracingPipelineShaders DxvkPathtracerGbuffer::getPipelineShaders( + const bool isPSRPass, + const bool useRayQuery, + const bool serEnabled, + const bool ommEnabled, + const bool includePortals) { ScopedCpuProfileZone(); DxvkRaytracingPipelineShaders shaders; if (useRayQuery) { diff --git a/src/dxvk/rtx_render/rtx_pathtracer_integrate_direct.cpp b/src/dxvk/rtx_render/rtx_pathtracer_integrate_direct.cpp index b5559e5b2..3eda13154 100644 --- a/src/dxvk/rtx_render/rtx_pathtracer_integrate_direct.cpp +++ b/src/dxvk/rtx_render/rtx_pathtracer_integrate_direct.cpp @@ -102,8 +102,9 @@ namespace dxvk { const bool isOpacityMicromapSupported = OpacityMicromapManager::checkIsOpacityMicromapSupported(*m_device); - for (int32_t ommEnabled = isOpacityMicromapSupported; ommEnabled > 0; ommEnabled--) + for (int32_t ommEnabled = isOpacityMicromapSupported; ommEnabled > 0; ommEnabled--) { pipelineManager.registerRaytracingShaders(getPipelineShaders(true, ommEnabled)); + } DxvkComputePipelineShaders shaders; shaders.cs = getComputeShader(); diff --git a/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp b/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp index ad4988961..56027ca19 100644 --- a/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp +++ b/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp @@ -411,12 +411,13 @@ namespace dxvk { } } - DxvkRaytracingPipelineShaders DxvkPathtracerIntegrateIndirect::getPipelineShaders(const bool useRayQuery, - const bool serEnabled, - const bool ommEnabled, - const bool useNeeCache, - const bool includePortals, - const bool pomEnabled) { + DxvkRaytracingPipelineShaders DxvkPathtracerIntegrateIndirect::getPipelineShaders( + const bool useRayQuery, + const bool serEnabled, + const bool ommEnabled, + const bool useNeeCache, + const bool includePortals, + const bool pomEnabled) { DxvkRaytracingPipelineShaders shaders; if (useRayQuery) { diff --git a/src/dxvk/shaders/rtx/README.md b/src/dxvk/shaders/rtx/README.md index 6af92b780..f001f795a 100644 --- a/src/dxvk/shaders/rtx/README.md +++ b/src/dxvk/shaders/rtx/README.md @@ -144,10 +144,13 @@ void main(uvec2 threadID : SV_DispatchThreadID) - Delimiter commas (function calls or parameter lists) or semicolons (in for loops) should be followed by a space (or a new line if needed to split across lines). - Lines should be kept at a reasonable length (100-120 ish characters max typically). Excessively long lines should be split up with newlines. - Splitting across lines should be done ideally at delimiters or other logical points, for example after each item in a function call, after a bitwise or boolean and/or in a chain of expressions, or even at "important" binary math operators. - +- An empty space should be between if/for/while/switch and (. +- Header files should be guarded with #pragma once. A combined example of these stylistic choices in use is as follows: ```glsl +#pragma once + struct Foo { uint fooBarBaz; @@ -169,33 +172,37 @@ vec3 exampleHelper(Foo foo, bool test, inout bool specialFlag) // Do some calculations conditionally - if (foo.anotherFoo > someConstant) + int loopCounter = 2; + while (loopCounter-- > 0) { - switch (foo.anotherFoo) + if (foo.anotherFoo > someConstant) { - // Note: Fallthrough to Apple type. - default: - case anotherFooTypeApple: - someExcessivelyLongFunctionNameForDemonstrationPurposes( - foo.anotherBaz + 1.0h, - foo.anotherBaz / 2.0h, - foo.anotherBaz * 5.0h); - - break; - case anotherFooTypeOrange: - if ( - (foo.fooBarBaz == 26 && foo.anotherBaz == 2.0h) || - foo.fooBarBaz == 5 - ) + switch (foo.anotherFoo) { - const uint someScalar = uint(foo.anotherFoo) * foo.fooBarBaz; - - specialFlag = true; - - return vec3(float(someScalar)); + // Note: Fallthrough to Apple type. + default: + case anotherFooTypeApple: + someExcessivelyLongFunctionNameForDemonstrationPurposes( + foo.anotherBaz + 1.0h, + foo.anotherBaz / 2.0h, + foo.anotherBaz * 5.0h); + + break; + case anotherFooTypeOrange: + if ( + (foo.fooBarBaz == 26 && foo.anotherBaz == 2.0h) || + foo.fooBarBaz == 5 + ) + { + const uint someScalar = uint(foo.anotherFoo) * foo.fooBarBaz; + + specialFlag = true; + + return vec3(float(someScalar)); + } + + break; } - - break; } } diff --git a/src/dxvk/shaders/rtx/algorithm/geometry_resolver.slangh b/src/dxvk/shaders/rtx/algorithm/geometry_resolver.slangh index f5bed1f8f..810fe9903 100644 --- a/src/dxvk/shaders/rtx/algorithm/geometry_resolver.slangh +++ b/src/dxvk/shaders/rtx/algorithm/geometry_resolver.slangh @@ -1030,22 +1030,20 @@ void geometryResolverOutputDebugView(uvec2 pixelCoordinate) } } -// Note: This function adds in a diffuse layer contribution for the surface from a combined diffuse layer weight. Do note this weight is typically +// This function calculates a diffuse layer contribution for the surface from a combined diffuse layer weight. Do note this weight is typically // made up of a shared component and a component from the reflection and/or translucent side of things. This should be added in regardless of if reflection // or transmission PSR is actually done, just since there's no need to make this contribution noisy for no reason. This contribution does not work quite // properly however when reflection or transmission PSR are individually disabled right now, we'd need to conditionally have the diffuse layer weight // only include the relevant lobe contributions rather than both always. -void approximateDiffuseLayerRadiance(SurfaceInteraction surfaceInteraction, +vec3 approximateDiffuseLayerRadiance(SurfaceInteraction surfaceInteraction, PortalSpace2BitsType portalSpace, - const f16vec3 diffuseLayerWeight, - const f16vec3 attenuation, - inout vec3 radiance) + const f16vec3 diffuseLayerWeight) { // Note: Important early out check to avoid expensive radiance cache lookups when they are not needed (as the diffuse layer // weight will be set to 0 in these cases). if (all(diffuseLayerWeight <= 0.0)) { - return; + return vec3(0); } // Fetch data from the radiance cache for the current surface interaction @@ -1062,7 +1060,7 @@ void approximateDiffuseLayerRadiance(SurfaceInteraction surfaceInteraction, // Todo: We should really be using spherical harmonics in the future for this to actually evaluate a directional contribution of the diffuse // layer as right now isotropic scattering looks a bit darker than it should (most the light should be backscattered for such a surface realistically // rather than equally scattered around). - radiance += diffuseLayerWeight * accumulatedOutgoingRadiance * attenuation; + return diffuseLayerWeight * accumulatedOutgoingRadiance; } void geometryResolverVertex( @@ -1194,7 +1192,7 @@ void geometryResolverVertex( } else { - if(cb.domeLightArgs.active) + if (cb.domeLightArgs.active) { emissiveRadiance += cb.domeLightArgs.radiance * sampleDomeLightTexture(LinearWrapSampler, geometryResolverState.direction, cb.domeLightArgs.textureIndex, cb.domeLightArgs.worldToLightTransform); } @@ -1322,11 +1320,11 @@ void geometryResolverVertex( // Note: Using attenuation here to factor in the "standard" attenuation from resolving beforehand. Importantly this // code needs to come before the PSRR attenuation is factored in otherwise the reflection attenuation will improperly modulate the // incident diffuse layer contribution. - vec3 diffuseLayerRadiance = 0.0; - approximateDiffuseLayerRadiance( - surfaceInteraction, geometryResolverState.portalSpace, diffuseLayerWeight, - geometryResolverState.attenuation, diffuseLayerRadiance); - + vec3 diffuseLayerRadiance = approximateDiffuseLayerRadiance( + surfaceInteraction, geometryResolverState.portalSpace, diffuseLayerWeight); + + diffuseLayerRadiance *= geometryResolverState.attenuation; + // Output diffuse component from the glass to a separate particle layer so that it won't get mixed with background noise. if (cb.outputParticleLayer && any(diffuseLayerRadiance > 0.0)) { @@ -1734,7 +1732,7 @@ void geometryPSRResolverVertex( } else { - if(cb.domeLightArgs.active) + if (cb.domeLightArgs.active) { emissiveRadiance += cb.domeLightArgs.radiance * sampleDomeLightTexture(LinearWrapSampler, ray.direction, cb.domeLightArgs.textureIndex, cb.domeLightArgs.worldToLightTransform); } @@ -1805,10 +1803,10 @@ void geometryPSRResolverVertex( // Note: This code needs to come before the PSR attenuation is factored in otherwise the reflection or transmission attenuation will improperly // modulate the diffuse layer contribution. - vec3 diffuseLayerRadiance = 0.0; - approximateDiffuseLayerRadiance( - surfaceInteraction, geometryPSRResolverState.portalSpace, diffuseLayerWeight, - geometryPSRResolverState.attenuation, diffuseLayerRadiance); + vec3 diffuseLayerRadiance = approximateDiffuseLayerRadiance( + surfaceInteraction, geometryPSRResolverState.portalSpace, diffuseLayerWeight); + + diffuseLayerRadiance *= geometryPSRResolverState.attenuation; if (cb.outputParticleLayer) { diff --git a/src/dxvk/shaders/rtx/algorithm/integrator_direct.slangh b/src/dxvk/shaders/rtx/algorithm/integrator_direct.slangh index 10083e0b9..e109d4b4b 100644 --- a/src/dxvk/shaders/rtx/algorithm/integrator_direct.slangh +++ b/src/dxvk/shaders/rtx/algorithm/integrator_direct.slangh @@ -341,7 +341,6 @@ void integrateDirectPath( else { // Select and sample a light for NEE via RIS - risLightSampleValid = sampleLightRIS( randomState, primarySurfaceInteraction, opaqueSurfaceMaterialInteraction, primaryMinimalRayInteraction.viewDirection, diff --git a/src/dxvk/shaders/rtx/algorithm/integrator_indirect.slangh b/src/dxvk/shaders/rtx/algorithm/integrator_indirect.slangh index 049190a60..6a3be6fd0 100644 --- a/src/dxvk/shaders/rtx/algorithm/integrator_indirect.slangh +++ b/src/dxvk/shaders/rtx/algorithm/integrator_indirect.slangh @@ -49,7 +49,7 @@ PathState pathStateCreateEmpty(GeometryFlags geometryFlags) pathState.coneSpreadAngle = cb.screenSpacePixelSpreadHalfAngle; pathState.radiance = vec3(0.0f, 0.0f, 0.0f); - pathState.throughput = vec3(1.0f); + pathState.throughput = f16vec3(1.h); pathState.firstBounceHitDistance = kEmptyPixelHitDistance; pathState.mediumMaterialIndex = BINDING_INDEX_INVALID; @@ -68,7 +68,9 @@ PathState pathStateCreateEmpty(GeometryFlags geometryFlags) pathState.rayMask = OBJECT_MASK_ALL | (geometryFlags.objectMask & OBJECT_MASK_ALL_DYNAMIC); if (geometryFlags.isViewModel) + { updateRayMaskForRayOriginFromViewModelSurface(pathState.rayMask, pathState.portalSpace); + } return pathState; } @@ -152,8 +154,8 @@ bool sampleLightNeeCache(inout RAB_RandomSamplerState rtxdiRNG, inout RNG random const bool isSubsurface = isSubsurfaceMaterial(opaqueSurfaceMaterialInteraction); - // Note: We are NOT taking transmission into consideration, because calculating probability of transmission have some costs. - // Also, it's approximate importance and no need to be exact, we just skip the calculation here for better performance. + // Note: We are NOT taking transmission into consideration, because calculating probability of transmission has some costs. + // Also, it's an approximate importance sample and does not need to be exact, so we just skip the calculation here for better performance. float16_t specularRatio = calcBt709Luminance(opaqueSurfaceMaterialInteraction.baseReflectivity) / calcBt709Luminance(opaqueSurfaceMaterialInteraction.albedo + opaqueSurfaceMaterialInteraction.baseReflectivity); vec2 uniformRandomNumber = vec2(getNextSampleBlueNoise(randomState), getNextSampleBlueNoise(randomState)); @@ -169,6 +171,7 @@ bool sampleLightNeeCache(inout RAB_RandomSamplerState rtxdiRNG, inout RNG random lightSample = memoryPolymorphicLightSampleArea(memoryPolymorphicLight, sampleCoordinates0, surfaceInteraction); return true; } + return false; } @@ -323,7 +326,7 @@ void integratePathVertex( // Note: True misses going out into infinity will have no hit in the ray interaction and the continue resolving flag set to false. This is in contrast to misses // which may require further resolving which may be needed in cases of skipping specific pieces of geometry while still wishing to continue traversal. - if(cb.domeLightArgs.active) + if (cb.domeLightArgs.active) { emissiveRadiance += cb.domeLightArgs.radiance * sampleDomeLightTexture(LinearWrapSampler, pathState.direction, cb.domeLightArgs.textureIndex, cb.domeLightArgs.worldToLightTransform); } @@ -538,7 +541,6 @@ void integratePathVertex( if (!isWithinGbuffer) { - // Select and sample a light for NEE via RIS if (NEE_CACHE_ENABLE && cb.neeCacheArgs.enable && cb.neeCacheArgs.enableAnalyticalLight) { lightSampleValid = sampleLightNeeCache(rtxdiRNG, randomState, pathState.neeCacheCellOffset, @@ -547,6 +549,7 @@ void integratePathVertex( } else { + // Select and sample a light for NEE via RIS lightSampleValid = sampleLightRIS( randomState, surfaceInteraction, opaqueSurfaceMaterialInteraction, rayInteraction.viewDirection, diff --git a/src/dxvk/shaders/rtx/algorithm/nee_cache_light.slangh b/src/dxvk/shaders/rtx/algorithm/nee_cache_light.slangh index 0fbc28f55..d1241f3d9 100644 --- a/src/dxvk/shaders/rtx/algorithm/nee_cache_light.slangh +++ b/src/dxvk/shaders/rtx/algorithm/nee_cache_light.slangh @@ -159,7 +159,7 @@ struct NEECacheUtils lightSample.normal = surfaceInteraction.interpolatedNormal; float lightPdf = trianglePdf; triangleArea = surfaceInteraction.triangleArea; - if(useSolidAnglePdf) + if (useSolidAnglePdf) { lightPdf *= calculateLightSamplingSolidAnglePDF( surfaceInteraction.triangleArea, surfaceInteraction.position, surfaceInteraction.triangleNormal, shadingPosition); diff --git a/src/dxvk/shaders/rtx/algorithm/path_state.slangh b/src/dxvk/shaders/rtx/algorithm/path_state.slangh index 712004ad0..c69ef453a 100644 --- a/src/dxvk/shaders/rtx/algorithm/path_state.slangh +++ b/src/dxvk/shaders/rtx/algorithm/path_state.slangh @@ -218,6 +218,8 @@ struct PathState : IBasePayloadState set { _roughness = f16ToUnorm8(newValue); } } + // Methods + // Calculates an RNG offset at a start of a bounce set in the path state uint calculateRNGOffset(uint sampleOffset) { diff --git a/src/dxvk/shaders/rtx/algorithm/resolve.slangh b/src/dxvk/shaders/rtx/algorithm/resolve.slangh index aae3d5f6e..a0aa8b7bc 100644 --- a/src/dxvk/shaders/rtx/algorithm/resolve.slangh +++ b/src/dxvk/shaders/rtx/algorithm/resolve.slangh @@ -831,7 +831,7 @@ void resolveVertexUnordered( const uint kMaxUnorderedResolveSteps = 32; #endif - for(uint step=0 ; step(Ray ray, RayHitInfo ra { // View model instances don't have an inter-frame mapping, assume they're transparent if (rayHitInfo.customIndex & CUSTOM_INDEX_IS_VIEW_MODEL) + { return 1.0; + } // Map the surface index from the previous frame to the current frame rayInteraction.surfaceIndex = surfaceMapping[rayInteraction.surfaceIndex]; if (rayInteraction.surfaceIndex == BINDING_INDEX_INVALID) + { // Surface no longer exists - assume it was transparent, which is safer than // assuming an opaque surface, because that would introduce more bias in ReSTIR return 1.0; + } } Surface surface = surfaces[uint(rayInteraction.surfaceIndex)]; @@ -85,8 +89,10 @@ f16vec3 handleVisibilityVertex(Ray ray, RayHitInfo ra SurfaceInteraction surfaceInteraction = surfaceInteractionCreate(surface, rayInteraction, ray, usePreviousTLAS); if (isSurfaceClipped(surface, surfaceInteraction)) + { // Ignore parts of surfaces that are under clip planes return 1.0; + } const MemoryPolymorphicSurfaceMaterial memoryPolymorphicSurfaceMaterial = surfaceMaterials[rayInteraction.surfaceIndex]; @@ -115,7 +121,7 @@ f16vec3 handleVisibilityVertex(Ray ray, RayHitInfo ra return 1.0h - opaqueSurfaceMaterialInteraction.opacity; } - if(VisibilityMode & visibilityModeEnableSubsurfaceMaterials) + if (VisibilityMode & visibilityModeEnableSubsurfaceMaterials) { const float16_t normalDotOutputDirection = dot(-ray.direction, opaqueSurfaceMaterialInteraction.shadingNormal); if (normalDotOutputDirection < materialEpsilon) @@ -191,8 +197,11 @@ float16_t getRayPortalTransparency( // Treat rays coming from behind the portal as not intersecting with it. const float NdotD = dot(ray.direction, portal.normal); t = dot(portal.centroid - ray.origin, portal.normal) / NdotD; - if (isinf(t) || isnan(t)) t = -1.0; - + if (isinf(t) || isnan(t)) + { + t = -1.0; + } + if (0 <= t && t <= ray.tMax && NdotD < 0) { const vec3 p = ray.origin + ray.direction * t; @@ -308,13 +317,14 @@ VisibilityResult traceVisibilityRay( : RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH; // Note: Enable culling of backfacing triangles only if culling is actually desired on this visibility ray. - if(cb.enableCullingSecondaryRays) { + if (cb.enableCullingSecondaryRays) + { rayFlags |= (VisibilityMode & visibilityModeDisableCulling) ? 0 : RAY_FLAG_CULL_BACK_FACING_TRIANGLES; } - while(true) + while (true) { RayQuery<0> rayQuery = RayQuery<0>(); @@ -352,7 +362,7 @@ VisibilityResult traceVisibilityRay( if ((float16_t(1) - calcBt709Luminance(result.attenuation)) >= cb.resolveOpaquenessThreshold) { // If opaque hit is not considered in the attenuation term, need to recover previous attenuation. - if(!clearOpaqueHitAttenuation) + if (!clearOpaqueHitAttenuation) { result.attenuation = prevAttenuation; } @@ -364,7 +374,7 @@ VisibilityResult traceVisibilityRay( if (rayQuery.CommittedStatus() == COMMITTED_TRIANGLE_HIT) { - if(clearOpaqueHitAttenuation) + if (clearOpaqueHitAttenuation) { result.attenuation = f16vec3(0.0); } diff --git a/src/dxvk/shaders/rtx/concept/light/light_helper.slangh b/src/dxvk/shaders/rtx/concept/light/light_helper.slangh index 458cb7cdb..0432993d2 100644 --- a/src/dxvk/shaders/rtx/concept/light/light_helper.slangh +++ b/src/dxvk/shaders/rtx/concept/light/light_helper.slangh @@ -39,7 +39,7 @@ struct LightSample float3 sampleDomeLightTexture(SamplerState sampler, float3 worldDirection, uint32_t domeLightTextureIndex, float4x4 worldToDomeLightTransform) { - if(domeLightTextureIndex == BINDING_INDEX_INVALID) + if (domeLightTextureIndex == BINDING_INDEX_INVALID) { return 1..xxx; } diff --git a/src/dxvk/shaders/rtx/concept/surface/surface_interaction.slangh b/src/dxvk/shaders/rtx/concept/surface/surface_interaction.slangh index 2a0f7e3be..f397dd822 100644 --- a/src/dxvk/shaders/rtx/concept/surface/surface_interaction.slangh +++ b/src/dxvk/shaders/rtx/concept/surface/surface_interaction.slangh @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -94,7 +94,9 @@ void computeAnisotropicEllipseAxes( bool isSurfaceClipped(Surface surface, MinimalSurfaceInteraction surfaceInteraction) { if (!surface.isClipPlaneEnabled) + { return false; + } const float clipDistance = dot(surface.clipPlane.xyz, surfaceInteraction.position) + surface.clipPlane.w; @@ -189,10 +191,14 @@ SurfaceInteraction surfaceInteractionCreate( { const uint indexBufferIndex = surface.indexBufferIndex; - if(surface.indexStride == 4) + if (surface.indexStride == 4) + { idx[i] = BUFFER_ARRAY(indices32, indexBufferIndex, indexIndex); + } else + { idx[i] = BUFFER_ARRAY(indices, indexBufferIndex, indexIndex); + } } else { diff --git a/src/dxvk/shaders/rtx/concept/surface_material/opaque_surface_material.slangh b/src/dxvk/shaders/rtx/concept/surface_material/opaque_surface_material.slangh index 3f5fe1168..77e6b56ea 100644 --- a/src/dxvk/shaders/rtx/concept/surface_material/opaque_surface_material.slangh +++ b/src/dxvk/shaders/rtx/concept/surface_material/opaque_surface_material.slangh @@ -53,7 +53,7 @@ OpaqueSurfaceMaterial opaqueSurfaceMaterialCreate(uint16_t surfaceMaterialIndex, opaqueSurfaceMaterial.tangentTextureIndex = BINDING_INDEX_INVALID; // If we're just doing a visibility check, we dont need these parameters. - if(visibilityCheckOnly) + if (visibilityCheckOnly) { opaqueSurfaceMaterial.emissiveColorTextureIndex = BINDING_INDEX_INVALID; opaqueSurfaceMaterial.roughnessTextureIndex = BINDING_INDEX_INVALID; diff --git a/src/dxvk/shaders/rtx/concept/surface_material/opaque_surface_material_interaction.slangh b/src/dxvk/shaders/rtx/concept/surface_material/opaque_surface_material_interaction.slangh index 4f2b0f587..ca130c759 100644 --- a/src/dxvk/shaders/rtx/concept/surface_material/opaque_surface_material_interaction.slangh +++ b/src/dxvk/shaders/rtx/concept/surface_material/opaque_surface_material_interaction.slangh @@ -255,7 +255,7 @@ float3 pomCalculateTexcoord( // raymarch to find intersection float currDepth = 0.0f, prevHeight = 0.0f; iterations = 0; - while(currDepth < currHeight) + while (currDepth < currHeight) { iterations++; currTexcoord -= step; @@ -306,7 +306,7 @@ float pomSampleVisibility( currHeight = pomSampleHeight(heightTextureIdx, samplerIndex, currTexcoord); currDepth -= layerSize; - if(currHeight < currDepth) + if (currHeight < currDepth) { visibility -= (currDepth - currHeight) / layerSize; } @@ -955,7 +955,7 @@ SurfaceMaterialInteractionLobeSample opaqueSurfaceMaterialInteractionCalcLobeSam diffuseReflectionProbability, specularReflectionProbability, opacityTransmissionProbability, diffuseTransmissionProbability); SurfaceMaterialInteractionLobeSample surfaceMaterialInteractionLobeSample; - if(!isValid) + if (!isValid) { // Note: Default to sampling specular lobe when no lobe desires to be sampled from. Ideally this could just be skipped entirely as // a sample though, but we currently do not support that logic, so for now we pick specular since it will generate more coherent diff --git a/src/dxvk/shaders/rtx/concept/surface_material/surface_material.h b/src/dxvk/shaders/rtx/concept/surface_material/surface_material.h index 80b90fa5f..cf42f8f2f 100644 --- a/src/dxvk/shaders/rtx/concept/surface_material/surface_material.h +++ b/src/dxvk/shaders/rtx/concept/surface_material/surface_material.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,8 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#ifndef SURFACE_MATERIAL_H -#define SURFACE_MATERIAL_H +#pragma once #include "rtx/utility/shader_types.h" #include "../../utility/shared_constants.h" @@ -246,5 +245,3 @@ struct PolymorphicSurfaceMaterialInteraction uint8_t type; }; - -#endif \ No newline at end of file diff --git a/src/dxvk/shaders/rtx/concept/surface_material/translucent_surface_material.slangh b/src/dxvk/shaders/rtx/concept/surface_material/translucent_surface_material.slangh index b008b4a34..8c2affcc8 100644 --- a/src/dxvk/shaders/rtx/concept/surface_material/translucent_surface_material.slangh +++ b/src/dxvk/shaders/rtx/concept/surface_material/translucent_surface_material.slangh @@ -56,7 +56,7 @@ TranslucentSurfaceMaterial translucentSurfaceMaterialCreate(uint16_t surfaceMate translucentSurfaceMaterial.sourceSurfaceMaterialIndex = surfaceMaterialIndex; // If we're just doing a visibility check, we dont need these parameters, only those for attenuation. - if(visibilityCheckOnly) + if (visibilityCheckOnly) { translucentSurfaceMaterial.normalTextureIndex = BINDING_INDEX_INVALID; translucentSurfaceMaterial.emissiveColorTextureIndex = BINDING_INDEX_INVALID; diff --git a/src/dxvk/shaders/rtx/concept/surface_material/translucent_surface_material_interaction.slangh b/src/dxvk/shaders/rtx/concept/surface_material/translucent_surface_material_interaction.slangh index e6a353bd6..6e2ef7b43 100644 --- a/src/dxvk/shaders/rtx/concept/surface_material/translucent_surface_material_interaction.slangh +++ b/src/dxvk/shaders/rtx/concept/surface_material/translucent_surface_material_interaction.slangh @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -508,7 +508,7 @@ SurfaceMaterialInteractionSample translucentSurfaceMaterialInteractionCalcSpecul const vec3 normal = normalize(vec3(translucentSurfaceMaterialInteraction.shadingNormal)); const vec3 outputDirection = normalize(vec3(minimalRayInteraction.viewDirection)); - // Calcuate the microfacet normal + // Calculate the microfacet normal // Note: Typically the microfacet normal would be sampled from so this would be known upfront in a sampling // method, due to being a dirac distribution though we always know it'll be the same as the normal. @@ -716,7 +716,7 @@ SurfaceMaterialInteractionPSRSample translucentSurfaceMaterialInteractionCalcPSR const vec3 normal = normalize(vec3(translucentSurfaceMaterialInteraction.shadingNormal)); const vec3 outputDirection = normalize(vec3(minimalRayInteraction.viewDirection)); - // Calcuate the microfacet normal + // Calculate the microfacet normal // Note: Typically the microfacet normal would be sampled from so this would be known upfront in a sampling // method, due to being a dirac distribution though we always know it'll be the same as the normal. @@ -863,7 +863,7 @@ SurfaceMaterialInteractionPSRSample translucentSurfaceMaterialInteractionCalcPSR const vec3 normal = normalize(vec3(translucentSurfaceMaterialInteraction.shadingNormal)); const vec3 outputDirection = normalize(vec3(minimalRayInteraction.viewDirection)); - // Calcuate the microfacet normal + // Calculate the microfacet normal // Note: Typically the microfacet normal would be sampled from so this would be known upfront in a sampling // method, due to being a dirac distribution though we always know it'll be the same as the normal. diff --git a/src/dxvk/shaders/rtx/pass/composite/composite.comp.slang b/src/dxvk/shaders/rtx/pass/composite/composite.comp.slang index d8cacb5f3..7fb283845 100644 --- a/src/dxvk/shaders/rtx/pass/composite/composite.comp.slang +++ b/src/dxvk/shaders/rtx/pass/composite/composite.comp.slang @@ -409,7 +409,7 @@ void main(uint2 thread_id : SV_DispatchThreadID, uint2 localIndex : SV_GroupThre vec4 totalLight = vec4(centerLight.xyz, 1); - if(cb.stochasticAlphaBlendEnableFilter) + if (cb.stochasticAlphaBlendEnableFilter) { float minHitT = surface.hitT; float maxHitT = surface.hitT; diff --git a/src/dxvk/shaders/rtx/pass/composite/composite_alpha_blend.comp.slang b/src/dxvk/shaders/rtx/pass/composite/composite_alpha_blend.comp.slang index d6ca9753f..eab36c471 100644 --- a/src/dxvk/shaders/rtx/pass/composite/composite_alpha_blend.comp.slang +++ b/src/dxvk/shaders/rtx/pass/composite/composite_alpha_blend.comp.slang @@ -153,7 +153,7 @@ void main(uint2 thread_id : SV_DispatchThreadID, uint2 localIndex : SV_GroupThre } centerPixel = neighborPixel; - if(found) + if (found) { int2 neighborPixel = centerPixel; vec3 diffuseLight = 0; @@ -183,7 +183,7 @@ void main(uint2 thread_id : SV_DispatchThreadID, uint2 localIndex : SV_GroupThre } } - if(cb.stochasticAlphaBlendUseRadianceVolume && !found) + if (cb.stochasticAlphaBlendUseRadianceVolume && !found) { uint froxelVolumeHint = froxelVolumeMain; @@ -224,7 +224,7 @@ void main(uint2 thread_id : SV_DispatchThreadID, uint2 localIndex : SV_GroupThre found= true; } } - if(!found) + if (!found) { surfaceLight = 0; } diff --git a/src/dxvk/shaders/rtx/pass/debug_view/debug_view.comp.slang b/src/dxvk/shaders/rtx/pass/debug_view/debug_view.comp.slang index e0bda71f0..97065552e 100644 --- a/src/dxvk/shaders/rtx/pass/debug_view/debug_view.comp.slang +++ b/src/dxvk/shaders/rtx/pass/debug_view/debug_view.comp.slang @@ -214,7 +214,7 @@ vec3 colorCodeIntoBGRexclusive(uint value, uint maxValue) vec4 loadInput(ivec2 threadId) { - vec4 value; + vec4 value = vec4(0); const GeometryFlags geometryFlags = geometryFlagsReadFromGBuffer(threadId, SharedFlags); // Compute the coordinate with respect to the upscaled output diff --git a/src/dxvk/shaders/rtx/pass/debug_view/debug_view_waveform_render_binding_indices.h b/src/dxvk/shaders/rtx/pass/debug_view/debug_view_waveform_render_binding_indices.h index 408842534..52d52951e 100644 --- a/src/dxvk/shaders/rtx/pass/debug_view/debug_view_waveform_render_binding_indices.h +++ b/src/dxvk/shaders/rtx/pass/debug_view/debug_view_waveform_render_binding_indices.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,8 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#ifndef DEBUG_VIEW_WAVEFORM_RENDER_BINDINGS_H -#define DEBUG_VIEW_WAVEFORM_RENDER_BINDINGS_H +#pragma once #include "rtx/utility/shader_types.h" @@ -37,5 +36,3 @@ #define DEBUG_VIEW_WAVEFORM_RENDER_MAX_BINDING (DEBUG_VIEW_WAVEFORM_RENDER_BINDING_INPUT_OUTPUT) #define DEBUG_VIEW_WAVEFORM_RENDER_NUM_BINDINGS (DEBUG_VIEW_MAX_BINDING + 1) - -#endif diff --git a/src/dxvk/shaders/rtx/pass/demodulate/demodulate.comp.slang b/src/dxvk/shaders/rtx/pass/demodulate/demodulate.comp.slang index 3b0dc08db..8d17e24cb 100644 --- a/src/dxvk/shaders/rtx/pass/demodulate/demodulate.comp.slang +++ b/src/dxvk/shaders/rtx/pass/demodulate/demodulate.comp.slang @@ -686,7 +686,7 @@ void main(uint2 pixelCoordinate : SV_DispatchThreadID, uint2 localIndex : SV_Gro primaryDirectDiffuseInput, primaryDirectSpecularInput, primaryDirectDiffuseOutput, primaryDirectSpecularOutput, cb.enableDemodulateRoughness); - if(cb.enableDirectLightBoilingFilter) + if (cb.enableDirectLightBoilingFilter) { applyDirectLightBoilingFilter(localIndex, primaryLinearViewZ, primaryVirtualWorldNormal, primaryDirectDiffuseOutput.xyz, primaryDirectSpecularOutput.xyz); diff --git a/src/dxvk/shaders/rtx/pass/gen_tri_list_index_buffer.comp.slang b/src/dxvk/shaders/rtx/pass/gen_tri_list_index_buffer.comp.slang index f8f56efc5..ba2cadf5f 100644 --- a/src/dxvk/shaders/rtx/pass/gen_tri_list_index_buffer.comp.slang +++ b/src/dxvk/shaders/rtx/pass/gen_tri_list_index_buffer.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -40,8 +40,12 @@ ConstantBuffer cb; [shader("compute")] [numthreads(128, 1, 1)] -void main(uint idx : SV_DispatchThreadID) { - if (idx >= cb.primCount) return; +void main(uint idx : SV_DispatchThreadID) +{ + if (idx >= cb.primCount) + { + return; + } generateIndices(idx, dst, src, cb); } \ No newline at end of file diff --git a/src/dxvk/shaders/rtx/pass/gpu_skinning.comp.slang b/src/dxvk/shaders/rtx/pass/gpu_skinning.comp.slang index 1510a84e1..67e755639 100644 --- a/src/dxvk/shaders/rtx/pass/gpu_skinning.comp.slang +++ b/src/dxvk/shaders/rtx/pass/gpu_skinning.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -45,8 +45,12 @@ StructuredBuffer srcNormal; [shader("compute")] [numthreads(128, 1, 1)] -void main(uint idx : SV_DispatchThreadID) { - if (idx >= cb.numVertices) return; - - skinning(idx, dstPosition, dstNormal, srcPosition, srcBlendWeight, srcBlendIndices, srcNormal, cb); +void main(uint idx : SV_DispatchThreadID) +{ + if (idx >= cb.numVertices) + { + return; + } + + skinning(idx, dstPosition, dstNormal, srcPosition, srcBlendWeight, srcBlendIndices, srcNormal, cb); } \ No newline at end of file diff --git a/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect.slangh b/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect.slangh index f00ecfc2f..809ea6b7d 100644 --- a/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect.slangh +++ b/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect.slangh @@ -84,9 +84,13 @@ void integrate_indirect_pass(ivec2 threadIndex) float gbufferSurfaceHitDistance = 0; if (geometryFlags.primarySelectedIntegrationSurface) + { gbufferSurfaceHitDistance = PrimaryHitDistance[threadIndex]; + } else + { gbufferSurfaceHitDistance = SecondaryHitDistance[threadIndex]; + } // Integrate the Indirect portion of the Path diff --git a/src/dxvk/shaders/rtx/pass/integrate/visualize_nee.comp.slang b/src/dxvk/shaders/rtx/pass/integrate/visualize_nee.comp.slang index a1853de6b..bc3f2259d 100644 --- a/src/dxvk/shaders/rtx/pass/integrate/visualize_nee.comp.slang +++ b/src/dxvk/shaders/rtx/pass/integrate/visualize_nee.comp.slang @@ -175,23 +175,23 @@ vec3 logarithmicColor(float value) { return vec3(1,0,0); } - else if(value < 100.0) + else if (value < 100.0) { return vec3(1,0.5,0); } - else if(value < 1000.0) + else if (value < 1000.0) { return vec3(1,1,0); } - else if(value < 10000.0) + else if (value < 10000.0) { return vec3(0,1,0); } - else if(value < 100000.0) + else if (value < 100000.0) { return vec3(0,1,1); } - else if(value < 1000000.0) + else if (value < 1000000.0) { return vec3(0,0,1); } @@ -283,7 +283,7 @@ void main(uint2 threadIndex : SV_DispatchThreadID, uint2 LocalIndex : SV_GroupTh NEECell sampleCell = NEECache.getCell(NEECache.pointToOffset(sampleSurface.minimalSurfaceInteraction.position, f16vec3(0), jitter)); if (sampleCell.isValid()) { - if(!canvas.isPadding()) + if (!canvas.isPadding()) { // Get bin index int binIndex = canvas.getBin(NEECell.getMaxCandidateCount()); @@ -321,11 +321,11 @@ void main(uint2 threadIndex : SV_DispatchThreadID, uint2 LocalIndex : SV_GroupTh } // Calculate histogram - if(canvas.isCross()) + if (canvas.isCross()) { canvas.drawForeground(vec3(1,0,0)); } - if(canvas.isLegend(1)) + if (canvas.isLegend(1)) { // Show samples int binIndex = canvas.getBin(NEE_CACHE_SAMPLES); @@ -334,11 +334,11 @@ void main(uint2 threadIndex : SV_DispatchThreadID, uint2 LocalIndex : SV_GroupTh float alpha = isLightHistogram ? (isBinValid ? 1.0 : 0.0) : 1.0; canvas.drawForeground(color, alpha); } - else if(canvas.isLegend(0)) + else if (canvas.isLegend(0)) { canvas.drawForeground(lightIntensity, isBinValid ? 1.0 : 0.0); } - else if(canvas.isHistogram() && canvas.isHistogramBar(probability)) + else if (canvas.isHistogram() && canvas.isHistogramBar(probability)) { // Histogram canvas.drawForeground(histogramColor, isBinValid ? 1.0 : 0.0); @@ -373,7 +373,7 @@ void main(uint2 threadIndex : SV_DispatchThreadID, uint2 LocalIndex : SV_GroupTh vec3 backgroundColor = indirectLight * linearToGamma(cellColor); vec4 triangleColor = 0.0; - if(lightSelectionPDF > 0.5) + if (lightSelectionPDF > 0.5) { triangleColor = lerp(vec4(1,1,0,0.5), vec4(0,1,0,0.5), (lightSelectionPDF - 0.5) * 2.0); } diff --git a/src/dxvk/shaders/rtx/pass/interleave_geometry.comp.slang b/src/dxvk/shaders/rtx/pass/interleave_geometry.comp.slang index b2749499a..386e9d264 100644 --- a/src/dxvk/shaders/rtx/pass/interleave_geometry.comp.slang +++ b/src/dxvk/shaders/rtx/pass/interleave_geometry.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -39,8 +39,12 @@ ConstantBuffer cb; [shader("compute")] [numthreads(128, 1, 1)] -void main(uint idx : SV_DispatchThreadID) { - if (idx >= cb.vertexCount) return; - +void main(uint idx : SV_DispatchThreadID) +{ + if (idx >= cb.vertexCount) + { + return; + } + interleaver::interleave(idx, dst, srcPosition, srcNormal, srcTexcoord, srcColor0, cb); } diff --git a/src/dxvk/shaders/rtx/pass/nee_cache/update_nee_cache.comp.slang b/src/dxvk/shaders/rtx/pass/nee_cache/update_nee_cache.comp.slang index 1fc9cd55e..79d976798 100644 --- a/src/dxvk/shaders/rtx/pass/nee_cache/update_nee_cache.comp.slang +++ b/src/dxvk/shaders/rtx/pass/nee_cache/update_nee_cache.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -61,8 +61,10 @@ int convertToThisFramePrefixSumID(int lastID, out int surfaceID, out int primiti return NEE_CACHE_INVALID_ID; } int surfaceIDLast, primitiveIDLast; - if(!NEECacheUtils.convertPrefixSumIDToID(lastID, LastPrimitiveIDPrefixSum, surfaceIDLast, primitiveIDLast)) + if (!NEECacheUtils.convertPrefixSumIDToID(lastID, LastPrimitiveIDPrefixSum, surfaceIDLast, primitiveIDLast)) + { return NEE_CACHE_INVALID_ID; + } int surfaceIDThis = NEECacheUtils.convertToCurrentSurfaceID(surfaceIDLast); surfaceID = surfaceIDThis; @@ -73,7 +75,9 @@ int convertToThisFramePrefixSumID(int lastID, out int surfaceID, out int primiti int convertLightIndex(int lightIndex) { if (lightIndex == NEE_CACHE_INVALID_ID) + { return NEE_CACHE_INVALID_ID; + } bool currentToPrevious = false; return lightMapping[lightIndex + (currentToPrevious ? 0 : cb.lightCount)]; @@ -254,7 +258,7 @@ void updateTriangleTask(NEECell cell, uint2 localIndex) } } - if(!found) + if (!found) { value.x = ((1 << 24) | value.x); insertTask(value, localIndex.y); @@ -424,7 +428,7 @@ void updateLightTask(NEECell cell, uint2 localIndex) GroupMemoryBarrierWithGroupSync(); - if(cb.neeCacheArgs.clearCache == 0) + if (cb.neeCacheArgs.clearCache == 0) { uint2 value = cell.getLightSlotTaskValue(localIndex.x); value.x = convertLightIndex(value.x); diff --git a/src/dxvk/shaders/rtx/pass/opacity_micromap/bake_opacity_micromap.comp.slang b/src/dxvk/shaders/rtx/pass/opacity_micromap/bake_opacity_micromap.comp.slang index 9ff13dff3..991592223 100644 --- a/src/dxvk/shaders/rtx/pass/opacity_micromap/bake_opacity_micromap.comp.slang +++ b/src/dxvk/shaders/rtx/pass/opacity_micromap/bake_opacity_micromap.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -67,10 +67,14 @@ void loadVertexData(uint triIdx, Surface surface, out float2 vertexTexcoords[3], { const uint indexBufferIndex = surface.indexBufferIndex; - if(surface.indexStride == 4) + if (surface.indexStride == 4) + { index = BUFFER_ARRAY(Indices32, indexBufferIndex, indexIndex); + } else + { index = BUFFER_ARRAY(Indices, indexBufferIndex, indexIndex); + } } else { @@ -102,11 +106,12 @@ void loadVertexData(uint triIdx, Surface surface, out float2 vertexTexcoords[3], void applyVertexAndTextureOperationsToOpacity(inout float16_t opacity, f16vec3 albedo, float3 bary, Surface surface, float16_t vertexOpacities[3]) { - if (cb.materialType == surfaceMaterialTypeOpaque) { - + if (cb.materialType == surfaceMaterialTypeOpaque) + { float16_t vertexInterpolatedOpacity = 1.h; - if (surface.color0BufferIndex != BINDING_INDEX_INVALID) { + if (surface.color0BufferIndex != BINDING_INDEX_INVALID) + { vertexInterpolatedOpacity = interpolateHitAttribute(vertexOpacities, bary); } @@ -137,7 +142,8 @@ f16vec4 sampleColorOpacityRaw(float2 texcoords) { f16vec4 colorOpacity = sampleColorOpacityTexture(Opacity, texcoords); - if (cb.materialType == surfaceMaterialTypeRayPortal) { + if (cb.materialType == surfaceMaterialTypeRayPortal) + { // TODO: match RT resolve transparency calculation for portals, handle animation // For now take the max opacity from both textures colorOpacity.a = max(colorOpacity.a, sampleColorOpacityTexture(SecondaryOpacity, texcoords).a); @@ -151,7 +157,9 @@ float16_t sampleOpacity(float2 texcoords, Surface surface, float3 bary, float16_ f16vec4 colorOpacity = sampleColorOpacityRaw(texcoords); if (cb.applyVertexAndTextureOperations) + { applyVertexAndTextureOperationsToOpacity(colorOpacity.a, colorOpacity.rgb, bary, surface, vertexOpacities); + } return colorOpacity.a; } @@ -171,7 +179,8 @@ void sampleOpacityConservative(Surface surface, float2 texcoordsMax = calculateTriangleTexcoordBBoxMax(microTriangleVertexTexcoords); // Check for invalid values should garbage texcoord data be fed in - if (!isValidValue(texcoordsMin) || !isValidValue(texcoordsMax)) { + if (!isValidValue(texcoordsMin) || !isValidValue(texcoordsMax)) + { minOpacity = 0; maxOpacity = 1; return; @@ -205,6 +214,7 @@ void sampleOpacityConservative(Surface surface, minOpacity = 1; maxOpacity = 0; for (uint v = 0; v < texelSampleDims.y; v++) + { for (uint u = 0; u < texelSampleDims.x; u++) { const float2 texcoords = texcoordsMin + uint2(u, v) * cb.rcpTextureResolution; @@ -219,6 +229,7 @@ void sampleOpacityConservative(Surface surface, minOpacity = min(opacity, minOpacity); maxOpacity = max(opacity, maxOpacity); } + } } enum OpacityState @@ -236,13 +247,21 @@ enum OpacityState OpacityState getOpacityState(float opacity) { if (opacity <= cb.resolveTransparencyThreshold) + { return OpacityState::Transparent; + } else if (opacity >= cb.resolveOpaquenessThreshold) + { return OpacityState::Opaque; + } else if (cb.is2StateOMMFormat) + { return OMM_2_STATE_UNKNOWN_STATE; + } else + { return OMM_4_STATE_UNKNOWN_STATE; + } } OpacityState calculateOpacityMicromapValue(float16_t minOpacity, float16_t maxOpacity) @@ -285,7 +304,7 @@ OpacityState calculateOpacityMicromapValue(uint uIdx, float rcpNumSubdivisions, minOpacity = opacity; // Taps at corners of the microtriangle at lod 0 - for (int i = 0; i < 3; i++) + for (uint i = 0; i < 3; i++) { opacity = sampleOpacity(microTriangleVertexTexcoords[i], surface, microTriangleVertexBarys[i], vertexOpacities); @@ -302,8 +321,10 @@ OpacityState calculateOpacityMicromapValue(uint uIdx, float rcpNumSubdivisions, void main(uint globalId: SV_DispatchThreadID, uint groupId : SV_GroupID, uint threadId : SV_GroupThreadID) { if (globalId >= cb.numActiveThreads) + { return; - + } + const uint numBitsPerMicroTriangle = cb.is2StateOMMFormat ? 1 : 2; const uint numSubdivisionsPerEdge = 1 << cb.subdivisionLevel; const float rcpNumSubdivisions = 1.f / numSubdivisionsPerEdge; @@ -319,7 +340,7 @@ void main(uint globalId: SV_DispatchThreadID, uint groupId : SV_GroupID, uint th loadVertexData(triIdx, cb.surface, vertexTexcoords, vertexOpacities); uint8_t compactResult = 0; - for (uint i=0 ; i 0 && !isInitialSample) + if (cb.enableReSTIRGILightingValidation > 0 && !isInitialSample) { validateSample(inputReservoir, resultReservoir, isGBufferSimilar); } @@ -347,7 +347,7 @@ void main(int2 thread_id : SV_DispatchThreadID) { storeInDebugView(thread_id, isGBufferSimilar ? lerp(vec3(1, 0, 0), vec3(0, 1, 0), reflectionReprojectionWeight) : vec3(0)); } - else if(cb.debugView == DEBUG_VIEW_NAN) + else if (cb.debugView == DEBUG_VIEW_NAN) { bool isValid = true; // DEBUG_VIEW_RESTIR_GI_INITIAL_SAMPLE diff --git a/src/dxvk/shaders/rtx/pass/rtxdi/rtxdi_spatial_reuse.comp.slang b/src/dxvk/shaders/rtx/pass/rtxdi/rtxdi_spatial_reuse.comp.slang index e3a1dc43c..9010ca53b 100644 --- a/src/dxvk/shaders/rtx/pass/rtxdi/rtxdi_spatial_reuse.comp.slang +++ b/src/dxvk/shaders/rtx/pass/rtxdi/rtxdi_spatial_reuse.comp.slang @@ -52,7 +52,7 @@ void main(int2 thread_id : SV_DispatchThreadID) } RAB_Surface surface = RAB_GetGBufferSurface(thread_id, false); - if(!cb.enableReSTIRGI) + if (!cb.enableReSTIRGI) { imageStore(GBufferLast, thread_id, RAB_PackLastFrameGBuffer(surface)); } diff --git a/src/dxvk/shaders/rtx/pass/tonemap/auto_exposure.comp.slang b/src/dxvk/shaders/rtx/pass/tonemap/auto_exposure.comp.slang index bb165d76a..4276a4d19 100644 --- a/src/dxvk/shaders/rtx/pass/tonemap/auto_exposure.comp.slang +++ b/src/dxvk/shaders/rtx/pass/tonemap/auto_exposure.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -49,7 +49,7 @@ float computePrefixSum(float val, const uint linearIndex) g_localData[linearIndex] = val; GroupMemoryBarrierWithGroupSync(); - for(uint k = WaveGetLaneCount(); k < EXPOSURE_HISTOGRAM_SIZE; k *= 2) + for (uint k = WaveGetLaneCount(); k < EXPOSURE_HISTOGRAM_SIZE; k *= 2) { uint blockIndex = linearIndex / k; // Propagate prefixSum to the next block for every other block so as to avoid @@ -80,7 +80,7 @@ void main(uint2 threadId : SV_DispatchThreadID, uint linearIndex : SV_GroupIndex float totalWeight = computePrefixSum(countThisBucket, linearIndex); float adaptedCountThisBucket = countThisBucket; - if(cb.averageMode == 0) // mean + if (cb.averageMode == 0) // mean { adaptedCountThisBucket *= linearIndex; // factor in the index so we can compute the mean bucket quickly } @@ -89,23 +89,25 @@ void main(uint2 threadId : SV_DispatchThreadID, uint linearIndex : SV_GroupIndex const float weightedSum = computePrefixSum(adaptedCountThisBucket, linearIndex); float normalizedEV = 0; - if(linearIndex == 0) + if (linearIndex == 0) { uint discardSampleCount = countThisBucket; // discarded (e.g. black) pixel count, since this is the 0th bucket float weightedAverage; - if(cb.averageMode == 1) + if (cb.averageMode == 1) { float median = (weightedSum - discardSampleCount) / 2.f; weightedAverage = 0.5f; // Start with the first bucket center - for(uint i=1 ; i median) + if (g_localData[i] > median) + { break; - + } + weightedAverage = i + 0.5f; // +0.5 as we want the center of the bucket } } @@ -134,10 +136,10 @@ void main(uint2 threadId : SV_DispatchThreadID, uint linearIndex : SV_GroupIndex OutExposure[0] = adaptedExposure; } - if(cb.debugMode) + if (cb.debugMode) { DebugView[uint2(linearIndex, 0)] = vec4(float(countThisBucket) / 10000, 0, weight, 1.0); - if(linearIndex == 0) + if (linearIndex == 0) { // Remap exposure to bucket (1, size-1) int avgIdx = uint(normalizedEVToHistogramOffset(normalizedEV)); diff --git a/src/dxvk/shaders/rtx/pass/tonemap/auto_exposure_histogram.comp.slang b/src/dxvk/shaders/rtx/pass/tonemap/auto_exposure_histogram.comp.slang index 8dc97b884..c165ed6ee 100644 --- a/src/dxvk/shaders/rtx/pass/tonemap/auto_exposure_histogram.comp.slang +++ b/src/dxvk/shaders/rtx/pass/tonemap/auto_exposure_histogram.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -39,8 +39,10 @@ uint inputToHistogramBucket(const float3 inputColor) // Count nearly black pixels in the 0th bucket const float kEpsilon = 0.00001f; if (inputLuminance < kEpsilon) + { return 0; - + } + const float ev100 = calcLuminanceEV100(inputLuminance); const float normalizedEV = saturate((ev100 - cb.evMinValue) / cb.evRange); @@ -51,8 +53,10 @@ uint inputToHistogramBucket(const float3 inputColor) float centerMeteringWeight(float2 screenUV, float aspect) { - if(!cb.enableCenterMetering) + if (!cb.enableCenterMetering) + { return 1.f; + } const float weight = saturate(length( (screenUV - vec2(0.5f)) / vec2(1.0f, aspect) ) / cb.centerMeteringSize); return lerp(1.0f, 0.0f, weight); @@ -83,7 +87,8 @@ void main(uint2 threadId : SV_DispatchThreadID, uint linearIndex : SV_GroupIndex GroupMemoryBarrierWithGroupSync(); uint localBinValue = g_localData[linearIndex]; - if (localBinValue != 0) { + if (localBinValue != 0) + { InterlockedAdd(OutHistogram[linearIndex], localBinValue); } } diff --git a/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_apply_tonemapping.comp.slang b/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_apply_tonemapping.comp.slang index c4ddbee38..7018c2a09 100644 --- a/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_apply_tonemapping.comp.slang +++ b/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_apply_tonemapping.comp.slang @@ -131,7 +131,7 @@ float3 applyToneMapping(float3 color, uint2 pixelPosition) // Normal tone mapping color = dynamicToneMapper(color); - if(cb.finalizeWithACES) + if (cb.finalizeWithACES) { color = ACESFilm(color); } diff --git a/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_histogram.comp.slang b/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_histogram.comp.slang index d30544be8..911b8d4df 100644 --- a/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_histogram.comp.slang +++ b/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_histogram.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -47,15 +47,16 @@ void main(uint2 threadId : SV_DispatchThreadID, uint linearIndex : SV_GroupIndex uvec2 screenSize; InColorBuffer.GetDimensions(screenSize.x, screenSize.y); - if (linearIndex < kToneCurveSampleCount) { + if (linearIndex < kToneCurveSampleCount) + { g_localHistogram[linearIndex] = 0; } GroupMemoryBarrierWithGroupSync(); // Ignore pixels that are outside of the image: - if (all(lessThan(threadId, screenSize))) { - + if (all(lessThan(threadId, screenSize))) + { vec3 inputColor = InColorBuffer[threadId].rgb; // Exposure correction @@ -65,8 +66,8 @@ void main(uint2 threadId : SV_DispatchThreadID, uint linearIndex : SV_GroupIndex const float pixelLuminance = calcBt709Luminance(inputColor); // Ignore completely black pixels, as well as pixels that are too bright: - if ((pixelLuminance > 0.0) && (pixelLuminance < exp2(cb.toneCurveMaxStops))) { - + if ((pixelLuminance > 0.0) && (pixelLuminance < exp2(cb.toneCurveMaxStops))) + { // Compute histogram bin (based on photographic stops) // The bins are numbered 0...kToneCurveSampleCount-1. When i > 0, we think of bin i // as sampling the histogram at the point @@ -107,10 +108,12 @@ void main(uint2 threadId : SV_DispatchThreadID, uint linearIndex : SV_GroupIndex // Finally, add the group's histogram to the global histogram. // This code requires at least kToneCurveSampleCount threads in each group. - if (linearIndex < kToneCurveSampleCount) { + if (linearIndex < kToneCurveSampleCount) + { uint localBinValue = g_localHistogram[linearIndex]; // Avoid performing atomic no-ops - if (localBinValue != 0) { + if (localBinValue != 0) + { InterlockedAdd(InOutHistogram[int(linearIndex)], localBinValue); } } diff --git a/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_noise.slangh b/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_noise.slangh index 61af7202a..221204061 100644 --- a/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_noise.slangh +++ b/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_noise.slangh @@ -43,7 +43,8 @@ float3 ditherTo8Bit( { // Early out if dithering is not enabled - if (!enableDithering) { + if (!enableDithering) + { return value; } diff --git a/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_tone_curve.comp.slang b/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_tone_curve.comp.slang index 9ec476853..5d4eec0b4 100644 --- a/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_tone_curve.comp.slang +++ b/src/dxvk/shaders/rtx/pass/tonemap/tonemapping_tone_curve.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -48,12 +48,16 @@ float computeSharedSum(float val, const uint linearIndex) { g_localData[linearIndex] = val; GroupMemoryBarrierWithGroupSync(); - for (uint k = kToneCurveSampleCount / 2; k >= WaveGetLaneCount(); k /= 2) { - if (linearIndex < k) { - g_localData[linearIndex] += g_localData[linearIndex + k]; - } - GroupMemoryBarrierWithGroupSync(); + for (uint k = kToneCurveSampleCount / 2; k >= WaveGetLaneCount(); k /= 2) + { + if (linearIndex < k) + { + g_localData[linearIndex] += g_localData[linearIndex + k]; + } + + GroupMemoryBarrierWithGroupSync(); } + return g_localData[0]; } @@ -68,7 +72,7 @@ float computePrefixSum(float val, const uint linearIndex) g_localData[linearIndex] = val; GroupMemoryBarrierWithGroupSync(); - for(uint k = WaveGetLaneCount(); k < EXPOSURE_HISTOGRAM_SIZE; k *= 2) + for (uint k = WaveGetLaneCount(); k < EXPOSURE_HISTOGRAM_SIZE; k *= 2) { uint blockIndex = linearIndex / k; // Propagate prefixSum to the next block for every other block so as to avoid @@ -95,7 +99,8 @@ float computeSlopes( const uint linearIndex) { // Compute local histogram for this section of the curve - if (linearIndex < minBin || linearIndex >= maxBinExclusive) { + if (linearIndex < minBin || linearIndex >= maxBinExclusive) + { hist = 0.0f; } @@ -123,7 +128,8 @@ float computeSlopes( float sumRecip; float lenOmega = float(kToneCurveSampleCount); float threshPassed; - for (uint i = 0; i < 16; ++i) { + for (uint i = 0; i < 16; ++i) + { threshPassed = step(thresh, hist); lenOmega = computeSharedSum(threshPassed, linearIndex); @@ -145,8 +151,9 @@ float computeSlopes( [numthreads(TONEMAPPING_TONE_CURVE_SAMPLE_COUNT, 1, 1)] void main(uint linearIndex : SV_GroupIndex) { - if (linearIndex >= kToneCurveSampleCount) { - return; + if (linearIndex >= kToneCurveSampleCount) + { + return; } // This is the log luminance of the histogram bin this thread is processing. @@ -175,7 +182,7 @@ void main(uint linearIndex : SV_GroupIndex) if (linearIndex < kCrossover) { - mySlope = max(mySlope, cb.shadowMinSlope); + mySlope = max(mySlope, cb.shadowMinSlope); } // Compute tone curve. @@ -214,10 +221,12 @@ void main(uint linearIndex : SV_GroupIndex) // Temporal filtering { - const float myOldToneCurve = InOutToneCurve[linearIndex].r; - if (cb.needsReset == 0) { - myToneCurve = mix(myToneCurve, myOldToneCurve, exp(-0.07)); // Ad-hoc constant for interpolation - } + const float myOldToneCurve = InOutToneCurve[linearIndex].r; + + if (cb.needsReset == 0) + { + myToneCurve = mix(myToneCurve, myOldToneCurve, exp(-0.07)); // Ad-hoc constant for interpolation + } } // Write to the output! diff --git a/src/dxvk/shaders/rtx/pass/volumetrics/volume_filter.comp.slang b/src/dxvk/shaders/rtx/pass/volumetrics/volume_filter.comp.slang index 2f37e09fa..73a9b93e4 100644 --- a/src/dxvk/shaders/rtx/pass/volumetrics/volume_filter.comp.slang +++ b/src/dxvk/shaders/rtx/pass/volumetrics/volume_filter.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -35,8 +35,10 @@ void main(uint3 ipos : SV_DispatchThreadID) const uint froxelVolume = threadIndex.x / froxelDimensions.x; if (any(threadIndex.yz >= froxelDimensions.yz) || froxelVolume > volumeArgs.numActiveFroxelVolumes) + { return; - + } + const uint froxelVolumeLeft = froxelVolume * volumeArgs.froxelGridDimensions.x; const uint froxelVolumeRight = froxelVolumeLeft + volumeArgs.froxelGridDimensions.x; diff --git a/src/dxvk/shaders/rtx/pass/volumetrics/volume_integrate.slangh b/src/dxvk/shaders/rtx/pass/volumetrics/volume_integrate.slangh index da668229d..b3b4c86c4 100644 --- a/src/dxvk/shaders/rtx/pass/volumetrics/volume_integrate.slangh +++ b/src/dxvk/shaders/rtx/pass/volumetrics/volume_integrate.slangh @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -35,8 +35,10 @@ void volume_integrate_pass(ivec3 threadIndex) const uint froxelVolume = threadIndex.x / froxelDimensions.x; if (any(threadIndex.yz >= froxelDimensions.yz) || froxelVolume > volumeArgs.numActiveFroxelVolumes) + { return; - + } + // Figure out which volume we'll be pulling the previous data from. // Usually it's the same volume, but in case of portal teleportation, that doesn't work. uint previousFroxelVolume = froxelVolume; diff --git a/src/dxvk/shaders/rtx/pass/volumetrics/volume_preintegrate.comp.slang b/src/dxvk/shaders/rtx/pass/volumetrics/volume_preintegrate.comp.slang index 3a0389dc2..7de390c7b 100644 --- a/src/dxvk/shaders/rtx/pass/volumetrics/volume_preintegrate.comp.slang +++ b/src/dxvk/shaders/rtx/pass/volumetrics/volume_preintegrate.comp.slang @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -44,8 +44,10 @@ float getRayPortalIntersection(float3 origin, float3 direction, RayPortalHitInfo const float NdotD = dot(direction, portal.normal); float t = dot(portal.centroid - origin, portal.normal) / NdotD; if (isinf(t) || isnan(t)) + { return -1.0; - + } + if (t > 0 && NdotD < 0) { // Compute the UV coordinates of the ray-portal intersection @@ -59,7 +61,9 @@ float getRayPortalIntersection(float3 origin, float3 direction, RayPortalHitInfo // This minimizes interpolation artifacts when the preintegrated volumetric texture is sampled // near the edge of the portal, or rather, hides them under the burning portal edge mask. if (length(uv) < 0.95) + { return t; + } } return -1.0; @@ -72,10 +76,12 @@ void main(uint3 ipos : SV_DispatchThreadID) ivec2 threadIndex = ipos.xy; const VolumeArgs volumeArgs = cb.volumeArgs; const uvec3 froxelDimensions = uvec3(volumeArgs.froxelGridDimensions, volumeArgs.froxelDepthSlices); - + if (any(threadIndex.xy >= froxelDimensions.xy)) + { return; - + } + const VolumeDefinitionCamera camera = volumeArgs.cameras[froxelVolumeMain]; // Set up for a portal transition diff --git a/src/dxvk/shaders/rtx/utility/filtering.slangh b/src/dxvk/shaders/rtx/utility/filtering.slangh index 9429dafef..1a5bab6d7 100644 --- a/src/dxvk/shaders/rtx/utility/filtering.slangh +++ b/src/dxvk/shaders/rtx/utility/filtering.slangh @@ -1,3 +1,24 @@ +/* +* Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +*/ #pragma once // Retrieves a median from 9 input values @@ -24,20 +45,28 @@ float4 getMedian(float4 v[9]) const float kMinInvalidValue = -1; mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]); if (v[1].w == kMinInvalidValue) + { v[1] = v[5]; + } mnmx5(v[1], v[2], v[3], v[4], v[6]); if (v[2].w == kMinInvalidValue) + { v[2] = v[6]; + } mnmx4(v[2], v[3], v[4], v[7]); if (v[3].w == kMinInvalidValue) + { v[3] = v[7]; + } mnmx3(v[3], v[4], v[8]); if (v[4].w == kMinInvalidValue) + { v[4] = v[8]; - + } + return v[4]; } diff --git a/src/dxvk/shaders/rtx/utility/gbuffer_helpers.slangh b/src/dxvk/shaders/rtx/utility/gbuffer_helpers.slangh index f81a84cea..b90081ef5 100644 --- a/src/dxvk/shaders/rtx/utility/gbuffer_helpers.slangh +++ b/src/dxvk/shaders/rtx/utility/gbuffer_helpers.slangh @@ -52,7 +52,8 @@ void minimalRayInteractionWriteToGBuffer( const GBufferMemoryMinimalRayInteraction gBufferMemoryMinimalRayInteraction = gBufferMemoryMinimalRayInteractionCreate(minimalRayInteraction, directionAltered); - if (directionAltered) { + if (directionAltered) + { viewDirectionTexture[position] = gBufferMemoryMinimalRayInteraction.encodedViewDirection; } @@ -212,7 +213,8 @@ void polymorphicSurfaceMaterialInteractionWriteToGBuffer( surfaceIndexTexture[position] = uint32_t(surfaceIndex); // Only write sharedTextureCoords if the material has a height texture, or the material has subsurface texture(s) - if (polymorphicSurfaceMaterialInteractionHasHeightTexture(polymorphicSurfaceMaterialInteraction)) { + if (polymorphicSurfaceMaterialInteractionHasHeightTexture(polymorphicSurfaceMaterialInteraction)) + { sharedTextureCoords[position] = surfaceInteraction.textureCoordinates; } diff --git a/src/dxvk/shaders/rtx/utility/gpu_printing.h b/src/dxvk/shaders/rtx/utility/gpu_printing.h index b03fa3369..a79f0c971 100644 --- a/src/dxvk/shaders/rtx/utility/gpu_printing.h +++ b/src/dxvk/shaders/rtx/utility/gpu_printing.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -33,7 +33,8 @@ struct GpuPrintBufferElement #ifndef __cplusplus [mutating] #endif - void invalidate() { + void invalidate() + { threadIndex.x = kInvalidThreadIndex; } diff --git a/src/dxvk/shaders/rtx/utility/instrumentation.slangh b/src/dxvk/shaders/rtx/utility/instrumentation.slangh index 809c0976e..43ed8fb1b 100644 --- a/src/dxvk/shaders/rtx/utility/instrumentation.slangh +++ b/src/dxvk/shaders/rtx/utility/instrumentation.slangh @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -34,12 +34,16 @@ void instrumentThreadDivergence(uint uniqueShaderLocationID, uint maxActiveLanes) { if (uniqueShaderLocationID != uint(cb.debugKnob.x)) + { return; + } bool isDivergent = WaveActiveSum(1) != maxActiveLanes; - + if (isDivergent) + { Instrumentation[DispatchRaysIndex().xy] = 1; + } } // Note: same referenceMaxActiveLanesID can be used among multiple INSTRUMENT_THREAD_DIVERGENCE diff --git a/src/dxvk/shaders/rtx/utility/math.slangh b/src/dxvk/shaders/rtx/utility/math.slangh index 6fff9a9da..c6e3fcc21 100644 --- a/src/dxvk/shaders/rtx/utility/math.slangh +++ b/src/dxvk/shaders/rtx/utility/math.slangh @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -36,7 +36,8 @@ static const uint uintMax = 4294967295; // Clamps a value to the range [0, 1] #define GENERIC_SATURATE(type) \ -type saturate(type x) { \ +type saturate(type x) \ +{ \ return clamp(x, type(0), type(1)); \ } @@ -282,7 +283,7 @@ f16vec3 quaternionTransformVector(f16vec4 q, f16vec3 v, bool signBitIsParity = f f16vec3 newVector = v + float16_t(2.0) * cross(q.xyz, cross(q.xyz, v) + q.w * v); // In cases where we encode the sign bit of the quaternion representing an improper rotation... - if(signBitIsParity) + if (signBitIsParity) { newVector = (isQuatRightHanded(q.w) ? -1.h : 1.h) * newVector; } @@ -307,7 +308,7 @@ f16vec4 quaternionMultiply(f16vec4 q1, f16vec4 q2, bool signBitIsParity = false) q = isQuatRightHanded(q.w) ? -q : q; // In cases where we encode the sign bit of the quaternion representing an improper rotation... - if(signBitIsParity) + if (signBitIsParity) { return (isQuatRightHanded(q1) ? -1.h : 1.h) * (isQuatRightHanded(q2.w) ? -1.h : 1.h) * q; } @@ -574,56 +575,57 @@ bool isQuatRightHanded(f16vec4 q) // `isQuatRightHanded` can be used to easily check if the input TBN was right handed. f16vec4 tbnFrameToQuaternion(f16vec3 tangent, f16vec3 biTangent, f16vec3 normal) { - const bool rightHanded = (dot(cross(tangent,biTangent), normal) >= 0.0); - if (!rightHanded) - { - biTangent = -biTangent; - } - f16mat3 rotationMatrix = { tangent, biTangent, normal }; - rotationMatrix = transpose(rotationMatrix); - - const float tr = rotationMatrix[0][0] + rotationMatrix[1][1] + rotationMatrix[2][2]; - f16vec4 quaternion; - if (tr > 0) - { - float s = sqrt(tr + 1.0) * 2; // s=4*qw - quaternion.w = 0.25 * s; - quaternion.x = (rotationMatrix[2][1] - rotationMatrix[1][2]) / s; - quaternion.y = (rotationMatrix[0][2] - rotationMatrix[2][0]) / s; - quaternion.z = (rotationMatrix[1][0] - rotationMatrix[0][1]) / s; - } - else if ((rotationMatrix[0][0] > rotationMatrix[1][1]) && (rotationMatrix[0][0] > rotationMatrix[2][2])) - { - float s = sqrt(1.0 + rotationMatrix[0][0] - rotationMatrix[1][1] - rotationMatrix[2][2]) * 2; // s=4*qx - quaternion.w = (rotationMatrix[2][1] - rotationMatrix[1][2]) / s; - quaternion.x = 0.25 * s; - quaternion.y = (rotationMatrix[0][1] + rotationMatrix[1][0]) / s; - quaternion.z = (rotationMatrix[0][2] + rotationMatrix[2][0]) / s; - } - else if (rotationMatrix[1][1] > rotationMatrix[2][2]) - { - float s = sqrt(1.0 + rotationMatrix[1][1] - rotationMatrix[0][0] - rotationMatrix[2][2]) * 2; // s=4*qy - quaternion.w = (rotationMatrix[0][2] - rotationMatrix[2][0]) / s; - quaternion.x = (rotationMatrix[0][1] + rotationMatrix[1][0]) / s; - quaternion.y = 0.25 * s; - quaternion.z = (rotationMatrix[1][2] + rotationMatrix[2][1]) / s; - } - else - { - float s = sqrt(1.0 + rotationMatrix[2][2] - rotationMatrix[0][0] - rotationMatrix[1][1]) * 2; // s=4*qz - quaternion.w = (rotationMatrix[1][0] - rotationMatrix[0][1]) / s; - quaternion.x = (rotationMatrix[0][2] + rotationMatrix[2][0]) / s; - quaternion.y = (rotationMatrix[1][2] + rotationMatrix[2][1]) / s; - quaternion.z = 0.25 * s; - } - - // If sign bit of w is negative but the original TBN was right handed - // (or vice versa) flip the quaternion. - if (isQuatRightHanded(quaternion) != rightHanded) { - quaternion = uint16BitsToHalf(float16BitsToUint16(quaternion) ^ 0x8000); - } - - return quaternion; + const bool rightHanded = (dot(cross(tangent,biTangent), normal) >= 0.0); + if (!rightHanded) + { + biTangent = -biTangent; + } + f16mat3 rotationMatrix = { tangent, biTangent, normal }; + rotationMatrix = transpose(rotationMatrix); + + const float tr = rotationMatrix[0][0] + rotationMatrix[1][1] + rotationMatrix[2][2]; + f16vec4 quaternion; + if (tr > 0) + { + float s = sqrt(tr + 1.0) * 2; // s=4*qw + quaternion.w = 0.25 * s; + quaternion.x = (rotationMatrix[2][1] - rotationMatrix[1][2]) / s; + quaternion.y = (rotationMatrix[0][2] - rotationMatrix[2][0]) / s; + quaternion.z = (rotationMatrix[1][0] - rotationMatrix[0][1]) / s; + } + else if ((rotationMatrix[0][0] > rotationMatrix[1][1]) && (rotationMatrix[0][0] > rotationMatrix[2][2])) + { + float s = sqrt(1.0 + rotationMatrix[0][0] - rotationMatrix[1][1] - rotationMatrix[2][2]) * 2; // s=4*qx + quaternion.w = (rotationMatrix[2][1] - rotationMatrix[1][2]) / s; + quaternion.x = 0.25 * s; + quaternion.y = (rotationMatrix[0][1] + rotationMatrix[1][0]) / s; + quaternion.z = (rotationMatrix[0][2] + rotationMatrix[2][0]) / s; + } + else if (rotationMatrix[1][1] > rotationMatrix[2][2]) + { + float s = sqrt(1.0 + rotationMatrix[1][1] - rotationMatrix[0][0] - rotationMatrix[2][2]) * 2; // s=4*qy + quaternion.w = (rotationMatrix[0][2] - rotationMatrix[2][0]) / s; + quaternion.x = (rotationMatrix[0][1] + rotationMatrix[1][0]) / s; + quaternion.y = 0.25 * s; + quaternion.z = (rotationMatrix[1][2] + rotationMatrix[2][1]) / s; + } + else + { + float s = sqrt(1.0 + rotationMatrix[2][2] - rotationMatrix[0][0] - rotationMatrix[1][1]) * 2; // s=4*qz + quaternion.w = (rotationMatrix[1][0] - rotationMatrix[0][1]) / s; + quaternion.x = (rotationMatrix[0][2] + rotationMatrix[2][0]) / s; + quaternion.y = (rotationMatrix[1][2] + rotationMatrix[2][1]) / s; + quaternion.z = 0.25 * s; + } + + // If sign bit of w is negative but the original TBN was right handed + // (or vice versa) flip the quaternion. + if (isQuatRightHanded(quaternion) != rightHanded) + { + quaternion = uint16BitsToHalf(float16BitsToUint16(quaternion) ^ 0x8000); + } + + return quaternion; } f16vec4 getIdentityQuaternion() diff --git a/src/dxvk/shaders/rtx/utility/noise.slangh b/src/dxvk/shaders/rtx/utility/noise.slangh index ec5c5c83a..8e7afb77c 100644 --- a/src/dxvk/shaders/rtx/utility/noise.slangh +++ b/src/dxvk/shaders/rtx/utility/noise.slangh @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,7 +23,8 @@ // 32 bit Jenkin's hash // http://burtleburtle.net/bob/hash/integer.html -uint hashJenkins(uint a) { +uint hashJenkins(uint a) +{ a = (a + 0x7ed55d16) + (a << 12); a = (a ^ 0xc761c23c) ^ (a >> 19); a = (a + 0x165667b1) + (a << 5); @@ -35,7 +36,8 @@ uint hashJenkins(uint a) { // Single iteration of Jenkin's One-At-A-Time hash // https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time -uint hashJenkinsOneAtATime(uint x) { +uint hashJenkinsOneAtATime(uint x) +{ x += (x << 10u); x ^= (x >> 6u); x += (x << 3u); @@ -45,7 +47,8 @@ uint hashJenkinsOneAtATime(uint x) { } // Alternative from https://nullprogram.com/blog/2018/07/31/ -uint prospectorHash(uint x) { +uint prospectorHash(uint x) +{ x ^= x >> 17; x *= 0xed5ad4bbU; x ^= x >> 11; @@ -56,7 +59,8 @@ uint prospectorHash(uint x) { return x; } -vec2 R2(uint index) { +vec2 R2(uint index) +{ // Generalized golden ratio to 2d. // Solution to x^3 = x + 1 // AKA plastic constant. @@ -67,7 +71,8 @@ vec2 R2(uint index) { #define RNG_SEED_FRAME_RANGE 64 -struct RNG { +struct RNG +{ uvec2 pixelIdx; uint seed; uint temporalIdx; @@ -76,7 +81,8 @@ struct RNG { // Creates a RNG from a pixel index (which should be spatially consistent), a temporal index (which should // only be provided from the current frame index for temporal consistency), and an optional sample offset to // advance the seed as if a number of samples happened already (this is useful for reconstructing a RNG in some cases). -RNG createRNG(uvec2 pixelIdx, uint temporalIdx, uint sampleOffset) { +RNG createRNG(uvec2 pixelIdx, uint temporalIdx, uint sampleOffset) +{ RNG rng; rng.pixelIdx = pixelIdx; rng.seed = temporalIdx / RNG_SEED_FRAME_RANGE + sampleOffset; @@ -85,13 +91,15 @@ RNG createRNG(uvec2 pixelIdx, uint temporalIdx, uint sampleOffset) { } // Overload for typical RNG construction when no sample offset is needed. -RNG createRNG(uvec2 pixelIdx, uint temporalIdx) { +RNG createRNG(uvec2 pixelIdx, uint temporalIdx) +{ return createRNG(pixelIdx, temporalIdx, 0); } // RNG construction variant used when no pixel index data is available. Likely not as optimal // for proper blue noise usage, but saves from needing to pass data through payloads for example. -RNG createRNGPosition(vec3 position, uint temporalIdx, uint sampleOffset) { +RNG createRNGPosition(vec3 position, uint temporalIdx, uint sampleOffset) +{ RNG rng; // Note: Use x/y position values mixed with z position value as the "pixel index". rng.pixelIdx = uvec2( @@ -103,7 +111,8 @@ RNG createRNGPosition(vec3 position, uint temporalIdx, uint sampleOffset) { } // Overload for position-based RNG construction when no sample offset is needed. -RNG createRNGPosition(vec3 position, uint temporalIdx) { +RNG createRNGPosition(vec3 position, uint temporalIdx) +{ return createRNGPosition(position, temporalIdx, 0); } @@ -118,7 +127,8 @@ RNG createRNGPosition(vec3 position, uint temporalIdx) { // generate proper 2D or 3D blue noise samples however, so subsequent samples of this should at least be reasonable as this // roughly follows the spatio-temporal blue noise algorithm for scalar generation. This could be improved some day however. // See: "Scalar Spatiotemporal Blue Noise Masks": https://arxiv.org/pdf/2112.09629.pdf -float getNextSampleBlueNoise(inout RNG rng) { +float getNextSampleBlueNoise(inout RNG rng) +{ #if WHITE_NOISE_OVERRIDE // Note: Jenkins hash-based white noise implementation from https://stackoverflow.com/a/17479300 @@ -154,7 +164,8 @@ float getNextSampleBlueNoise(inout RNG rng) { #endif } -uint reverseBits4(uint x) { +uint reverseBits4(uint x) +{ x = ((x & 0x5) << 1) | ((x & 0xA) >> 1); x = ((x & 0x3) << 2) | ((x & 0xC) >> 2); return x; @@ -162,7 +173,8 @@ uint reverseBits4(uint x) { // https://en.wikipedia.org/wiki/Ordered_dithering // RESULT: [0; 1) -float bayer4x4(uvec2 samplePos, uint frameIndex) { +float bayer4x4(uvec2 samplePos, uint frameIndex) +{ uvec2 samplePosWrap = samplePos & 3; uint a = 2068378560 * (1 - (samplePosWrap.y >> 1)) + 1500172770 * (samplePosWrap.y >> 1); uint b = (samplePosWrap.x + ((samplePosWrap.y & 1) << 2)) << 2; @@ -191,20 +203,21 @@ float temporalInterleavedGradientNoise(float2 uvPosition, uint frameIdx) // This is used to get the thread ID anywhere in a compute shader. property uint3 gl_GlobalInvocationID { - get + get + { + __target_switch { - __target_switch - { - case glsl: __intrinsic_asm "(gl_GlobalInvocationID)"; - case spirv: return spirv_asm { result:$$uint3 = OpLoad builtin(GlobalInvocationId:uint3); }; - } + case glsl: __intrinsic_asm "(gl_GlobalInvocationID)"; + case spirv: return spirv_asm { result:$$uint3 = OpLoad builtin(GlobalInvocationId:uint3); }; } } +} #endif // NOTE: This will allow anyone to create a RNG sampler anywhere without needing to pass it around to every function. // By default, this uses the invocation thread ID (works for Compute and Ray pipelines). -RNG createRngAnywhere(uint temporalIdx, uint offset) { +RNG createRngAnywhere(uint temporalIdx, uint offset) +{ uint2 pixelIdx = 0; #ifdef RAY_PIPELINE pixelIdx = DispatchRaysIndex().xy; diff --git a/src/dxvk/shaders/rtx/utility/sampling.slangh b/src/dxvk/shaders/rtx/utility/sampling.slangh index cdace1edd..662c78549 100644 --- a/src/dxvk/shaders/rtx/utility/sampling.slangh +++ b/src/dxvk/shaders/rtx/utility/sampling.slangh @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -212,7 +212,8 @@ float sphericalTriangleCosineAngle(vec3 A, vec3 B, vec3 C) // Note: Handle cases when normalization may be NaN (in these cases two of the points // are colinear which can be interpreted as having an angle of 0 in the spherical triangle, // or in the case of the cosine of the angle, 1). - if (lengthCA == 0.0f || lengthBA == 0.0f) { + if (lengthCA == 0.0f || lengthBA == 0.0f) + { return 1.0f; } diff --git a/src/dxvk/shaders/rtx/utility/shader_types.h b/src/dxvk/shaders/rtx/utility/shader_types.h index 38f011b19..9b2fb06f8 100644 --- a/src/dxvk/shaders/rtx/utility/shader_types.h +++ b/src/dxvk/shaders/rtx/utility/shader_types.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,8 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#ifndef SHADER_TYPES_H -#define SHADER_TYPES_H +#pragma once #ifdef __cplusplus @@ -213,5 +212,3 @@ inline int32_t floatBitsToInt(float x) { #include "rtx/utility/shader_types.slangh" #endif // __cplusplus - -#endif // SHADER_TYPES_H \ No newline at end of file diff --git a/src/dxvk/shaders/rtx/utility/shader_types.slangh b/src/dxvk/shaders/rtx/utility/shader_types.slangh index 8658744a1..1f9998dfe 100644 --- a/src/dxvk/shaders/rtx/utility/shader_types.slangh +++ b/src/dxvk/shaders/rtx/utility/shader_types.slangh @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -127,9 +127,9 @@ __generic __target_intrinsic(hlsl) T saturate(T x) { - return clamp(x, - (T(0)), - (T(1))); + return clamp(x, + (T(0)), + (T(1))); } __target_intrinsic(glsl, "unpack16($0)")