Skip to content

Commit 0b28657

Browse files
authored
Qt, FullscreenUI, PostProcessing: Add shader enable/disable toggle. (#3621)
* Qt, FullscreenUI, PostProcessing: Add shader enable/disable toggle. Allows enabling/disabling individual shaders in a post processing chain. Unlike removing, disabling preserves custom parameter values. * Use `Qt::ItemIsUserCheckable` flag for shader list
1 parent 475b69b commit 0b28657

File tree

5 files changed

+94
-15
lines changed

5 files changed

+94
-15
lines changed

src/core/fullscreenui_settings.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4110,6 +4110,13 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
41104110
str.format(FSUI_FSTR("Stage {}: {}"), stage_index + 1, si.name);
41114111
MenuHeading(str);
41124112

4113+
if (DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_WAND_MAGIC_SPARKLES, "Enable Shader"),
4114+
FSUI_VSTR("If not enabled, this shader will be ignored."),
4115+
fmt::format("PostProcessing/Stage{}", stage_index + 1).c_str(), "Enabled", true))
4116+
{
4117+
reload_pending = true;
4118+
}
4119+
41134120
if (MenuButton(FSUI_ICONVSTR(ICON_PF_REMOVE, "Remove From Chain"),
41144121
FSUI_VSTR("Removes this shader from the chain.")))
41154122
{

src/duckstation-qt/postprocessingsettingswidget.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ void PostProcessingChainConfigWidget::connectUi()
9191
connect(m_ui.moveDown, &QPushButton::clicked, this, &PostProcessingChainConfigWidget::onMoveDownButtonClicked);
9292
connect(m_ui.stages, &QListWidget::itemSelectionChanged, this,
9393
&PostProcessingChainConfigWidget::onSelectedShaderChanged);
94+
connect(m_ui.stages, &QListWidget::itemChanged, this, &PostProcessingChainConfigWidget::onShaderToggled);
9495
}
9596

9697
std::optional<u32> PostProcessingChainConfigWidget::getSelectedIndex() const
@@ -124,11 +125,17 @@ void PostProcessingChainConfigWidget::updateList(const SettingsInterface& si)
124125

125126
const u32 stage_count = PostProcessing::Config::GetStageCount(si, m_section);
126127

128+
QSignalBlocker sb(m_ui.stages);
129+
127130
for (u32 i = 0; i < stage_count; i++)
128131
{
132+
const bool stage_enabled = PostProcessing::Config::IsStageEnabled(si, m_section, i);
129133
const std::string stage_name = PostProcessing::Config::GetStageShaderName(si, m_section, i);
134+
130135
QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(stage_name), m_ui.stages);
136+
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
131137
item->setData(Qt::UserRole, QVariant(i));
138+
item->setCheckState(stage_enabled ? Qt::Checked : Qt::Unchecked);
132139
}
133140

134141
m_ui.clear->setEnabled(stage_count > 0);
@@ -284,6 +291,24 @@ void PostProcessingChainConfigWidget::onSelectedShaderChanged()
284291
updateButtonsAndConfigPane(index);
285292
}
286293

