From 2da8ad6273d90557f42a27076eda6fa4568dd713 Mon Sep 17 00:00:00 2001 From: Mark Henderson Date: Wed, 22 Jan 2025 10:55:02 -0800 Subject: [PATCH] [REMIX-3833] Only prewarm shader variants accessible without opening the menus. Do not compile shader variants that are not used based on currently selected options. This improves startup times significantly when the shader cache is empty. --- RtxOptions.md | 1 + src/dxvk/rtx_render/rtx_options.h | 1 + .../rtx_render/rtx_pathtracer_gbuffer.cpp | 57 +++++++++++++----- .../rtx_pathtracer_integrate_indirect.cpp | 59 +++++++++++++------ 4 files changed, 86 insertions(+), 32 deletions(-) diff --git a/RtxOptions.md b/RtxOptions.md index 4bdde000..4d71a855 100644 --- a/RtxOptions.md +++ b/RtxOptions.md @@ -499,6 +499,7 @@ Tables below enumerate all the options and their defaults set by RTX Remix. Note |rtx.postfx.vignetteRadius|float|0.8|The radius that vignette effect starts\. The unit is normalized screen space, 0 represents the center, 1 means the edge of the short edge of the rendering window\. So, this setting can larger than 1 until reach to the long edge of the rendering window\.| |rtx.postfx.vignetteSoftness|float|0.2|The gradient that the color drop to black from the vignetteRadius to the edge of rendering window\.| |rtx.presentThrottleDelay|int|16|A time in milliseconds that the DXVK presentation thread should sleep for\. Requires present throttling to be enabled to take effect\.
Note that the application may sleep for longer than the specified time as is expected with sleep functions in general\.| +|rtx.prewarmAllShaderVariants|bool|False|When set to true, all variants of shaders will be pre compiled at launch\.| |rtx.primaryRayMaxInteractions|int|32|The maximum number of resolver interactions to use for primary \(initial G\-Buffer\) rays\.
This affects how many Decals, Ray Portals and potentially particles \(if unordered approximations are not enabled\) may be interacted with along a ray at the cost of performance for higher amounts of interactions\.| |rtx.psrRayMaxInteractions|int|32|The maximum number of resolver interactions to use for PSR \(primary surface replacement G\-Buffer\) rays\.
This affects how many Decals, Ray Portals and potentially particles \(if unordered approximations are not enabled\) may be interacted with along a ray at the cost of performance for higher amounts of interactions\.| |rtx.psrrMaxBounces|int|10|The maximum number of Reflection PSR bounces to traverse\. Must be 15 or less due to payload encoding\.
Should be set higher when many mirror\-like reflection bounces may be needed, though more bounces may come at a higher performance cost\.| diff --git a/src/dxvk/rtx_render/rtx_options.h b/src/dxvk/rtx_render/rtx_options.h index 584340e6..527d88b2 100644 --- a/src/dxvk/rtx_render/rtx_options.h +++ b/src/dxvk/rtx_render/rtx_options.h @@ -283,6 +283,7 @@ namespace dxvk { RTX_OPTION_ENV("rtx", RaytraceModePreset, raytraceModePreset, RaytraceModePreset::Auto, "DXVK_RAYTRACE_MODE_PRESET_TYPE", ""); RTX_OPTION_ENV("rtx", std::string, sourceRootPath, "", "RTX_SOURCE_ROOT", "A path pointing at the root folder of the project, used to override the path to the root of the project generated at build-time (as this path is only valid for the machine the project was originally compiled on). Used primarily for locating shader source files for runtime shader recompilation."); RTX_OPTION("rtx", bool, recompileShadersOnLaunch, false, "When set to true runtime shader recompilation will execute on the first frame after launch."); + RTX_OPTION_ENV("rtx", bool, prewarmAllShaderVariants, false, "RTX_PREWARM_ALL_SHADER_VARIANTS", "When set to true, all variants of shaders will be pre compiled at launch."); RTX_OPTION("rtx", bool, useLiveShaderEditMode, false, "When set to true shaders will be automatically recompiled when any shader file is updated (saved for instance) in addition to the usual manual recompilation trigger."); RTX_OPTION("rtx", float, emissiveIntensity, 1.0f, "A general scale factor on all emissive intensity values globally. Generally per-material emissive intensities should be used, but this option may be useful for debugging without needing to author materials."); RTX_OPTION("rtx", float, fireflyFilteringLuminanceThreshold, 1000.0f, "Maximum luminance threshold for the firefly filtering to clamp to."); diff --git a/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp b/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp index c1e27b14..2ec71e0a 100644 --- a/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp +++ b/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp @@ -151,25 +151,52 @@ namespace dxvk { } void DxvkPathtracerGbuffer::prewarmShaders(DxvkPipelineManager& pipelineManager) const { - const bool isOpacityMicromapSupported = OpacityMicromapManager::checkIsOpacityMicromapSupported(*m_device); - const bool isShaderExecutionReorderingSupported = - RtxContext::checkIsShaderExecutionReorderingSupported(*m_device) && - RtxOptions::Get()->isShaderExecutionReorderingInPathtracerGbufferEnabled(); - - for (int32_t isPSRPass = 1; isPSRPass >= 0; isPSRPass--) { - for (int32_t includePortals = 1; includePortals >= 0; includePortals--) { - for (int32_t useRayQuery = 1; useRayQuery >= 0; useRayQuery--) { - for (int32_t serEnabled = isShaderExecutionReorderingSupported; serEnabled >= 0; serEnabled--) { - for (int32_t ommEnabled = isOpacityMicromapSupported; ommEnabled >= 0; ommEnabled--) { - pipelineManager.registerRaytracingShaders(getPipelineShaders(isPSRPass, useRayQuery, serEnabled, ommEnabled, includePortals)); + if (RtxOptions::prewarmAllShaderVariants()) { + const bool isOpacityMicromapSupported = OpacityMicromapManager::checkIsOpacityMicromapSupported(*m_device); + const bool isShaderExecutionReorderingSupported = + RtxContext::checkIsShaderExecutionReorderingSupported(*m_device) && + RtxOptions::Get()->isShaderExecutionReorderingInPathtracerGbufferEnabled(); + + for (int32_t isPSRPass = 1; isPSRPass >= 0; isPSRPass--) { + for (int32_t includePortals = 1; includePortals >= 0; includePortals--) { + for (int32_t useRayQuery = 1; useRayQuery >= 0; useRayQuery--) { + for (int32_t serEnabled = isShaderExecutionReorderingSupported; serEnabled >= 0; serEnabled--) { + for (int32_t ommEnabled = isOpacityMicromapSupported; ommEnabled >= 0; ommEnabled--) { + pipelineManager.registerRaytracingShaders(getPipelineShaders(isPSRPass, useRayQuery, serEnabled, ommEnabled, includePortals)); + } } } } - } - DxvkComputePipelineShaders shaders; - shaders.cs = getComputeShader(isPSRPass); - pipelineManager.createComputePipeline(shaders); + DxvkComputePipelineShaders shaders; + shaders.cs = getComputeShader(isPSRPass); + pipelineManager.createComputePipeline(shaders); + } + } else { + const bool serEnabled = RtxOptions::Get()->isShaderExecutionReorderingInPathtracerGbufferEnabled(); + const bool ommEnabled = RtxOptions::Get()->getEnableOpacityMicromap(); + const bool useNeeCache = NeeCachePass::enable(); + const bool includePortals = RtxOptions::Get()->rayPortalModelTextureHashes().size() > 0; + + // Need both PSR and non-PSR passes. + for (int32_t isPSRPass = 1; isPSRPass >= 0; isPSRPass--) { + // Prewarm POM on and off, as that can change based on game content (if nothing in the frame has a height texture, then POM turns off) + for (int32_t pomEnabled = 1; pomEnabled >= 0; pomEnabled--) { + DxvkComputePipelineShaders shaders; + switch (RtxOptions::Get()->getRenderPassGBufferRaytraceMode()) { + case RaytraceMode::RayQuery: + shaders.cs = getComputeShader(isPSRPass); + pipelineManager.createComputePipeline(shaders); + break; + case RaytraceMode::RayQueryRayGen: + pipelineManager.registerRaytracingShaders(getPipelineShaders(isPSRPass, true, serEnabled, ommEnabled, includePortals)); + break; + case RaytraceMode::TraceRay: + pipelineManager.registerRaytracingShaders(getPipelineShaders(isPSRPass, false, serEnabled, ommEnabled, includePortals)); + break; + } + } + } } } diff --git a/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp b/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp index 96377c52..46d562f5 100644 --- a/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp +++ b/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp @@ -215,28 +215,53 @@ namespace dxvk { } void DxvkPathtracerIntegrateIndirect::prewarmShaders(DxvkPipelineManager& pipelineManager) const { - - const bool isOpacityMicromapSupported = OpacityMicromapManager::checkIsOpacityMicromapSupported(*m_device); - const bool isShaderExecutionReorderingSupported = - RtxContext::checkIsShaderExecutionReorderingSupported(*m_device) && - RtxOptions::Get()->isShaderExecutionReorderingInPathtracerIntegrateIndirectEnabled(); - - for (int32_t useNeeCache = 1; useNeeCache >= 0; useNeeCache--) { - for (int32_t includesPortals = 1; includesPortals >= 0; includesPortals--) { - for (int32_t useRayQuery = 1; useRayQuery >= 0; useRayQuery--) { - for (int32_t serEnabled = isShaderExecutionReorderingSupported; serEnabled >= 0; serEnabled--) { - for (int32_t ommEnabled = isOpacityMicromapSupported; ommEnabled >= 0; ommEnabled--) { - for (int32_t pomEnable = 1; pomEnable >= 0; pomEnable--) { - pipelineManager.registerRaytracingShaders(getPipelineShaders(useRayQuery, serEnabled, ommEnabled, useNeeCache, includesPortals, pomEnable)); + if (RtxOptions::prewarmAllShaderVariants()) { + const bool isOpacityMicromapSupported = OpacityMicromapManager::checkIsOpacityMicromapSupported(*m_device); + const bool isShaderExecutionReorderingSupported = + RtxContext::checkIsShaderExecutionReorderingSupported(*m_device) && + RtxOptions::Get()->isShaderExecutionReorderingInPathtracerIntegrateIndirectEnabled(); + + for (int32_t useNeeCache = 1; useNeeCache >= 0; useNeeCache--) { + for (int32_t includesPortals = 1; includesPortals >= 0; includesPortals--) { + for (int32_t useRayQuery = 1; useRayQuery >= 0; useRayQuery--) { + for (int32_t serEnabled = isShaderExecutionReorderingSupported; serEnabled >= 0; serEnabled--) { + for (int32_t ommEnabled = isOpacityMicromapSupported; ommEnabled >= 0; ommEnabled--) { + for (int32_t pomEnabled = 1; pomEnabled >= 0; pomEnabled--) { + + + pipelineManager.registerRaytracingShaders(getPipelineShaders(useRayQuery, serEnabled, ommEnabled, useNeeCache, includesPortals, pomEnabled)); + } } } } } - } - DxvkComputePipelineShaders shaders; - shaders.cs = getComputeShader(useNeeCache); - pipelineManager.createComputePipeline(shaders); + DxvkComputePipelineShaders shaders; + shaders.cs = getComputeShader(useNeeCache); + pipelineManager.createComputePipeline(shaders); + } + } else { + const bool serEnabled = RtxOptions::Get()->isShaderExecutionReorderingInPathtracerIntegrateIndirectEnabled(); + const bool ommEnabled = OpacityMicromapManager::checkIsOpacityMicromapSupported(*m_device) && RtxOptions::Get()->opacityMicromap.enable(); + const bool useNeeCache = NeeCachePass::enable(); + const bool includesPortals = RtxOptions::Get()->rayPortalModelTextureHashes().size() > 0; + + // Prewarm POM on and off, as that can change based on game content (if nothing in the frame has a height texture, then POM turns off) + for (int32_t pomEnabled = 1; pomEnabled >= 0; pomEnabled--) { + DxvkComputePipelineShaders shaders; + switch (RtxOptions::Get()->getRenderPassIntegrateIndirectRaytraceMode()) { + case RaytraceMode::RayQuery: + shaders.cs = getComputeShader(useNeeCache); + pipelineManager.createComputePipeline(shaders); + break; + case RaytraceMode::RayQueryRayGen: + pipelineManager.registerRaytracingShaders(getPipelineShaders(true, serEnabled, ommEnabled, useNeeCache, includesPortals, pomEnabled)); + break; + case RaytraceMode::TraceRay: + pipelineManager.registerRaytracingShaders(getPipelineShaders(false, serEnabled, ommEnabled, useNeeCache, includesPortals, pomEnabled)); + break; + } + } } }