Skip to content

Commit a8192ec

Browse files
Merge branch 'REMIX-4605-graphics-preset-fix' into 'main'
[REMIX-4605] fix graphics preset dropdown to apply the correct preset Closes REMIX-4605 See merge request lightspeedrtx/dxvk-remix-nv!1702
2 parents 53dff7d + 6035d19 commit a8192ec

11 files changed

+65
-45
lines changed

src/dxvk/imgui/dxvk_imgui.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,22 +1405,14 @@ namespace dxvk {
14051405

14061406
ImGui::TextSeparator("Preset Settings");
14071407

1408-
const auto graphicsPresetChanged = graphicsPresetCombo.getKey(&RtxOptions::graphicsPresetObject());
1409-
1410-
m_userGraphicsSettingChanged |= graphicsPresetChanged;
1408+
m_userGraphicsSettingChanged |= graphicsPresetCombo.getKey(&RtxOptions::graphicsPresetObject());
14111409

14121410
// Map settings to indirect particle level
14131411
int indirectLightParticlesLevel = 0;
14141412
if (RtxOptions::enableUnorderedResolveInIndirectRays()) {
14151413
indirectLightParticlesLevel = RtxOptions::enableUnorderedEmissiveParticlesInIndirectRays() ? 2 : 1;
14161414
}
14171415

1418-
// Map presets to options
1419-
1420-
if (graphicsPresetChanged) {
1421-
RtxOptions::updateGraphicsPresets(ctx->getDevice().ptr());
1422-
}
1423-
14241416
// Path Tracing Settings
14251417

14261418
ImGui::TextSeparator("Path Tracing Settings");

src/dxvk/rtx_render/rtx_context.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ namespace dxvk {
694694
getSceneManager().clearFogState();
695695

696696
// apply changes to RtxOptions after the frame has ended
697-
RtxOption<bool>::applyPendingValues();
697+
RtxOption<bool>::applyPendingValues(m_device.ptr());
698698

699699
// Update stats
700700
updateMetrics(gpuIdleTimeMilliseconds);

src/dxvk/rtx_render/rtx_debug_view.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,13 +1674,13 @@ namespace dxvk {
16741674
RtxOptions::useDenoiserReferenceMode();
16751675
}
16761676

1677-
void DebugView::maxValueOnChange() {
1677+
void DebugView::maxValueOnChange(DxvkDevice* device) {
16781678
// If the max value is negative, we want the min value to be further away from 0.
16791679
const float factor = maxValue() > 0 ? 0.99999f : 1.00001f;
16801680
minValueObject().setMaxValue(maxValue() * factor);
16811681
}
16821682

1683-
void DebugView::minValueOnChange() {
1683+
void DebugView::minValueOnChange(DxvkDevice* device) {
16841684
// If the min value is negative, we want the max value to be closer to 0.
16851685
const float factor = minValue() > 0 ? 1.00001f : 0.99999f;
16861686
maxValueObject().setMinValue(minValue() * factor);

src/dxvk/rtx_render/rtx_debug_view.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,13 @@ namespace dxvk {
164164
bool m_enableAlphaChannel = false;
165165
float m_scale = 1.f;
166166

167-
public: static void maxValueOnChange();
167+
public: static void maxValueOnChange(DxvkDevice* device);
168168
RTX_OPTION_ARGS("rtx.debugView", float, minValue, 0.f,
169169
"The minimum debug view input value to map to 0 in the output when the standard debug display is in use. Values below this value in the input will be clamped to 0 in the output.",
170170
args.environment = "DXVK_RTX_DEBUG_VIEW_MIN_VALUE",
171171
args.onChangeCallback = &maxValueOnChange);
172172

173-
public: static void minValueOnChange();
173+
public: static void minValueOnChange(DxvkDevice* device);
174174
RTX_OPTION_ARGS("rtx.debugView", float, maxValue, 1.f,
175175
"The maximum debug view input value to map to 1 in the output when the standard debug display is in use. Values above this value in the input will be clamped to 1 in the output.",
176176
args.environment = "DXVK_RTX_DEBUG_VIEW_MAX_VALUE",

src/dxvk/rtx_render/rtx_initializer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ namespace dxvk {
8484
ShaderManager::getInstance()->addGlobalExtraLayout(pCommon->getSceneManager().getBindlessResourceManager().getGlobalBindlessTableLayout(BindlessResourceManager::Samplers));
8585

8686
// Need to promote all of the hardware support Options before prewarming shaders.
87-
RtxOption<bool>::applyPendingValues();
87+
RtxOption<bool>::applyPendingValues(m_device);
8888

8989
// Kick off shader prewarming
9090
startPrewarmShaders();

src/dxvk/rtx_render/rtx_neural_radiance_cache.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ namespace dxvk {
132132
PREWARM_SHADER_PIPELINE(NrcResolveShader);
133133
}
134134

135-
void NeuralRadianceCache::NrcOptions::onMaxNumTrainingIterationsChanged() {
135+
void NeuralRadianceCache::NrcOptions::onMaxNumTrainingIterationsChanged(DxvkDevice* device) {
136136
targetNumTrainingIterations.setMaxValue(maxNumTrainingIterations());
137137
}
138138

@@ -316,7 +316,7 @@ namespace dxvk {
316316
return NrcContext::checkIsSupported(device);
317317
}
318318

319-
void NeuralRadianceCache::NrcOptions::onQualityPresetChanged() {
319+
void NeuralRadianceCache::NrcOptions::onQualityPresetChanged(DxvkDevice* device) {
320320
// Note: This function is called during onChange handler for quality preset option and
321321
// all the NRC calls have been issued, so it's safe to set the new settings using immediately.
322322
// In addition, this ensures the settings being applied immediately on start, rather than being delayed to the next frame

src/dxvk/rtx_render/rtx_neural_radiance_cache.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ namespace dxvk {
6161
"Each training batch contains 16K training records derived from path segments\n"
6262
"in the the NRC update path tracing pass. For example, 4 training iterations results in 64K training records.\n"
6363
"Higher number results in more responsive NRC cache at the cost of increased workload.\n");
64-
public: static void onMaxNumTrainingIterationsChanged();
64+
public: static void onMaxNumTrainingIterationsChanged(DxvkDevice* device);
6565
RTX_OPTION_ARGS("rtx.neuralRadianceCache", uint32_t, maxNumTrainingIterations, 16,
6666
"This controls the max number of training iterations to perform in a frame.\n"
6767
"When the pathtracer generates more training records than the ideal number of training records\n"
@@ -122,7 +122,7 @@ namespace dxvk {
122122
RTX_OPTION("rtx.neuralRadianceCache", bool, enableCalculateTrainingLoss, false, "Enables calculation of a training loss. Imposes a performance penalty.");
123123
RTX_OPTION("rtx.neuralRadianceCache", bool, enableAdaptiveTrainingDimensions, true, "Enables adaptive training dimensions that scale based off pathtracer's execution behavior on a given scene.");
124124

125-
static void onQualityPresetChanged();
125+
static void onQualityPresetChanged(DxvkDevice* device);
126126
RTX_OPTION_ARGS("rtx.neuralRadianceCache", QualityPreset, qualityPreset, QualityPreset::Ultra,
127127
"Quality Preset: Medium (0), High (1), Ultra (2).\n"
128128
"Adjusts quality of RTX Neural Radiance Cache (NRC):\n"

src/dxvk/rtx_render/rtx_option.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ namespace dxvk {
189189
}
190190
}
191191

192-
void RtxOptionImpl::invokeOnChangeCallback() const {
192+
void RtxOptionImpl::invokeOnChangeCallback(DxvkDevice* device) const {
193193
if (onChangeCallback) {
194-
onChangeCallback();
194+
onChangeCallback(device);
195195
}
196196
}
197197

src/dxvk/rtx_render/rtx_option.h

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#endif
4141

4242
namespace dxvk {
43+
class DxvkDevice;
44+
4345
// RtxOption refers to a serializable option, which can be of a basic type (i.e. int) or a class type (i.e. vector hash value)
4446
// On initialization, it retrieves a value from a Config object and add itself to a global list so that all options can be serialized
4547
// into a file when requested.
@@ -100,7 +102,7 @@ namespace dxvk {
100102
std::optional<GenericValue> minValue;
101103
std::optional<GenericValue> maxValue;
102104
uint32_t flags = 0;
103-
std::function<void()> onChangeCallback;
105+
std::function<void(DxvkDevice* device)> onChangeCallback;
104106

105107
RtxOptionImpl(XXH64_hash_t hash, const char* optionName, const char* optionCategory, OptionType optionType, const char* optionDescription) :
106108
hash(hash),
@@ -132,7 +134,7 @@ namespace dxvk {
132134
getDirtyRtxOptionMap()[hash] = this;
133135
}
134136

135-
void invokeOnChangeCallback() const;
137+
void invokeOnChangeCallback(DxvkDevice* device) const;
136138

137139
// Returns true if the value was changed
138140
bool clampValue(ValueType type);
@@ -173,7 +175,9 @@ namespace dxvk {
173175
std::optional<T> minValue;
174176
std::optional<T> maxValue;
175177

176-
typedef void (*RtxOptionOnChangeCallback)();
178+
// NOTE: onChange handlers can be invoked before the DxvkDevice is created,
179+
// so these callbacks need to null check the device.
180+
typedef void (*RtxOptionOnChangeCallback)(DxvkDevice* device);
177181
RtxOptionOnChangeCallback onChangeCallback = nullptr;
178182
};
179183

@@ -321,7 +325,7 @@ namespace dxvk {
321325
// This should be called at the very end of the frame in the dxvk-cs thread.
322326
// Before the first frame is rendered, it also needs to be called at least once during initialization.
323327
// It's currently called twice during init, due to multiple sections that set many Options then immediately use them.
324-
static void applyPendingValues() {
328+
static void applyPendingValues(DxvkDevice* device) {
325329
std::unique_lock<std::mutex> lock(RtxOptionImpl::s_updateMutex);
326330

327331
auto& dirtyOptions = RtxOptionImpl::getDirtyRtxOptionMap();
@@ -339,7 +343,7 @@ namespace dxvk {
339343

340344
// Invoke onChange callbacks after promoting all the values, so that newly set values will be updated at the end of the next frame
341345
for (RtxOptionImpl* rtxOption : dirtyOptionsVector) {
342-
rtxOption->invokeOnChangeCallback();
346+
rtxOption->invokeOnChangeCallback(device);
343347
}
344348
}
345349

@@ -397,6 +401,7 @@ namespace dxvk {
397401
pImpl->valueList[i].value = 0;
398402
*reinterpret_cast<BasicType*>(&pImpl->valueList[i].value) = value;
399403
}
404+
initializeClamping(args);
400405
}
401406
}
402407

@@ -408,6 +413,7 @@ namespace dxvk {
408413
for (int i = 0; i < (int)RtxOptionImpl::ValueType::Count; i++) {
409414
pImpl->valueList[i].pointer = new ClassType(value);
410415
}
416+
initializeClamping(args);
411417
}
412418
}
413419

@@ -457,17 +463,6 @@ namespace dxvk {
457463
pImpl->flags = args.flags;
458464
// Need to wrap this so we can cast it to the correct type
459465
pImpl->onChangeCallback = args.onChangeCallback;
460-
if constexpr (isClampable()) {
461-
if (args.minValue.has_value()) {
462-
setMinValue(args.minValue.value());
463-
}
464-
if (args.maxValue.has_value()) {
465-
setMaxValue(args.maxValue.value());
466-
}
467-
} else if (args.minValue.has_value() || args.maxValue.has_value()) {
468-
// If this happens on an option that should be clampable, the type probably needs to be added to isClampable(), and supported in the clampValue() method.
469-
assert(false && "RtxOption - args.minValue and args.maxValue are not supported for types not included in isClampable().");
470-
}
471466
globalRtxOptions[optionHash] = pImpl;
472467
return true;
473468
} else {
@@ -478,6 +473,21 @@ namespace dxvk {
478473
}
479474
}
480475

476+
// This needs to be done after the valueList is initialized in the constructor.
477+
void initializeClamping(RtxOptionArgs<T> args) {
478+
if constexpr (isClampable()) {
479+
if (args.minValue.has_value()) {
480+
setMinValue(args.minValue.value());
481+
}
482+
if (args.maxValue.has_value()) {
483+
setMaxValue(args.maxValue.value());
484+
}
485+
} else if (args.minValue.has_value() || args.maxValue.has_value()) {
486+
// If this happens on an option that should be clampable, the type probably needs to be added to isClampable(), and supported in the clampValue() method.
487+
assert(false && "RtxOption - args.minValue and args.maxValue are not supported for types not included in isClampable().");
488+
}
489+
}
490+
481491
// Get pointer to basic types
482492
template <typename BasicType, std::enable_if_t<std::is_pod_v<BasicType>, bool> = true>
483493
BasicType* getValuePtr(RtxOptionImpl::ValueType type) const {
@@ -505,7 +515,7 @@ namespace dxvk {
505515
} else {
506516
// For non-POD types (vectors, etc.), store as pointer
507517
if (!targetValue.has_value()) {
508-
targetValue = std::optional<GenericValue>();
518+
targetValue = std::optional<GenericValue>(GenericValue{});
509519
// Note: This is a `new` with no matching `delete`. This is safe because the
510520
// RtxOptionImpl object is never destroyed, and follows the pattern used in the constructor.
511521
targetValue.value().pointer = new T();

src/dxvk/rtx_render/rtx_options.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,29 @@
3939

4040
namespace dxvk {
4141
std::unique_ptr<RtxOptions> RtxOptions::m_instance = nullptr;
42+
43+
void RtxOptions::graphicsPresetOnChange(DxvkDevice* device) {
44+
// device will be nullptr during initial config loading.
45+
if (device == nullptr) {
46+
return;
47+
}
48+
49+
// TODO[REMIX-1482]: Currently tests expect to skip applying the graphics preset, so this needs to be skipped in test runs.
50+
// When we fix tests to actually use the preset, the if statement should be removed.
51+
if (env::getEnvVar("DXVK_TERMINATE_APP_FRAME") == "" ||
52+
env::getEnvVar("DXVK_GRAPHICS_PRESET_TYPE") != "0") {
53+
RtxOptions::updateGraphicsPresets(device);
54+
}
55+
}
4256

43-
void RtxOptions::showUICursorOnChange() {
57+
void RtxOptions::showUICursorOnChange(DxvkDevice* device) {
4458
if (ImGui::GetCurrentContext() != nullptr) {
4559
auto& io = ImGui::GetIO();
4660
io.MouseDrawCursor = RtxOptions::showUICursor() && RtxOptions::showUI() != UIType::None;
4761
}
4862
}
4963

50-
void RtxOptions::blockInputToGameInUIOnChange() {
64+
void RtxOptions::blockInputToGameInUIOnChange(DxvkDevice* device) {
5165
const bool doBlock = RtxOptions::blockInputToGameInUI() && RtxOptions::showUI() != UIType::None;
5266

5367
BridgeMessageChannel::get().send("UWM_REMIX_UIACTIVE_MSG", doBlock ? 1 : 0, 0);

0 commit comments

Comments
 (0)