294+
void PostProcessingChainConfigWidget::onShaderToggled(QListWidgetItem* item)
295+
{
296+
if (!item)
297+
return;
298+
299+
const QVariant item_data = item->data(Qt::UserRole);
300+
if (!item_data.isValid())
301+
return;
302+
303+
const u32 index = item_data.toUInt();
304+
305+
auto lock = Host::GetSettingsLock();
306+
SettingsInterface& si = getSettingsInterfaceToUpdate();
307+
PostProcessing::Config::SetStageEnabled(si, m_section, index, item->checkState() == Qt::Checked);
308+
lock.unlock();
309+
commitSettingsUpdate();
310+
}
311+
287312
PostProcessingShaderConfigWidget::PostProcessingShaderConfigWidget(QWidget* parent,
288313
PostProcessingChainConfigWidget* widget,
289314
const char* section, u32 stage_index,

src/duckstation-qt/postprocessingsettingswidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class PostProcessingChainConfigWidget : public QWidget
5353
void onReloadButtonClicked();
5454
void onOpenDirectoryButtonClicked();
5555
void onSelectedShaderChanged();
56+
void onShaderToggled(QListWidgetItem* item);
5657
void triggerSettingsReload();
5758

5859
SettingsWindow* m_dialog;

src/util/postprocessing.cpp

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,29 @@ bool PostProcessing::Config::IsEnabled(const SettingsInterface& si, const char*
276276
return si.GetBoolValue(section, "Enabled", false);
277277
}
278278

279+
bool PostProcessing::Config::IsStageEnabled(const SettingsInterface& si, const char* section, u32 index)
280+
{
281+
return si.GetBoolValue(GetStageConfigSection(section, index), "Enabled", true);
282+
}
283+
279284
u32 PostProcessing::Config::GetStageCount(const SettingsInterface& si, const char* section)
280285
{
281286
return si.GetUIntValue(section, "StageCount", 0u);
282287
}
283288

289+
u32 PostProcessing::Config::GetEnabledStageCount(const SettingsInterface& si, const char* section)
290+
{
291+
const int stage_count = GetStageCount(si, section);
292+
int enabled_count = 0;
293+
for (int i = 0; i < stage_count; i++)
294+
{
295+
if (IsStageEnabled(si, section, i))
296+
enabled_count++;
297+
}
298+
299+
return enabled_count;
300+
}
301+
284302
std::string PostProcessing::Config::GetStageShaderName(const SettingsInterface& si, const char* section, u32 index)
285303
{
286304
return si.GetStringValue(GetStageConfigSection(section, index), "ShaderName");
@@ -317,6 +335,11 @@ std::vector<PostProcessing::ShaderOption> PostProcessing::Config::GetShaderOptio
317335
return ret;
318336
}
319337

338+
void PostProcessing::Config::SetStageEnabled(SettingsInterface& si, const char* section, u32 index, bool enabled)
339+
{
340+
si.SetBoolValue(GetStageConfigSection(section, index), "Enabled", enabled);
341+
}
342+
320343
bool PostProcessing::Config::AddStage(SettingsInterface& si, const char* section, const std::string& shader_name,
321344
Error* error)
322345
{
@@ -329,6 +352,7 @@ bool PostProcessing::Config::AddStage(SettingsInterface& si, const char* section
329352

330353
const TinyString stage_section = GetStageConfigSection(section, index);
331354
si.SetStringValue(stage_section, "ShaderName", shader->GetName().c_str());
355+
SetStageEnabled(si, section, index, true);
332356

333357
#if 0
334358
// Leave options unset for now.
@@ -448,16 +472,23 @@ void PostProcessing::Chain::LoadStages(std::unique_lock<std::mutex>& settings_lo
448472
m_wants_unscaled_input = false;
449473

450474
const u32 stage_count = Config::GetStageCount(si, m_section);
451-
if (stage_count == 0)
475+
const u32 enabled_stage_count = Config::GetEnabledStageCount(si, m_section);
476+
if (stage_count == 0 || enabled_stage_count == 0)
452477
return;
453478

454479
Error error;
455480
FullscreenUI::LoadingScreenProgressCallback progress;
456481
progress.SetTitle("Loading Post-Processing Shaders...");
457-
progress.SetProgressRange(stage_count);
482+
progress.SetProgressRange(enabled_stage_count);
458483

459484
for (u32 i = 0; i < stage_count; i++)
460485
{
486+
bool stage_enabled = Config::IsStageEnabled(si, m_section, i);
487+
if (!stage_enabled)
488+
{
489+
continue;
490+
}
491+
461492
std::string stage_name = Config::GetStageShaderName(si, m_section, i);
462493
if (stage_name.empty())
463494
{
@@ -483,8 +514,8 @@ void PostProcessing::Chain::LoadStages(std::unique_lock<std::mutex>& settings_lo
483514
m_stages.push_back(std::move(shader));
484515
}
485516

486-
if (stage_count > 0)
487-
DEV_LOG("Loaded {} post-processing stages.", stage_count);
517+
if (enabled_stage_count > 0)
518+
DEV_LOG("Loaded {} post-processing stages.", enabled_stage_count);
488519

489520
// precompile shaders
490521
if (preload_swap_chain_size && g_gpu_device && g_gpu_device->HasMainSwapChain())
@@ -515,7 +546,8 @@ void PostProcessing::Chain::UpdateSettings(std::unique_lock<std::mutex>& setting
515546
m_enabled = si.GetBoolValue(m_section, "Enabled", false);
516547

517548
const u32 stage_count = Config::GetStageCount(si, m_section);
518-
if (stage_count == 0)
549+
const u32 enabled_stage_count = Config::GetEnabledStageCount(si, m_section);
550+
if (stage_count == 0 || enabled_stage_count == 0)
519551
{
520552
m_stages.clear();
521553
return;
@@ -527,12 +559,12 @@ void PostProcessing::Chain::UpdateSettings(std::unique_lock<std::mutex>& setting
527559

528560
FullscreenUI::LoadingScreenProgressCallback progress;
529561
progress.SetTitle("Loading Post-Processing Shaders...");
530-
progress.SetProgressRange(stage_count);
562+
progress.SetProgressRange(enabled_stage_count);
531563

532564
const GPUTexture::Format prev_format = m_target_format;
533565
m_wants_depth_buffer = false;
534566

535-
for (u32 i = 0; i < stage_count; i++)
567+
for (u32 i = 0, j = 0; i < stage_count; i++)
536568
{
537569
std::string stage_name = Config::GetStageShaderName(si, m_section, i);
538570
if (stage_name.empty())
@@ -542,10 +574,18 @@ void PostProcessing::Chain::UpdateSettings(std::unique_lock<std::mutex>& setting
542574
return;
543575
}
544576

545-
if (!m_stages[i] || stage_name != m_stages[i]->GetName())
577+
bool stage_enabled = Config::IsStageEnabled(si, m_section, i);
578+
if (!stage_enabled)
546579
{
547-
if (i < m_stages.size())
548-
m_stages[i].reset();
580+
if (m_stages[j] && stage_name == m_stages[j]->GetName())
581+
m_stages[j].reset();
582+
continue;
583+
}
584+
585+
if (!m_stages[j] || stage_name != m_stages[j]->GetName())
586+
{
587+
if (j < m_stages.size())
588+
m_stages[j].reset();
549589

550590
// Force recompile.
551591
m_target_format = GPUTexture::Format::Unknown;
@@ -559,27 +599,30 @@ void PostProcessing::Chain::UpdateSettings(std::unique_lock<std::mutex>& setting
559599
return;
560600
}
561601

562-
if (i < m_stages.size())
563-
m_stages[i] = std::move(shader);
602+
if (j < m_stages.size())
603+
m_stages[j] = std::move(shader);
564604
else
565605
m_stages.push_back(std::move(shader));
566606

567607
settings_lock.lock();
568608
}
569609

570-
m_stages[i]->LoadOptions(si, GetStageConfigSection(m_section, i));
610+
m_stages[j]->LoadOptions(si, GetStageConfigSection(m_section, i));
611+
j++;
571612
}
572613

614+
m_stages.resize(enabled_stage_count);
615+
573616
if (prev_format != GPUTexture::Format::Unknown)
574617
{
575618
CheckTargets(m_target_width, m_target_height, prev_format, m_source_width, m_source_height, m_viewport_width,
576619
m_viewport_height, &progress);
577620
}
578621

579-
if (stage_count > 0)
622+
if (enabled_stage_count > 0)
580623
{
581624
s_start_time = Timer::GetCurrentValue();
582-
DEV_LOG("Loaded {} post-processing stages.", stage_count);
625+
DEV_LOG("Loaded {} post-processing stages.", enabled_stage_count);
583626
}
584627

585628
// must be down here, because we need to compile first, triggered by CheckTargets()

src/util/postprocessing.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,14 @@ inline constexpr const char* DISPLAY_CHAIN_SECTION = "PostProcessing";
105105
inline constexpr const char* INTERNAL_CHAIN_SECTION = "InternalPostProcessing";
106106

107107
bool IsEnabled(const SettingsInterface& si, const char* section);
108+
bool IsStageEnabled(const SettingsInterface& si, const char* section, u32 index);
108109
u32 GetStageCount(const SettingsInterface& si, const char* section);
110+
u32 GetEnabledStageCount(const SettingsInterface& si, const char* section);
109111
std::string GetStageShaderName(const SettingsInterface& si, const char* section, u32 index);
110112
std::vector<ShaderOption> GetStageOptions(const SettingsInterface& si, const char* section, u32 index);
111113
std::vector<ShaderOption> GetShaderOptions(const std::string& shader_name, Error* error);
112114

115+
void SetStageEnabled(SettingsInterface& si, const char* section, u32 index, bool enabled);
113116
bool AddStage(SettingsInterface& si, const char* section, const std::string& shader_name, Error* error);
114117
void RemoveStage(SettingsInterface& si, const char* section, u32 index);
115118
void MoveStageUp(SettingsInterface& si, const char* section, u32 index);

0 commit comments

Comments
 (0)