Skip to content

Commit 1d6dcb2

Browse files
committed
Merge branch 'OptionLayerGui1.3' into 'release/v1.3'
[REMIX-4881] [REMIX-4882] [REMIX-4883] [REMIX-4884] Improving RtxOption Layer gui See merge request lightspeedrtx/dxvk-remix-nv!1863
2 parents 78a51af + 6e6d4a0 commit 1d6dcb2

File tree

1 file changed

+149
-60
lines changed

1 file changed

+149
-60
lines changed

src/dxvk/imgui/dxvk_imgui.cpp

Lines changed: 149 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,42 +2086,58 @@ namespace dxvk {
20862086
}
20872087
#endif
20882088

2089-
if (ImGui::CollapsingHeader("Option Layers")) {
2089+
if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Option Layers"), "View what options are present in each layer, and alter the blend strength and threshold for them.")) {
20902090
ImGui::Indent();
2091+
static char optionLayerFilter[256] = "";
2092+
if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Layer Controls"), "Some utilities for controlling the option layers and display.")) {
2093+
ImGui::Indent();
20912094

2092-
if (IMGUI_ADD_TOOLTIP(ImGui::Button("Disable Layers"), "Reset all settings to Default.")) {
2093-
for (auto& [unusedLayerKey, optionLayerPtr] : RtxOptionImpl::getRtxOptionLayerMap()) {
2094-
optionLayerPtr->requestEnabled(false);
2095+
if (IMGUI_ADD_TOOLTIP(ImGui::Button("Disable Layers"), "All optional layers will be disabled. The runtime and default layers will remain active.")) {
2096+
for (auto& [layerKey, optionLayerPtr] : RtxOptionImpl::getRtxOptionLayerMap()) {
2097+
if (layerKey.priority != RtxOptionLayer::s_runtimeOptionLayerPriority && layerKey.priority != (uint32_t)RtxOptionLayer::SystemLayerPriority::Default) {
2098+
optionLayerPtr->requestEnabled(false);
2099+
}
2100+
}
20952101
}
2096-
}
20972102

2098-
ImGui::SameLine();
2099-
if (IMGUI_ADD_TOOLTIP(ImGui::Button("Enable Layers"), "Enable all option layers.")) {
2100-
for (auto& [unusedLayerKey, optionLayerPtr] : RtxOptionImpl::getRtxOptionLayerMap()) {
2101-
optionLayerPtr->requestEnabled(true);
2103+
ImGui::SameLine();
2104+
if (IMGUI_ADD_TOOLTIP(ImGui::Button("Enable Layers"), "Enable all option layers.")) {
2105+
for (auto& [unusedLayerKey, optionLayerPtr] : RtxOptionImpl::getRtxOptionLayerMap()) {
2106+
optionLayerPtr->requestEnabled(true);
2107+
}
21022108
}
2103-
}
21042109

2105-
ImGui::Checkbox("Override configs", &RtxOptions::Option::overwriteConfigObject());
2110+
// Filter for option layer contents
2111+
IMGUI_ADD_TOOLTIP(ImGui::InputText("RtxOption Display Filter", optionLayerFilter, IM_ARRAYSIZE(optionLayerFilter)),
2112+
"Filter options displayed in the Contents sections. Only options containing this text will be shown.");
2113+
2114+
2115+
ImGui::Checkbox("Pause Graph Execution", &GraphManager::pauseGraphUpdatesObject());
2116+
if (ImGui::IsItemHovered()) {
2117+
ImGui::SetTooltip(
2118+
"Many graphs set `enable`, `blendStrength`, and `blendThreshold` every frame.\n"
2119+
"Pausing the graph execution will allow controlling these values without interference.");
2120+
}
2121+
ImGui::Unindent();
2122+
}
2123+
// Pre-compute lowercased filter once for efficiency
2124+
std::string filterLower = optionLayerFilter;
2125+
std::transform(filterLower.begin(), filterLower.end(), filterLower.begin(), ::tolower);
21062126

21072127
uint32_t optionLayerCounter = 1;
21082128
for (auto& [layerKey, optionLayerPtr] : RtxOptionImpl::getRtxOptionLayerMap()) {
2109-
// Runtime option layer priority is reserved for real-time user changes.
2110-
// These layers should not be modified through the GUI.
2111-
if (layerKey.priority != RtxOptionLayer::s_runtimeOptionLayerPriority) {
2112-
RtxOptionLayer& optionLayer = *optionLayerPtr;
2113-
ImGui::Dummy(ImVec2(0.0f, 5.0f));
2114-
ImGui::Separator();
2115-
ImGui::Dummy(ImVec2(0.0f, 5.0f));
2129+
RtxOptionLayer& optionLayer = *optionLayerPtr;
21162130

2131+
std::string displayName;
2132+
2133+
if (layerKey.priority != RtxOptionLayer::s_runtimeOptionLayerPriority && layerKey.priority != (uint32_t)RtxOptionLayer::SystemLayerPriority::Default) {
21172134
const std::string optionLayerName = optionLayer.getName();
2118-
2135+
21192136
// Process the display name
2120-
std::string displayName;
21212137
// construct "rtx-remix/mods/" using OS appropriate separator
21222138
const std::string modsMarker = (std::filesystem::path("rtx-remix") / "mods" / "").string();
21232139
size_t modsPos = optionLayerName.find(modsMarker);
2124-
2140+
21252141
constexpr size_t kLongestPathLength = 30;
21262142
if (modsPos != std::string::npos) {
21272143
// Extract portion after "mods/"
@@ -2132,49 +2148,27 @@ namespace dxvk {
21322148
} else {
21332149
displayName = optionLayerName;
21342150
}
2151+
bool pendingEnabled = optionLayer.getPendingEnabled();
2152+
float pendingStrength = optionLayer.getPendingBlendStrength();
2153+
float pendingThreshold = optionLayer.getPendingBlendThreshold();
21352154

21362155
const std::string optionLayerText = std::to_string(optionLayerCounter++) + ". " + displayName;
2137-
const std::string optionLayerStrengthText = " Strength###Strength_" + displayName;
2138-
const std::string optionLayerThresholdText = " Threshold###Threshold_" + displayName;
2156+
const bool isLayerActive = pendingEnabled && pendingStrength > pendingThreshold;
21392157

2140-
// Use pending values for UI display and send requests on change
2141-
bool pendingEnabled = optionLayer.getPendingEnabled();
2142-
if (IMGUI_ADD_TOOLTIP(ImGui::Checkbox(optionLayerText.c_str(), &pendingEnabled), optionLayer.getName().c_str())) {
2143-
optionLayer.requestEnabled(pendingEnabled);
2144-
}
2145-
2146-
float pendingStrength = optionLayer.getPendingBlendStrength();
2147-
if (IMGUI_ADD_TOOLTIP(ImGui::SliderFloat(optionLayerStrengthText.c_str(), &pendingStrength, 0.0f, 1.0f),
2148-
"Adjusts the blending strength of this option layer (0 = off, 1 = full effect).")) {
2149-
optionLayer.requestBlendStrength(pendingStrength);
2158+
// Dim the header text when the layer is inactive
2159+
if (!isLayerActive) {
2160+
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled));
21502161
}
21512162

2152-
float pendingThreshold = optionLayer.getPendingBlendThreshold();
2153-
if (IMGUI_ADD_TOOLTIP(ImGui::SliderFloat(optionLayerThresholdText.c_str(), &pendingThreshold, 0.0f, 1.0f),
2154-
"Sets the blending strength threshold for this option layer. Only applicable to non-float variables. The option is applied only when the blend strength exceeds this threshold.")) {
2155-
optionLayer.requestBlendThreshold(pendingThreshold);
2163+
bool headerOpen = IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader(optionLayerText.c_str(), collapsingHeaderClosedFlags), optionLayer.getName().c_str());
2164+
2165+
if (!isLayerActive) {
2166+
ImGui::PopStyleColor();
21562167
}
2157-
2158-
// TODO: We need to move these part into a separate saving session
2159-
// std::string layerType;
2160-
// if (optionLayerName == "rtx.conf") {
2161-
// layerType = "RTX";
2162-
// } else if (optionLayerName == "quality.conf") {
2163-
// layerType = "Quality";
2164-
// } else if (optionLayerName == "user.conf") {
2165-
// layerType = "Runtime";
2166-
// } else {
2167-
// layerType = optionLayerName;
2168-
// }
2169-
// const std::string optionLayerSavingText = RtxOptions::Option::saveToLayerConf() || displayName == "rtx.conf"?
2170-
// "Save all settings from " + layerType + " layer to " + displayName :
2171-
// "Save all settings from " + layerType + " layer to rtx.conf";
2172-
// if (IMGUI_ADD_TOOLTIP(ImGui::Button(optionLayerSavingText.c_str()), "Save layer to rtx.conf")) {
2173-
// RtxOptions::serializeOptionLayer(optionLayer, RtxOptions::Option::saveToLayerConf());
2174-
// }
2175-
2176-
if (ImGui::CollapsingHeader(("Contents of " + displayName).c_str(), collapsingHeaderClosedFlags)) {
2168+
2169+
if (headerOpen) {
21772170
ImGui::Indent();
2171+
21782172
const std::string priorityText = "Priority: " + std::to_string(optionLayer.getPriority());
21792173
ImGui::Text(priorityText.c_str());
21802174
if (ImGui::IsItemHovered()) {
@@ -2184,9 +2178,104 @@ namespace dxvk {
21842178
"If a layer's blendWeight is not 1 and the option is a float or Vector type,\n"
21852179
"then the values will be calculated as LERP(previousValue, layerValue, blendWeight).");
21862180
}
2187-
for (const auto& option : optionLayer.getConfig().getOptions()) {
2188-
const std::string optionText = option.first + "=" + option.second;
2189-
ImGui::TextWrapped(optionText.c_str());
2181+
2182+
const std::string optionLayerEnabledText = "Enabled###Enabled_" + displayName;
2183+
const std::string optionLayerStrengthText = " Strength###Strength_" + displayName;
2184+
const std::string optionLayerThresholdText = " Threshold###Threshold_" + displayName;
2185+
const std::string optionLayerContentsText = "Contents###Contents_" + displayName;
2186+
2187+
// Use pending values for UI display and send requests on change
2188+
if (IMGUI_ADD_TOOLTIP(ImGui::Checkbox(optionLayerEnabledText.c_str(), &pendingEnabled), "Check to enable the option layer. Uncheck to disable it.")) {
2189+
optionLayer.requestEnabled(pendingEnabled);
2190+
}
2191+
2192+
if (IMGUI_ADD_TOOLTIP(ImGui::SliderFloat(optionLayerStrengthText.c_str(), &pendingStrength, 0.0f, 1.0f),
2193+
"Adjusts the blending strength of this option layer (0 = off, 1 = full effect).")) {
2194+
optionLayer.requestBlendStrength(pendingStrength);
2195+
}
2196+
2197+
if (IMGUI_ADD_TOOLTIP(ImGui::SliderFloat(optionLayerThresholdText.c_str(), &pendingThreshold, 0.0f, 1.0f),
2198+
"Sets the blending strength threshold for this option layer. Only applicable to non-float variables.\n"
2199+
"The option is applied only when the blend strength exceeds this threshold.")) {
2200+
optionLayer.requestBlendThreshold(pendingThreshold);
2201+
}
2202+
2203+
if (ImGui::CollapsingHeader(optionLayerContentsText.c_str(), collapsingHeaderClosedFlags)) {
2204+
ImGui::Indent();
2205+
for (const auto& option : optionLayer.getConfig().getOptions()) {
2206+
// Apply filter if one is set
2207+
if (!filterLower.empty()) {
2208+
std::string optionLower = option.first;
2209+
std::transform(optionLower.begin(), optionLower.end(), optionLower.begin(), ::tolower);
2210+
if (optionLower.find(filterLower) == std::string::npos) {
2211+
continue;
2212+
}
2213+
}
2214+
const std::string optionText = option.first + "=" + option.second;
2215+
ImGui::TextWrapped(optionText.c_str());
2216+
}
2217+
ImGui::Unindent();
2218+
}
2219+
ImGui::Unindent();
2220+
}
2221+
} else {
2222+
// Runtime and default option layers don't have configs in the same way as the other layers, so print them differently
2223+
// The blend and enabled settings for these layers should not be modified through the GUI.
2224+
bool headerOpen = false;
2225+
if (layerKey.priority == RtxOptionLayer::s_runtimeOptionLayerPriority) {
2226+
displayName = "runtime layer";
2227+
const std::string optionLayerText = std::to_string(optionLayerCounter++) + ". user.conf and runtime changes";
2228+
headerOpen = IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader(optionLayerText.c_str(), collapsingHeaderClosedFlags),
2229+
"This layer is initialized from user.conf, but includes any options that are changed at runtime (either through the GUI, the API, or when applying presets).");
2230+
} else {
2231+
displayName = "default";
2232+
const std::string optionLayerText = std::to_string(optionLayerCounter++) + ". default";
2233+
headerOpen = IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader(optionLayerText.c_str(), collapsingHeaderClosedFlags),
2234+
"This is the default setting for each option, as can be seen in RtxOptions.md.");
2235+
}
2236+
if (headerOpen) {
2237+
ImGui::Indent();
2238+
if (layerKey.priority == RtxOptionLayer::s_runtimeOptionLayerPriority) {
2239+
ImGui::Text("Priority: MAX");
2240+
if (ImGui::IsItemHovered()) {
2241+
ImGui::SetTooltip("Highest possible priority - any changes made in this layer will apply fully regardless of options in other layers.\n"
2242+
"The actual priority value is 4,294,967,295, or uint32's max value.");
2243+
}
2244+
} else {
2245+
ImGui::Text("Priority: 0");
2246+
if (ImGui::IsItemHovered()) {
2247+
ImGui::SetTooltip("Lowest possible priority - every other layer will be applied on top of this layer.");
2248+
}
2249+
}
2250+
const std::string optionLayerContentsText = "Contents###Contents_" + displayName;
2251+
2252+
if (ImGui::CollapsingHeader(optionLayerContentsText.c_str(), collapsingHeaderClosedFlags)) {
2253+
ImGui::Indent();
2254+
2255+
// For runtime layer, iterate through all options and find those with runtime layer values
2256+
// (the runtime layer's config is empty since values are stored in each option's optionLayerValueQueue)
2257+
for (const auto& [optionHash, optionPtr] : RtxOptionImpl::getGlobalRtxOptionMap()) {
2258+
const RtxOptionImpl& rtxOption = *optionPtr;
2259+
// Check if this option has a runtime layer value (first entry has runtime priority)
2260+
if (!rtxOption.optionLayerValueQueue.empty() &&
2261+
rtxOption.optionLayerValueQueue.begin()->first.priority == optionLayer.getPriority()) {
2262+
const std::string fullName = rtxOption.getFullName();
2263+
2264+
// Apply filter if one is set
2265+
if (!filterLower.empty()) {
2266+
std::string optionLower = fullName;
2267+
std::transform(optionLower.begin(), optionLower.end(), optionLower.begin(), ::tolower);
2268+
if (optionLower.find(filterLower) == std::string::npos) {
2269+
continue;
2270+
}
2271+
}
2272+
2273+
const std::string optionText = fullName + "=" +
2274+
rtxOption.genericValueToString(rtxOption.optionLayerValueQueue.begin()->second.value);
2275+
ImGui::TextWrapped(optionText.c_str());
2276+
}
2277+
}
2278+
ImGui::Unindent();
21902279
}
21912280
ImGui::Unindent();
21922281
}

0 commit comments

Comments
 (0)