@@ -255,11 +255,30 @@ namespace dxvk {
255255 releaseValue (optionLayer.second .value , type);
256256 }
257257
258- for (int i = 0 ; i < (int )ValueType::Count; i++) {
259- releaseValue (valueList[i], type);
258+ releaseValue (resolvedValue, type);
259+ }
260+
261+ const GenericValue& RtxOptionImpl::getGenericValue (const ValueType valueType) const {
262+ if (valueType == ValueType::DefaultValue) {
263+ return optionLayerValueQueue.at (0 ).value ;
264+ } else if (valueType == ValueType::PendingValue) {
265+ return optionLayerValueQueue.begin ()->second .value ;
266+ } else if (valueType == ValueType::Value) {
267+ return resolvedValue;
268+ } else {
269+ Logger::warn (" [RTX Option]: Unknown generic value type." );
270+ static const GenericValue dummyValue {};
271+ return dummyValue;
260272 }
261273 }
262274
275+ GenericValue& RtxOptionImpl::getGenericValue (const ValueType valueType) {
276+ // Reuse the const overload to avoid duplicating switch logic.
277+ // const_cast is safe here because we are returning a non-const reference
278+ // only when called on a non-const RtxOptionImpl instance.
279+ return const_cast <GenericValue&>(static_cast <const RtxOptionImpl*>(this )->getGenericValue (valueType));
280+ }
281+
263282 const char * RtxOptionImpl::getTypeString () const {
264283 switch (type) {
265284 case OptionType::Bool: return " bool" ;
@@ -280,7 +299,7 @@ namespace dxvk {
280299 }
281300
282301 std::string RtxOptionImpl::genericValueToString (ValueType valueType) const {
283- const GenericValue & value = valueList[ static_cast < int > (valueType)] ;
302+ const auto & value = getGenericValue (valueType);
284303 return genericValueToString (value);
285304 }
286305
@@ -334,7 +353,7 @@ namespace dxvk {
334353 }
335354
336355 bool RtxOptionImpl::clampValue (ValueType valueType) {
337- GenericValue & value = valueList[ static_cast < int > (valueType)] ;
356+ auto & value = getGenericValue (valueType);
338357 bool changed = false ;
339358
340359 switch (type) {
@@ -446,17 +465,17 @@ namespace dxvk {
446465
447466 void RtxOptionImpl::readOption (const Config& options, RtxOptionImpl::ValueType valueType) {
448467 const std::string fullName = getFullName ();
449- auto & value = valueList[( int ) valueType] ;
468+ auto & value = getGenericValue ( valueType) ;
450469 readValue (options, fullName, value);
451470
452471 clampValue (valueType);
453472
454473 if (valueType == ValueType::PendingValue) {
455474 // If reading into the pending value, need to mark the option as dirty so it gets copied to the value at the end of the frame.
456- markDirty ();
475+ // markDirty();
457476 } else if (valueType == ValueType::Value) {
458477 // If reading into the value, need to immediately copy to the pending value so they stay in sync.
459- copyValue (ValueType::Value, ValueType::PendingValue);
478+ copyValue (resolvedValue, getGenericValue ( ValueType::PendingValue) );
460479
461480 // Also mark the option dirty so the onChange callback is invoked at the normal time.
462481 markDirty ();
@@ -468,7 +487,7 @@ namespace dxvk {
468487 return ;
469488
470489 std::string fullName = getFullName ();
471- auto & value = valueList[( int ) ValueType::Value] ;
490+ auto & value = resolvedValue ;
472491
473492 if (changedOptionOnly) {
474493 if (isDefault ()) {
@@ -518,6 +537,15 @@ namespace dxvk {
518537 }
519538 }
520539
540+ void RtxOptionImpl::insertEmptyOptionLayer (const uint32_t priority, const float blendStrength, const float blendStrengthThreshold) {
541+ GenericValue optionLayerValue = createGenericValue (type);
542+ const PrioritizedValue newValue (optionLayerValue, priority, blendStrength, blendStrengthThreshold);
543+ auto [it, inserted] = optionLayerValueQueue.emplace (priority, newValue);
544+ if (!inserted) {
545+ Logger::warn (" [RTX Option]: Duplicate priority " + std::to_string (priority) + " ignored (only first kept)." );
546+ }
547+ }
548+
521549 void RtxOptionImpl::insertOptionLayerValue (const GenericValue& value, const uint32_t priority, const float blendStrength, const float blendStrengthThreshold) {
522550 // Check if there's a same priority layer
523551 for (const auto & optionLayerValue : optionLayerValueQueue) {
@@ -527,21 +555,10 @@ namespace dxvk {
527555 }
528556 }
529557
530- // Only float or float based vectors are allowed to mix with other option layers
531- float layerBlendStrenth = blendStrength;
532- if (type != OptionType::Float && type != OptionType::Vector2 && type != OptionType::Vector3 && type != OptionType::Vector4) {
533- // For disallowed types, snap the strength to either 0.0f or 1.0f, based on whether it passes the strength threshold
534- if (blendStrength >= blendStrengthThreshold || priority == 0 ) {
535- layerBlendStrenth = 1 .0f ;
536- } else {
537- layerBlendStrenth = 0 .0f ;
538- }
539- }
540-
541558 GenericValue optionLayerValue = createGenericValue (type);
542559 copyValue (value, optionLayerValue);
543560
544- const PrioritizedValue newValue { optionLayerValue, priority, layerBlendStrenth } ;
561+ const PrioritizedValue newValue ( optionLayerValue, priority, blendStrength, blendStrengthThreshold) ;
545562 auto [it, inserted] = optionLayerValueQueue.emplace (priority, newValue);
546563 if (!inserted) {
547564 Logger::warn (" [RTX Option]: Duplicate priority " + std::to_string (priority) + " ignored (only first kept)." );
@@ -557,8 +574,6 @@ namespace dxvk {
557574 insertOptionLayerValue (value.data , optionLayer.getPriority (), optionLayer.getBlendStrength (), optionLayer.getBlendStrengthThreshold ());
558575 // When adding a new option layer, dirty current option
559576 markDirty ();
560- } else {
561- Logger::warn (" [RTX Option] Attempted to read option that is not defined in the option layer." );
562577 }
563578 }
564579
@@ -584,27 +599,16 @@ namespace dxvk {
584599 // Find the option layer value that the strength needs to be updated (same priority)
585600 for (auto & optionLayerValue : optionLayerValueQueue) {
586601 if (optionLayer.getPriority () == optionLayerValue.second .priority ) {
587- if (type == OptionType::Float || type == OptionType::Vector2 || type == OptionType::Vector3 || type == OptionType::Vector4) {
588- // Only float or float based vectors are allowed to mix with other option layers
589- optionLayerValue.second .blendStrength = optionLayer.getBlendStrength ();
590- } else {
591- // For disallowed types, snap the strength to either 0.0f or 1.0f, based on whether it passes the strength threshold
592- if (optionLayer.getBlendStrength () >= optionLayer.getBlendStrengthThreshold ()) {
593- optionLayerValue.second .blendStrength = 1 .0f ;
594- } else {
595- optionLayerValue.second .blendStrength = 0 .0f ;
596- }
597- }
602+ optionLayerValue.second .blendStrength = optionLayer.getBlendStrength ();
603+ optionLayerValue.second .blendThreshold = optionLayer.getBlendStrengthThreshold ();
598604 return ;
599605 }
600606 }
601- } else {
602- Logger::warn (" [RTX Option] Attempted to update option that is not defined in the option layer." );
603607 }
604608 }
605609
606610 bool RtxOptionImpl::isDefault () const {
607- return isEqual (ValueType::Value, ValueType::DefaultValue);
611+ return isEqual (resolvedValue, getGenericValue ( ValueType::DefaultValue) );
608612 }
609613
610614 bool RtxOptionImpl::isEqual (const GenericValue& aValue, const GenericValue& bValue) const {
@@ -649,24 +653,20 @@ namespace dxvk {
649653 return false ;
650654 }
651655
652- bool RtxOptionImpl::isEqual (ValueType a, ValueType b) const {
653- return isEqual (valueList[(int ) a], valueList[(int ) b]);
654- }
655-
656656 void RtxOptionImpl::resetOption () {
657657 if (flags & (uint32_t ) RtxOptionFlags::NoReset)
658658 return ;
659659
660660 // If value and defaultValue are equal, no need to to change the Value.
661- if (isEqual (ValueType::Value, ValueType::DefaultValue)) {
661+ if (isEqual (resolvedValue, getGenericValue ( ValueType::DefaultValue) )) {
662662 // Check if the option has a pending value, and if so reset that.
663- if (isEqual (ValueType::PendingValue, ValueType::DefaultValue)) {
664- copyValue (ValueType::DefaultValue, ValueType::PendingValue);
663+ if (isEqual (getGenericValue ( ValueType::PendingValue), getGenericValue ( ValueType::DefaultValue) )) {
664+ copyValue (getGenericValue ( ValueType::DefaultValue), getGenericValue ( ValueType::PendingValue) );
665665 }
666666 return ;
667667 }
668668
669- copyValue (ValueType::DefaultValue, ValueType::PendingValue);
669+ copyValue (getGenericValue ( ValueType::DefaultValue), getGenericValue ( ValueType::PendingValue) );
670670 markDirty ();
671671 }
672672
@@ -713,10 +713,6 @@ namespace dxvk {
713713 }
714714 }
715715
716- void RtxOptionImpl::copyValue (ValueType source, ValueType target) {
717- copyValue (valueList[(int ) source], valueList[(int ) target]);
718- }
719-
720716 void RtxOptionImpl::addWeightedValue (const GenericValue& source, const float weight, GenericValue& target) {
721717 switch (type) {
722718 case OptionType::Float:
@@ -746,21 +742,9 @@ namespace dxvk {
746742 }
747743 }
748744
749- void RtxOptionImpl::copyValueToOptionLayer (ValueType source) {
750- const auto & sourceValue = valueList[(int ) source];
751- // Ensure the top-most layer is the runtime layer, insert if missing.
752- if (optionLayerValueQueue.begin ()->second .priority != RtxOptionLayer::s_runtimeOptionLayerPriority) {
753- // Insert runtime layer with full strength so runtime overrides win immediately.
754- insertOptionLayerValue (sourceValue, RtxOptionLayer::s_runtimeOptionLayerPriority, 1 .0f , 1 .0f );
755- } else {
756- // Runtime layer already present at top, update its value in-place.
757- copyValue (sourceValue, optionLayerValueQueue.begin ()->second .value );
758- }
759- }
760-
761745 void RtxOptionImpl::copyOptionLayerToValue () {
762746 GenericValue& optionValueTop = optionLayerValueQueue.begin ()->second .value ;
763- const auto & pendingValue = valueList[( int ) RtxOptionImpl::ValueType::PendingValue] ;
747+ const auto & pendingValue = getGenericValue ( RtxOptionImpl::ValueType::PendingValue) ;
764748
765749 if (optionLayerValueQueue.begin ()->second .priority == RtxOptionLayer::s_runtimeOptionLayerPriority &&
766750 !isEqual (pendingValue, optionValueTop)) {
@@ -802,18 +786,25 @@ namespace dxvk {
802786 float throughput = 1 .0f ;
803787 // Loop layers from highest priority to lowest to lerp the value across layers base on the blend strength of layers
804788 for (const auto & optionLayer : optionLayerValueQueue) {
805- // Stop when the blend strength is larger than 1, because lerp(a, b, 1.0f) => b, we don't need to loop lower priority values
806- if (optionLayer.second .blendStrength >= 1 .0f ) {
807- addWeightedValue (optionLayer.second .value , throughput, optionValue.data );
808- break ;
809- }
789+ if (type == OptionType::Float || type == OptionType::Vector2 || type == OptionType::Vector3 || type == OptionType::Vector4) {
790+ // Stop when the blend strength is larger than 1, because lerp(a, b, 1.0f) => b, we don't need to loop lower priority values
791+ if (optionLayer.second .blendStrength >= 1 .0f ) {
792+ addWeightedValue (optionLayer.second .value , throughput, optionValue.data );
793+ break ;
794+ }
810795
811- addWeightedValue (optionLayer.second .value , optionLayer.second .blendStrength * throughput, optionValue.data );
812- throughput *= (1 .0f - optionLayer.second .blendStrength );
796+ addWeightedValue (optionLayer.second .value , optionLayer.second .blendStrength * throughput, optionValue.data );
797+ throughput *= (1 .0f - optionLayer.second .blendStrength );
798+ } else {
799+ if (optionLayer.second .blendStrength >= optionLayer.second .blendThreshold || optionLayer.second .priority == 0 ) {
800+ addWeightedValue (optionLayer.second .value , throughput, optionValue.data );
801+ break ;
802+ }
803+ }
813804 }
814805
815- // Copy to valueList
816- copyValue (optionValue.data , valueList[( int ) RtxOptionImpl::ValueType::Value] );
806+ // Copy to resolvedValue
807+ copyValue (optionValue.data , resolvedValue );
817808 }
818809
819810 bool RtxOptionImpl::writeMarkdownDocumentation (const char * outputMarkdownFilePath) {
@@ -1017,6 +1008,12 @@ Tables below enumerate all the options and their defaults set by RTX Remix. Note
10171008 return s_rtxOptionLayers;
10181009 }
10191010
1011+ void RtxOptionImpl::addRtxOptionLayer (const RtxOptionLayer& layer) {
1012+ if (layer.isValid ()) {
1013+ getRtxOptionLayerMap ().insert (layer);
1014+ }
1015+ }
1016+
10201017 bool writeMarkdownDocumentation (const char * outputMarkdownFilePath) {
10211018 return dxvk::RtxOptionImpl::writeMarkdownDocumentation (outputMarkdownFilePath);
10221019 }
0 commit comments