fix/feat: Introduce CAS & Add Dynamic Slider Viewing for Toggled WAF's, and remove Android ASTC visibility on PC

This commit is contained in:
collecting
2026-02-05 02:57:28 -05:00
parent 9443737034
commit 37dd2fddc4
18 changed files with 388 additions and 324 deletions

View File

@@ -31,6 +31,12 @@
#include <qgridlayout.h> #include <qgridlayout.h>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include "citron/configuration/configuration_shared.h"
#include "citron/configuration/configure_graphics.h"
#include "citron/configuration/shared_widget.h"
#include "citron/qt_common.h"
#include "citron/uisettings.h"
#include "citron/vk_device_info.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/dynamic_library.h" #include "common/dynamic_library.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@@ -38,12 +44,6 @@
#include "common/settings_enums.h" #include "common/settings_enums.h"
#include "core/core.h" #include "core/core.h"
#include "ui_configure_graphics.h" #include "ui_configure_graphics.h"
#include "citron/configuration/configuration_shared.h"
#include "citron/configuration/configure_graphics.h"
#include "citron/configuration/shared_widget.h"
#include "citron/qt_common.h"
#include "citron/uisettings.h"
#include "citron/vk_device_info.h"
static const std::vector<VkPresentModeKHR> default_present_modes{VK_PRESENT_MODE_IMMEDIATE_KHR, static const std::vector<VkPresentModeKHR> default_present_modes{VK_PRESENT_MODE_IMMEDIATE_KHR,
VK_PRESENT_MODE_FIFO_KHR}; VK_PRESENT_MODE_FIFO_KHR};
@@ -276,6 +276,14 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) {
return builder.BuildWidget( return builder.BuildWidget(
setting, apply_funcs, ConfigurationShared::RequestType::ReverseSlider, true, setting, apply_funcs, ConfigurationShared::RequestType::ReverseSlider, true,
0.5f, nullptr, tr("%", "FSR sharpening percentage (e.g. 50%)")); 0.5f, nullptr, tr("%", "FSR sharpening percentage (e.g. 50%)"));
} else if (setting->Id() == Settings::values.cas_sharpening_slider.Id()) {
// CAS needs a 0.5 multiplier to show 0-100% (actually 0.0-0.5 internally if we
// follow FSR) Wait, CAS slider is 0-100 in settings.h. FSR is 0-200 internally?
// Actually FSR slider is 0-200 in settings.h.
// Let's check settings.h for CAS slider again.
return builder.BuildWidget(setting, apply_funcs,
ConfigurationShared::RequestType::Slider, true, 1.0f,
nullptr, tr("%"));
} else { } else {
return builder.BuildWidget(setting, apply_funcs); return builder.BuildWidget(setting, apply_funcs);
} }
@@ -289,9 +297,20 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) {
continue; continue;
} }
// Store reference to the FSR sharpness widget for later use
if (setting->Id() == Settings::values.fsr_sharpening_slider.Id()) { if (setting->Id() == Settings::values.fsr_sharpening_slider.Id()) {
fsr_sharpness_widget = widget; fsr_sharpness_widget = widget;
} else if (setting->Id() == Settings::values.cas_sharpening_slider.Id()) {
cas_sharpness_widget = widget;
} else if (setting->Id() == Settings::values.lanczos_quality.Id()) {
lq_widget = widget;
} else if (setting->Id() == Settings::values.crt_scanline_strength.Id() ||
setting->Id() == Settings::values.crt_curvature.Id() ||
setting->Id() == Settings::values.crt_gamma.Id() ||
setting->Id() == Settings::values.crt_bloom.Id() ||
setting->Id() == Settings::values.crt_mask_type.Id() ||
setting->Id() == Settings::values.crt_brightness.Id() ||
setting->Id() == Settings::values.crt_alpha.Id()) {
crt_widgets.push_back(widget);
} }
if (setting->Id() == Settings::values.renderer_backend.Id()) { if (setting->Id() == Settings::values.renderer_backend.Id()) {
@@ -372,39 +391,61 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) {
api_grid_layout->addWidget(widget); api_grid_layout->addWidget(widget);
} }
// Set up FSR sharpness slider conditional enabling // Set up Scaling Filter conditional visibility for sliders
if (fsr_sharpness_widget) { QComboBox* scaling_filter_combobox = nullptr;
// Create a function to update the enabled state based on scaling filter for (const auto& [id, widget] : hold_graphics) {
auto update_fsr_sharpness_enabled = [this]() { if (id == Settings::values.scaling_filter.Id()) {
if (fsr_sharpness_widget) { scaling_filter_combobox = static_cast<ConfigurationShared::Widget*>(widget)->combobox;
const auto scaling_filter = Settings::values.scaling_filter.GetValue(); break;
const bool fsr2_selected = (scaling_filter == Settings::ScalingFilter::Fsr2); }
fsr_sharpness_widget->setEnabled(!fsr2_selected); }
// Grey out the widget when disabled if (scaling_filter_combobox) {
// Create a function to update the enabled/visible state based on current UI selection
auto update_visibility = [this, scaling_filter_combobox, &builder]() {
const auto& translations = builder.ComboboxTranslations().at(
Settings::EnumMetadata<Settings::ScalingFilter>::Index());
const auto scaling_filter = static_cast<Settings::ScalingFilter>(
translations.at(scaling_filter_combobox->currentIndex()).first);
if (fsr_sharpness_widget) {
const bool fsr_selected = (scaling_filter == Settings::ScalingFilter::Fsr);
const bool fsr2_selected = (scaling_filter == Settings::ScalingFilter::Fsr2);
// Visible only if FSR 1 or FSR 2 is selected
fsr_sharpness_widget->setVisible(fsr_selected || fsr2_selected);
// FSR 2.0 doesn't use the FSR 1.0 sharpness slider but we allow it to be visible
// but disabled to show it's an FSR-related setting.
fsr_sharpness_widget->setEnabled(!fsr2_selected);
if (fsr2_selected) { if (fsr2_selected) {
fsr_sharpness_widget->setStyleSheet(QStringLiteral("QWidget { color: gray; }")); fsr_sharpness_widget->setStyleSheet(QStringLiteral("QWidget { color: gray; }"));
} else { } else {
fsr_sharpness_widget->setStyleSheet(QStringLiteral("")); fsr_sharpness_widget->setStyleSheet(QStringLiteral(""));
} }
} }
if (cas_sharpness_widget) {
cas_sharpness_widget->setVisible(scaling_filter == Settings::ScalingFilter::Cas);
}
if (lq_widget) {
lq_widget->setVisible(scaling_filter == Settings::ScalingFilter::Lanczos);
}
const bool crt_selected = (scaling_filter == Settings::ScalingFilter::CRTEasyMode ||
scaling_filter == Settings::ScalingFilter::CRTRoyale);
for (auto* crt_widget : crt_widgets) {
crt_widget->setVisible(crt_selected);
}
}; };
// Initial state // Initial state
update_fsr_sharpness_enabled(); update_visibility();
// Connect to scaling filter changes // Connect to scaling filter changes (real-time update)
if (!Settings::IsConfiguringGlobal()) { QObject::connect(scaling_filter_combobox, QOverload<int>::of(&QComboBox::activated),
// Find the scaling filter widget and connect to its changes [update_visibility]() { update_visibility(); });
for (const auto& [id, widget] : hold_graphics) {
if (id == Settings::values.scaling_filter.Id()) {
auto* config_widget = static_cast<ConfigurationShared::Widget*>(widget);
QObject::connect(config_widget->combobox, QOverload<int>::of(&QComboBox::activated),
[update_fsr_sharpness_enabled]() { update_fsr_sharpness_enabled(); });
break;
}
}
}
} }
// Background color is too specific to build into the new system, so we manage it here // Background color is too specific to build into the new system, so we manage it here
@@ -615,8 +656,10 @@ void ConfigureGraphics::SetTemplateStyleSheet(const QString& sheet) {
// Replace all placeholders with the actual color values in #RRGGBB format // Replace all placeholders with the actual color values in #RRGGBB format
// Use QStringLiteral() to satisfy Qt 6's explicit string constructor requirements // Use QStringLiteral() to satisfy Qt 6's explicit string constructor requirements
final_style.replace(QStringLiteral("%%ACCENT_COLOR%%"), accent_color.name(QColor::HexRgb)); final_style.replace(QStringLiteral("%%ACCENT_COLOR%%"), accent_color.name(QColor::HexRgb));
final_style.replace(QStringLiteral("%%ACCENT_COLOR_HOVER%%"), accent_color_hover.name(QColor::HexRgb)); final_style.replace(QStringLiteral("%%ACCENT_COLOR_HOVER%%"),
final_style.replace(QStringLiteral("%%ACCENT_COLOR_PRESSED%%"), accent_color_pressed.name(QColor::HexRgb)); accent_color_hover.name(QColor::HexRgb));
final_style.replace(QStringLiteral("%%ACCENT_COLOR_PRESSED%%"),
accent_color_pressed.name(QColor::HexRgb));
// Apply the processed stylesheet to this widget and all its children (like checkboxes) // Apply the processed stylesheet to this widget and all its children (like checkboxes)
this->setStyleSheet(final_style); this->setStyleSheet(final_style);

View File

@@ -14,11 +14,11 @@
#include <QWidget> #include <QWidget>
#include <qobjectdefs.h> #include <qobjectdefs.h>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include "citron/configuration/configuration_shared.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/settings_enums.h" #include "common/settings_enums.h"
#include "configuration/shared_translation.h" #include "configuration/shared_translation.h"
#include "vk_device_info.h" #include "vk_device_info.h"
#include "citron/configuration/configuration_shared.h"
class QPushButton; class QPushButton;
class QEvent; class QEvent;
@@ -47,7 +47,8 @@ class ConfigureGraphics : public ConfigurationShared::Tab {
Q_OBJECT Q_OBJECT
// This property allows the main UI file to pass its stylesheet to this widget // This property allows the main UI file to pass its stylesheet to this widget
Q_PROPERTY(QString templateStyleSheet READ GetTemplateStyleSheet WRITE SetTemplateStyleSheet NOTIFY TemplateStyleSheetChanged) Q_PROPERTY(QString templateStyleSheet READ GetTemplateStyleSheet WRITE SetTemplateStyleSheet
NOTIFY TemplateStyleSheetChanged)
public: public:
explicit ConfigureGraphics( explicit ConfigureGraphics(
@@ -125,6 +126,9 @@ private:
QComboBox* aspect_ratio_combobox; QComboBox* aspect_ratio_combobox;
QComboBox* resolution_combobox; QComboBox* resolution_combobox;
QWidget* fsr_sharpness_widget; QWidget* fsr_sharpness_widget;
QWidget* cas_sharpness_widget;
QWidget* lq_widget;
std::vector<QWidget*> crt_widgets;
// This variable will hold the raw stylesheet string // This variable will hold the raw stylesheet string
QString m_template_style_sheet; QString m_template_style_sheet;

View File

@@ -2,16 +2,17 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "citron/configuration/configure_graphics_advanced.h"
#include <vector> #include <vector>
#include <QLabel> #include <QLabel>
#include <qnamespace.h> #include <qnamespace.h>
#include "citron/configuration/configuration_shared.h"
#include "citron/configuration/configure_graphics_advanced.h"
#include "citron/configuration/shared_translation.h"
#include "citron/configuration/shared_widget.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h" #include "core/core.h"
#include "ui_configure_graphics_advanced.h" #include "ui_configure_graphics_advanced.h"
#include "citron/configuration/configuration_shared.h"
#include "citron/configuration/shared_translation.h"
#include "citron/configuration/shared_widget.h"
ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced( ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(
const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_, const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,
@@ -37,6 +38,11 @@ void ConfigureGraphicsAdvanced::Setup(const ConfigurationShared::Builder& builde
for (auto setting : for (auto setting :
Settings::values.linkage.by_category[Settings::Category::RendererAdvanced]) { Settings::values.linkage.by_category[Settings::Category::RendererAdvanced]) {
#ifndef ANDROID
if (setting->Id() == Settings::values.android_astc_mode.Id()) {
continue;
}
#endif
ConfigurationShared::Widget* widget = builder.BuildWidget(setting, apply_funcs); ConfigurationShared::Widget* widget = builder.BuildWidget(setting, apply_funcs);
if (widget == nullptr) { if (widget == nullptr) {

View File

@@ -10,11 +10,11 @@
#include <utility> #include <utility>
#include <QCoreApplication> #include <QCoreApplication>
#include <QWidget> #include <QWidget>
#include "citron/uisettings.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/settings_enums.h" #include "common/settings_enums.h"
#include "common/settings_setting.h" #include "common/settings_setting.h"
#include "common/time_zone.h" #include "common/time_zone.h"
#include "citron/uisettings.h"
namespace ConfigurationShared { namespace ConfigurationShared {
@@ -130,30 +130,42 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
"much more VRAM and bandwidth.\n" "much more VRAM and bandwidth.\n"
"Options lower than 1X can cause rendering issues.")); "Options lower than 1X can cause rendering issues."));
INSERT(Settings, scaling_filter, tr("Window Adapting Filter:"), QStringLiteral()); INSERT(Settings, scaling_filter, tr("Window Adapting Filter:"), QStringLiteral());
INSERT(Settings, fsr_sharpening_slider, tr("FSR Sharpness:"), INSERT(Settings, fsr_sharpening_slider, tr("FSR Sharpness"),
tr("Determines how sharpened the image will look while using FSR's dynamic contrast.")); tr("Determines how sharpened the image will look while using FSR's dynamic contrast."));
INSERT(Settings, lanczos_quality, tr("Lanczos Quality:"), tr("The quality of the Lanczos filter. Higher is sharper but more expensive.")); INSERT(Settings, cas_sharpening_slider, tr("CAS Sharpness"),
tr("Determines the level of sharpening applied by the Contrast Adaptive Sharpening "
"(CAS) filter."));
INSERT(Settings, lanczos_quality, tr("Lanczos Quality:"),
tr("The quality of the Lanczos filter. Higher is sharper but more expensive."));
INSERT(Settings, fsr2_quality_mode, tr("FSR 2.0 Quality Mode:"), INSERT(Settings, fsr2_quality_mode, tr("FSR 2.0 Quality Mode:"),
tr("Selects the quality mode for FSR 2.0 upscaling. Quality provides better image quality, Performance provides better performance.")); tr("Selects the quality mode for FSR 2.0 upscaling. Quality provides better image "
"quality, Performance provides better performance."));
INSERT(Settings, crt_scanline_strength, tr("CRT Scanline Strength:"), INSERT(Settings, crt_scanline_strength, tr("CRT Scanline Strength:"),
tr("Controls the intensity of scanlines. Higher values create more pronounced horizontal lines.")); tr("Controls the intensity of scanlines. Higher values create more pronounced "
"horizontal lines."));
INSERT(Settings, crt_curvature, tr("CRT Curvature:"), INSERT(Settings, crt_curvature, tr("CRT Curvature:"),
tr("Applies barrel distortion to simulate the curved screen of a CRT monitor.")); tr("Applies barrel distortion to simulate the curved screen of a CRT monitor."));
INSERT(Settings, crt_gamma, tr("CRT Gamma:"), INSERT(Settings, crt_gamma, tr("CRT Gamma:"),
tr("Adjusts the gamma correction curve. Higher values brighten the image, lower values darken it.")); tr("Adjusts the gamma correction curve. Higher values brighten the image, lower values "
"darken it."));
INSERT(Settings, crt_bloom, tr("CRT Bloom:"), INSERT(Settings, crt_bloom, tr("CRT Bloom:"),
tr("Controls the glow effect around bright areas, simulating phosphor persistence.")); tr("Controls the glow effect around bright areas, simulating phosphor persistence."));
INSERT(Settings, crt_mask_type, tr("CRT Mask Type:"), INSERT(Settings, crt_mask_type, tr("CRT Mask Type:"),
tr("Selects the phosphor mask pattern: None, Aperture Grille (vertical stripes), or Shadow Mask (triangular pattern).")); tr("Selects the phosphor mask pattern: None, Aperture Grille (vertical stripes), or "
"Shadow Mask (triangular pattern)."));
INSERT(Settings, crt_brightness, tr("CRT Brightness:"), INSERT(Settings, crt_brightness, tr("CRT Brightness:"),
tr("Adjusts overall brightness of the CRT effect. Use to compensate for darkening from other effects.")); tr("Adjusts overall brightness of the CRT effect. Use to compensate for darkening from "
"other effects."));
INSERT(Settings, crt_alpha, tr("CRT Alpha:"), INSERT(Settings, crt_alpha, tr("CRT Alpha:"),
tr("Controls transparency of the CRT effect. Lower values make the effect more transparent.")); tr("Controls transparency of the CRT effect. Lower values make the effect more "
"transparent."));
INSERT(Settings, frame_skipping, tr("Frame Skipping:"), INSERT(Settings, frame_skipping, tr("Frame Skipping:"),
tr("Skips frames to maintain performance when the system cannot keep up with the target frame rate.")); tr("Skips frames to maintain performance when the system cannot keep up with the target "
"frame rate."));
INSERT(Settings, frame_skipping_mode, tr("Frame Skipping Mode:"), INSERT(Settings, frame_skipping_mode, tr("Frame Skipping Mode:"),
tr("Adaptive mode skips frames based on performance, while Fixed mode skips a specific number of frames.")); tr("Adaptive mode skips frames based on performance, while Fixed mode skips a specific "
"number of frames."));
INSERT(Settings, anti_aliasing, tr("Anti-Aliasing Method:"), INSERT(Settings, anti_aliasing, tr("Anti-Aliasing Method:"),
tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA has a " tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA has a "
"lower performance impact and can produce a better and more stable picture under " "lower performance impact and can produce a better and more stable picture under "
@@ -202,7 +214,8 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
INSERT(Settings, vram_limit_mb, tr("VRAM Limit (MB):"), INSERT(Settings, vram_limit_mb, tr("VRAM Limit (MB):"),
tr("Sets the maximum VRAM usage limit in megabytes. Set to 0 for auto-detection " tr("Sets the maximum VRAM usage limit in megabytes. Set to 0 for auto-detection "
"(80% of available VRAM). Recommended: 6144 for 8GB GPUs, 4096 for 6GB GPUs.")); "(80% of available VRAM). Recommended: 6144 for 8GB GPUs, 4096 for 6GB GPUs."));
INSERT(Settings, gc_aggressiveness, tr("GC Aggressiveness:"), INSERT(
Settings, gc_aggressiveness, tr("GC Aggressiveness:"),
tr("Controls how aggressively the emulator evicts unused textures and buffers from VRAM.\n" tr("Controls how aggressively the emulator evicts unused textures and buffers from VRAM.\n"
"Off: Disable automatic cleanup (not recommended, may cause crashes).\n" "Off: Disable automatic cleanup (not recommended, may cause crashes).\n"
"Light: Gentle cleanup, keeps more textures cached (recommended).")); "Light: Gentle cleanup, keeps more textures cached (recommended)."));
@@ -271,13 +284,15 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
"unlocked.")); "unlocked."));
INSERT(Settings, barrier_feedback_loops, tr("Barrier feedback loops"), INSERT(Settings, barrier_feedback_loops, tr("Barrier feedback loops"),
tr("Improves rendering of transparency effects in specific games.")); tr("Improves rendering of transparency effects in specific games."));
INSERT(Settings, extended_dynamic_state, tr("Extended Dynamic State:"), INSERT(
Settings, extended_dynamic_state, tr("Extended Dynamic State:"),
tr("Selects the level of Vulkan Extended Dynamic State support.\n" tr("Selects the level of Vulkan Extended Dynamic State support.\n"
"EDS3: Enables all Extended Dynamic State features (recommended).\n" "EDS3: Enables all Extended Dynamic State features (recommended).\n"
"EDS2: Enables EDS1 and EDS2 features only.\n" "EDS2: Enables EDS1 and EDS2 features only.\n"
"EDS1: Enables basic Extended Dynamic State features only.\n" "EDS1: Enables basic Extended Dynamic State features only.\n"
"Disabled: Disables all Extended Dynamic State features (may reduce compatibility).")); "Disabled: Disables all Extended Dynamic State features (may reduce compatibility)."));
INSERT(Settings, use_conditional_rendering, tr("Use conditional rendering"), INSERT(
Settings, use_conditional_rendering, tr("Use conditional rendering"),
tr("Enables conditional rendering based on query results.\n" tr("Enables conditional rendering based on query results.\n"
"Disabling this can fix flickering objects in some games but may impact performance.\n" "Disabling this can fix flickering objects in some games but may impact performance.\n"
"Try disabling if you see objects appearing and disappearing rapidly.")); "Try disabling if you see objects appearing and disappearing rapidly."));
@@ -477,6 +492,7 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) {
PAIR(ScalingFilter, Fsr2, tr("AMD FidelityFX™ Super Resolution 2.0")), PAIR(ScalingFilter, Fsr2, tr("AMD FidelityFX™ Super Resolution 2.0")),
PAIR(ScalingFilter, CRTEasyMode, tr("CRT EasyMode")), PAIR(ScalingFilter, CRTEasyMode, tr("CRT EasyMode")),
PAIR(ScalingFilter, CRTRoyale, tr("CRT Royale")), PAIR(ScalingFilter, CRTRoyale, tr("CRT Royale")),
PAIR(ScalingFilter, Cas, tr("CAS (Contrast Adaptive Sharpening)")),
}}); }});
translations->insert({Settings::EnumMetadata<Settings::AntiAliasing>::Index(), translations->insert({Settings::EnumMetadata<Settings::AntiAliasing>::Index(),
{ {

View File

@@ -42,14 +42,14 @@ static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map
{Settings::ScalingFilter::Lanczos, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Lanczos"))}, {Settings::ScalingFilter::Lanczos, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Lanczos"))},
{Settings::ScalingFilter::ScaleForce, {Settings::ScalingFilter::ScaleForce,
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))}, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))},
{Settings::ScalingFilter::ScaleFx, {Settings::ScalingFilter::ScaleFx, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleFX"))},
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleFX"))},
{Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))}, {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
{Settings::ScalingFilter::Fsr2, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR 2.0"))}, {Settings::ScalingFilter::Fsr2, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR 2.0"))},
{Settings::ScalingFilter::CRTEasyMode, {Settings::ScalingFilter::CRTEasyMode,
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "CRT EasyMode"))}, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "CRT EasyMode"))},
{Settings::ScalingFilter::CRTRoyale, {Settings::ScalingFilter::CRTRoyale,
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "CRT Royale"))}, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "CRT Royale"))},
{Settings::ScalingFilter::Cas, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "CAS"))},
}; };
static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map = { static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map = {

View File

@@ -5710,8 +5710,22 @@ void GMainWindow::UpdateAPIText() {
void GMainWindow::UpdateFilterText() { void GMainWindow::UpdateFilterText() {
const auto filter = Settings::values.scaling_filter.GetValue(); const auto filter = Settings::values.scaling_filter.GetValue();
const auto filter_text = ConfigurationShared::scaling_filter_texts_map.find(filter)->second; const auto filter_text = ConfigurationShared::scaling_filter_texts_map.find(filter)->second;
filter_status_button->setText(filter == Settings::ScalingFilter::Fsr ? tr("FSR") QString label;
: filter_text.toUpper()); switch (filter) {
case Settings::ScalingFilter::Fsr:
label = tr("FSR");
break;
case Settings::ScalingFilter::Fsr2:
label = tr("FSR2");
break;
case Settings::ScalingFilter::Cas:
label = tr("CAS");
break;
default:
label = filter_text.toUpper();
break;
}
filter_status_button->setText(label);
} }
void GMainWindow::UpdateAAText() { void GMainWindow::UpdateAAText() {
@@ -6512,7 +6526,6 @@ void GMainWindow::CheckForUpdatesAutomatically() {
void GMainWindow::RegisterAutoloaderContents() { void GMainWindow::RegisterAutoloaderContents() {
autoloader_provider->ClearAllEntries(); autoloader_provider->ClearAllEntries();
const auto& disabled_addons = Settings::values.disabled_addons;
const auto sdmc_path = Common::FS::GetCitronPath(Common::FS::CitronPath::SDMCDir); const auto sdmc_path = Common::FS::GetCitronPath(Common::FS::CitronPath::SDMCDir);
const auto autoloader_root = sdmc_path / "autoloader"; const auto autoloader_root = sdmc_path / "autoloader";
@@ -6526,17 +6539,13 @@ void GMainWindow::RegisterAutoloaderContents() {
if (!title_dir_entry.is_directory()) if (!title_dir_entry.is_directory())
continue; continue;
u64 title_id_val = 0;
try { try {
title_id_val = std::stoull(title_dir_entry.path().filename().string(), nullptr, 16); [[maybe_unused]] auto val =
std::stoull(title_dir_entry.path().filename().string(), nullptr, 16);
} catch (const std::invalid_argument&) { } catch (const std::invalid_argument&) {
continue; continue;
} }
const auto it = disabled_addons.find(title_id_val);
const auto& disabled_for_game =
(it != disabled_addons.end()) ? it->second : std::vector<std::string>{};
const auto process_content_type = [&](const std::filesystem::path& content_path) { const auto process_content_type = [&](const std::filesystem::path& content_path) {
if (!Common::FS::IsDir(content_path)) if (!Common::FS::IsDir(content_path))
return; return;
@@ -6546,7 +6555,7 @@ void GMainWindow::RegisterAutoloaderContents() {
continue; continue;
const std::string mod_name = mod_dir_entry.path().filename().string(); const std::string mod_name = mod_dir_entry.path().filename().string();
// Citron: We do NOT skip disabled content here. // We do NOT skip disabled content here.
// If we skip it here, it doesn't show up in the UI (Properties -> Add-ons), // If we skip it here, it doesn't show up in the UI (Properties -> Add-ons),
// making it impossible for the user to re-enable it. // making it impossible for the user to re-enable it.
// The PatchManager (core/file_sys/patch_manager.cpp) handles the actual enforcement // The PatchManager (core/file_sys/patch_manager.cpp) handles the actual enforcement

View File

@@ -353,72 +353,47 @@ struct Values {
Specialization::Percentage, Specialization::Percentage,
true, true,
true}; true};
SwitchableSetting<int, true> cas_sharpening_slider{linkage,
50,
0,
100,
"cas_sharpening_slider",
Category::Renderer,
Specialization::Scalar |
Specialization::Percentage,
true,
true};
// CRT Shader Settings (only active when CRT filter is selected) // CRT Shader Settings (only active when CRT filter is selected)
SwitchableSetting<float, true> crt_scanline_strength{linkage, SwitchableSetting<float, true> crt_scanline_strength{
linkage,
1.0f, // 100/100 = 1.0 (range 0-200, actual 0.0-2.0) 1.0f, // 100/100 = 1.0 (range 0-200, actual 0.0-2.0)
0.0f, 0.0f, 2.0f, "crt_scanline_strength", Category::Renderer, Specialization::Scalar,
2.0f, true, true};
"crt_scanline_strength", SwitchableSetting<float, true> crt_curvature{
Category::Renderer, linkage, 0.0f, 0.0f, 1.0f, "crt_curvature", Category::Renderer, Specialization::Scalar,
Specialization::Scalar, true, true};
true, SwitchableSetting<float, true> crt_gamma{
true}; linkage,
SwitchableSetting<float, true> crt_curvature{linkage,
0.0f,
0.0f,
1.0f,
"crt_curvature",
Category::Renderer,
Specialization::Scalar,
true,
true};
SwitchableSetting<float, true> crt_gamma{linkage,
1.0f, // 100 maps to 1.0 (range 1-300, actual 1.0-3.0) 1.0f, // 100 maps to 1.0 (range 1-300, actual 1.0-3.0)
1.0f, 1.0f, 3.0f, "crt_gamma", Category::Renderer, Specialization::Scalar, true, true};
3.0f, SwitchableSetting<float, true> crt_bloom{
"crt_gamma", linkage,
Category::Renderer,
Specialization::Scalar,
true,
true};
SwitchableSetting<float, true> crt_bloom{linkage,
0.33f, // 33/100 = 0.33 (range 0-100, actual 0.0-1.0) 0.33f, // 33/100 = 0.33 (range 0-100, actual 0.0-1.0)
0.0f, 0.0f, 1.0f, "crt_bloom", Category::Renderer, Specialization::Scalar, true, true};
1.0f, SwitchableSetting<int, true> crt_mask_type{
"crt_bloom", linkage,
Category::Renderer,
Specialization::Scalar,
true,
true};
SwitchableSetting<int, true> crt_mask_type{linkage,
1, // Already correct 1, // Already correct
0, 0, 2, "crt_mask_type", Category::Renderer, Specialization::Scalar,
2, true, true}; // 0=none, 1=aperture, 2=shadow
"crt_mask_type", SwitchableSetting<float, true> crt_brightness{
Category::Renderer, linkage,
Specialization::Scalar,
true,
true}; // 0=none, 1=aperture, 2=shadow
SwitchableSetting<float, true> crt_brightness{linkage,
1.0f, // Default brightness (1.0 = no change) 1.0f, // Default brightness (1.0 = no change)
0.0f, 0.0f, 2.0f, "crt_brightness", Category::Renderer, Specialization::Scalar, true, true};
2.0f, SwitchableSetting<float, true> crt_alpha{
"crt_brightness", linkage,
Category::Renderer,
Specialization::Scalar,
true,
true};
SwitchableSetting<float, true> crt_alpha{linkage,
1.0f, // Default alpha (1.0 = fully opaque) 1.0f, // Default alpha (1.0 = fully opaque)
0.0f, 0.0f, 1.0f, "crt_alpha", Category::Renderer, Specialization::Scalar, true, true};
1.0f,
"crt_alpha",
Category::Renderer,
Specialization::Scalar,
true,
true};
SwitchableSetting<int, true> lanczos_quality{linkage, SwitchableSetting<int, true> lanczos_quality{linkage,
3, // Default value 3, // Default value
@@ -430,7 +405,8 @@ struct Values {
true, true,
true}; true};
SwitchableSetting<FSR2QualityMode, true> fsr2_quality_mode{linkage, SwitchableSetting<FSR2QualityMode, true> fsr2_quality_mode{
linkage,
FSR2QualityMode::Quality, // Quality by default FSR2QualityMode::Quality, // Quality by default
FSR2QualityMode::Quality, // Min value FSR2QualityMode::Quality, // Min value
FSR2QualityMode::UltraPerformance, // Max value FSR2QualityMode::UltraPerformance, // Max value
@@ -440,9 +416,8 @@ struct Values {
true, true,
true}; true};
SwitchableSetting<FrameSkipping, true> frame_skipping{
linkage,
SwitchableSetting<FrameSkipping, true> frame_skipping{linkage,
FrameSkipping::Disabled, // Disabled by default FrameSkipping::Disabled, // Disabled by default
FrameSkipping::Disabled, FrameSkipping::Disabled,
FrameSkipping::Enabled, FrameSkipping::Enabled,
@@ -452,7 +427,8 @@ struct Values {
true, true,
true}; true};
SwitchableSetting<FrameSkippingMode, true> frame_skipping_mode{linkage, SwitchableSetting<FrameSkippingMode, true> frame_skipping_mode{
linkage,
FrameSkippingMode::Adaptive, // Adaptive by default FrameSkippingMode::Adaptive, // Adaptive by default
FrameSkippingMode::Adaptive, FrameSkippingMode::Adaptive,
FrameSkippingMode::Fixed, FrameSkippingMode::Fixed,
@@ -552,9 +528,8 @@ struct Values {
true}; true};
// Enable sparse texture priority eviction (evict large unmapped pages first) // Enable sparse texture priority eviction (evict large unmapped pages first)
SwitchableSetting<bool> sparse_texture_priority_eviction{linkage, false, SwitchableSetting<bool> sparse_texture_priority_eviction{
"sparse_texture_priority_eviction", linkage, false, "sparse_texture_priority_eviction", Category::RendererAdvanced};
Category::RendererAdvanced};
// Enable VRAM usage logging for debugging // Enable VRAM usage logging for debugging
SwitchableSetting<bool> log_vram_usage{linkage, false, "log_vram_usage", SwitchableSetting<bool> log_vram_usage{linkage, false, "log_vram_usage",
@@ -605,7 +580,8 @@ struct Values {
Category::RendererAdvanced}; Category::RendererAdvanced};
SwitchableSetting<bool> barrier_feedback_loops{linkage, true, "barrier_feedback_loops", SwitchableSetting<bool> barrier_feedback_loops{linkage, true, "barrier_feedback_loops",
Category::RendererAdvanced}; Category::RendererAdvanced};
SwitchableSetting<ExtendedDynamicState, true> extended_dynamic_state{linkage, SwitchableSetting<ExtendedDynamicState, true> extended_dynamic_state{
linkage,
ExtendedDynamicState::EDS3, ExtendedDynamicState::EDS3,
ExtendedDynamicState::Disabled, ExtendedDynamicState::Disabled,
ExtendedDynamicState::EDS3, ExtendedDynamicState::EDS3,
@@ -676,7 +652,9 @@ struct Values {
true}; true};
// Linux // Linux
Setting<bool, false> is_wayland_platform{linkage, false, "is_wayland_platform", Category::Miscellaneous, Specialization::Default, false}; Setting<bool, false> is_wayland_platform{
linkage, false, "is_wayland_platform", Category::Miscellaneous, Specialization::Default,
false};
SwitchableSetting<bool> enable_gamemode{linkage, true, "enable_gamemode", Category::Linux}; SwitchableSetting<bool> enable_gamemode{linkage, true, "enable_gamemode", Category::Linux};
// Controls // Controls
@@ -809,7 +787,8 @@ struct Values {
Setting<std::string> citron_token{linkage, std::string(), "citron_token", Category::WebService}; Setting<std::string> citron_token{linkage, std::string(), "citron_token", Category::WebService};
// Updater // Updater
Setting<bool> enable_auto_update_check{linkage, true, "enable_auto_update_check", Category::WebService}; Setting<bool> enable_auto_update_check{linkage, true, "enable_auto_update_check",
Category::WebService};
// Add-Ons // Add-Ons
std::map<u64, std::vector<std::string>> disabled_addons; std::map<u64, std::vector<std::string>> disabled_addons;
@@ -823,9 +802,12 @@ struct Values {
// This stores the external path used for Intelligent Mirroring sync // This stores the external path used for Intelligent Mirroring sync
std::map<u64, std::string> mirrored_save_paths; std::map<u64, std::string> mirrored_save_paths;
Setting<bool> global_custom_save_path_enabled{linkage, false, "global_custom_save_path_enabled", Category::DataStorage}; Setting<bool> global_custom_save_path_enabled{linkage, false, "global_custom_save_path_enabled",
Setting<std::string> global_custom_save_path{linkage, std::string(), "global_custom_save_path", Category::DataStorage}; Category::DataStorage};
Setting<bool> backup_saves_to_nand{linkage, false, "backup_saves_to_nand", Category::DataStorage}; Setting<std::string> global_custom_save_path{linkage, std::string(), "global_custom_save_path",
Category::DataStorage};
Setting<bool> backup_saves_to_nand{linkage, false, "backup_saves_to_nand",
Category::DataStorage};
}; };
extern Values values; extern Values values;

View File

@@ -110,8 +110,7 @@ enum class AudioMode : u32 {
}; };
template <> template <>
inline std::vector<std::pair<std::string, AudioMode>> inline std::vector<std::pair<std::string, AudioMode>> EnumMetadata<AudioMode>::Canonicalizations() {
EnumMetadata<AudioMode>::Canonicalizations() {
return { return {
{"Mono", AudioMode::Mono}, {"Mono", AudioMode::Mono},
{"Stereo", AudioMode::Stereo}, {"Stereo", AudioMode::Stereo},
@@ -146,8 +145,7 @@ enum class Language : u32 {
}; };
template <> template <>
inline std::vector<std::pair<std::string, Language>> inline std::vector<std::pair<std::string, Language>> EnumMetadata<Language>::Canonicalizations() {
EnumMetadata<Language>::Canonicalizations() {
return { return {
{"Japanese", Language::Japanese}, {"Japanese", Language::Japanese},
{"EnglishAmerican", Language::EnglishAmerican}, {"EnglishAmerican", Language::EnglishAmerican},
@@ -186,15 +184,10 @@ enum class Region : u32 {
}; };
template <> template <>
inline std::vector<std::pair<std::string, Region>> inline std::vector<std::pair<std::string, Region>> EnumMetadata<Region>::Canonicalizations() {
EnumMetadata<Region>::Canonicalizations() {
return { return {
{"Japan", Region::Japan}, {"Japan", Region::Japan}, {"Usa", Region::Usa}, {"Europe", Region::Europe},
{"Usa", Region::Usa}, {"Australia", Region::Australia}, {"China", Region::China}, {"Korea", Region::Korea},
{"Europe", Region::Europe},
{"Australia", Region::Australia},
{"China", Region::China},
{"Korea", Region::Korea},
{"Taiwan", Region::Taiwan}, {"Taiwan", Region::Taiwan},
}; };
} }
@@ -254,8 +247,7 @@ enum class TimeZone : u32 {
}; };
template <> template <>
inline std::vector<std::pair<std::string, TimeZone>> inline std::vector<std::pair<std::string, TimeZone>> EnumMetadata<TimeZone>::Canonicalizations() {
EnumMetadata<TimeZone>::Canonicalizations() {
return { return {
{"Auto", TimeZone::Auto}, {"Auto", TimeZone::Auto},
{"Default", TimeZone::Default}, {"Default", TimeZone::Default},
@@ -388,8 +380,7 @@ enum class VSyncMode : u32 {
}; };
template <> template <>
inline std::vector<std::pair<std::string, VSyncMode>> inline std::vector<std::pair<std::string, VSyncMode>> EnumMetadata<VSyncMode>::Canonicalizations() {
EnumMetadata<VSyncMode>::Canonicalizations() {
return { return {
{"Immediate", VSyncMode::Immediate}, {"Immediate", VSyncMode::Immediate},
{"Mailbox", VSyncMode::Mailbox}, {"Mailbox", VSyncMode::Mailbox},
@@ -543,12 +534,9 @@ template <>
inline std::vector<std::pair<std::string, MemoryLayout>> inline std::vector<std::pair<std::string, MemoryLayout>>
EnumMetadata<MemoryLayout>::Canonicalizations() { EnumMetadata<MemoryLayout>::Canonicalizations() {
return { return {
{"Memory_4Gb", MemoryLayout::Memory_4Gb}, {"Memory_4Gb", MemoryLayout::Memory_4Gb}, {"Memory_6Gb", MemoryLayout::Memory_6Gb},
{"Memory_6Gb", MemoryLayout::Memory_6Gb}, {"Memory_8Gb", MemoryLayout::Memory_8Gb}, {"Memory_10Gb", MemoryLayout::Memory_10Gb},
{"Memory_8Gb", MemoryLayout::Memory_8Gb}, {"Memory_12Gb", MemoryLayout::Memory_12Gb}, {"Memory_14Gb", MemoryLayout::Memory_14Gb},
{"Memory_10Gb", MemoryLayout::Memory_10Gb},
{"Memory_12Gb", MemoryLayout::Memory_12Gb},
{"Memory_14Gb", MemoryLayout::Memory_14Gb},
{"Memory_16Gb", MemoryLayout::Memory_16Gb}, {"Memory_16Gb", MemoryLayout::Memory_16Gb},
}; };
} }
@@ -641,20 +629,13 @@ template <>
inline std::vector<std::pair<std::string, ResolutionSetup>> inline std::vector<std::pair<std::string, ResolutionSetup>>
EnumMetadata<ResolutionSetup>::Canonicalizations() { EnumMetadata<ResolutionSetup>::Canonicalizations() {
return { return {
{"Res1_4X", ResolutionSetup::Res1_4X}, {"Res1_4X", ResolutionSetup::Res1_4X}, {"Res1_2X", ResolutionSetup::Res1_2X},
{"Res1_2X", ResolutionSetup::Res1_2X}, {"Res3_4X", ResolutionSetup::Res3_4X}, {"Res1X", ResolutionSetup::Res1X},
{"Res3_4X", ResolutionSetup::Res3_4X}, {"Res5_4X", ResolutionSetup::Res5_4X}, {"Res3_2X", ResolutionSetup::Res3_2X},
{"Res1X", ResolutionSetup::Res1X}, {"Res7_4X", ResolutionSetup::Res7_4X}, {"Res2X", ResolutionSetup::Res2X},
{"Res5_4X", ResolutionSetup::Res5_4X}, {"Res3X", ResolutionSetup::Res3X}, {"Res4X", ResolutionSetup::Res4X},
{"Res3_2X", ResolutionSetup::Res3_2X}, {"Res5X", ResolutionSetup::Res5X}, {"Res6X", ResolutionSetup::Res6X},
{"Res7_4X", ResolutionSetup::Res7_4X}, {"Res7X", ResolutionSetup::Res7X}, {"Res8X", ResolutionSetup::Res8X},
{"Res2X", ResolutionSetup::Res2X},
{"Res3X", ResolutionSetup::Res3X},
{"Res4X", ResolutionSetup::Res4X},
{"Res5X", ResolutionSetup::Res5X},
{"Res6X", ResolutionSetup::Res6X},
{"Res7X", ResolutionSetup::Res7X},
{"Res8X", ResolutionSetup::Res8X},
}; };
} }
@@ -675,7 +656,8 @@ enum class ScalingFilter : u32 {
Fsr2 = 8, Fsr2 = 8,
CRTEasyMode = 9, CRTEasyMode = 9,
CRTRoyale = 10, CRTRoyale = 10,
MaxEnum = 11, Cas = 11,
MaxEnum = 12,
}; };
template <> template <>
@@ -693,6 +675,7 @@ EnumMetadata<ScalingFilter>::Canonicalizations() {
{"Fsr2", ScalingFilter::Fsr2}, {"Fsr2", ScalingFilter::Fsr2},
{"CRTEasyMode", ScalingFilter::CRTEasyMode}, {"CRTEasyMode", ScalingFilter::CRTEasyMode},
{"CRTRoyale", ScalingFilter::CRTRoyale}, {"CRTRoyale", ScalingFilter::CRTRoyale},
{"Cas", ScalingFilter::Cas},
{"MaxEnum", ScalingFilter::MaxEnum}, {"MaxEnum", ScalingFilter::MaxEnum},
}; };
} }
@@ -714,10 +697,8 @@ template <>
inline std::vector<std::pair<std::string, AntiAliasing>> inline std::vector<std::pair<std::string, AntiAliasing>>
EnumMetadata<AntiAliasing>::Canonicalizations() { EnumMetadata<AntiAliasing>::Canonicalizations() {
return { return {
{"None", AntiAliasing::None}, {"None", AntiAliasing::None}, {"Fxaa", AntiAliasing::Fxaa},
{"Fxaa", AntiAliasing::Fxaa}, {"Smaa", AntiAliasing::Smaa}, {"Taa", AntiAliasing::Taa},
{"Smaa", AntiAliasing::Smaa},
{"Taa", AntiAliasing::Taa},
{"MaxEnum", AntiAliasing::MaxEnum}, {"MaxEnum", AntiAliasing::MaxEnum},
}; };
} }
@@ -805,12 +786,9 @@ template <>
inline std::vector<std::pair<std::string, AspectRatio>> inline std::vector<std::pair<std::string, AspectRatio>>
EnumMetadata<AspectRatio>::Canonicalizations() { EnumMetadata<AspectRatio>::Canonicalizations() {
return { return {
{"R16_9", AspectRatio::R16_9}, {"R16_9", AspectRatio::R16_9}, {"R4_3", AspectRatio::R4_3},
{"R4_3", AspectRatio::R4_3}, {"R21_9", AspectRatio::R21_9}, {"R16_10", AspectRatio::R16_10},
{"R21_9", AspectRatio::R21_9}, {"R32_9", AspectRatio::R32_9}, {"Stretch", AspectRatio::Stretch},
{"R16_10", AspectRatio::R16_10},
{"R32_9", AspectRatio::R32_9},
{"Stretch", AspectRatio::Stretch},
}; };
} }

View File

@@ -95,6 +95,7 @@ void BlitScreen::CreateWindowAdapt() {
break; break;
case Settings::ScalingFilter::Fsr: case Settings::ScalingFilter::Fsr:
case Settings::ScalingFilter::Fsr2: case Settings::ScalingFilter::Fsr2:
case Settings::ScalingFilter::Cas:
case Settings::ScalingFilter::Bilinear: case Settings::ScalingFilter::Bilinear:
default: default:
window_adapt = MakeBilinear(device); window_adapt = MakeBilinear(device);

View File

@@ -49,11 +49,12 @@ FSR::FSR(u32 output_width_, u32 output_height_) : width(output_width_), height(o
FSR::~FSR() = default; FSR::~FSR() = default;
GLuint FSR::Draw(ProgramManager& program_manager, GLuint texture, u32 input_image_width, GLuint FSR::Draw(ProgramManager& program_manager, GLuint texture, u32 input_image_width,
u32 input_image_height, const Common::Rectangle<f32>& crop_rect) { u32 input_image_height, const Common::Rectangle<float>& crop_rect,
const f32 input_width = static_cast<f32>(input_image_width); float sharpening) {
const f32 input_height = static_cast<f32>(input_image_height); const float input_width = static_cast<float>(input_image_width);
const f32 output_width = static_cast<f32>(width); const float input_height = static_cast<float>(input_image_height);
const f32 output_height = static_cast<f32>(height); const float output_width = static_cast<float>(width);
const float output_height = static_cast<float>(height);
const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width; const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width;
const f32 viewport_x = crop_rect.left * input_width; const f32 viewport_x = crop_rect.left * input_width;
const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_height; const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_height;
@@ -66,9 +67,6 @@ GLuint FSR::Draw(ProgramManager& program_manager, GLuint texture, u32 input_imag
easu_con.data() + 12, viewport_width, viewport_height, input_width, easu_con.data() + 12, viewport_width, viewport_height, input_width,
input_height, output_width, output_height, viewport_x, viewport_y); input_height, output_width, output_height, viewport_x, viewport_y);
const float sharpening =
static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
FsrRcasCon(rcas_con.data(), sharpening); FsrRcasCon(rcas_con.data(), sharpening);
glProgramUniform4uiv(easu_frag.handle, 0, sizeof(easu_con), easu_con.data()); glProgramUniform4uiv(easu_frag.handle, 0, sizeof(easu_con), easu_con.data());

View File

@@ -20,7 +20,8 @@ public:
~FSR(); ~FSR();
GLuint Draw(ProgramManager& program_manager, GLuint texture, u32 input_image_width, GLuint Draw(ProgramManager& program_manager, GLuint texture, u32 input_image_width,
u32 input_image_height, const Common::Rectangle<f32>& crop_rect); u32 input_image_height, const Common::Rectangle<float>& crop_rect,
float sharpening);
bool NeedsRecreation(const Common::Rectangle<u32>& screen); bool NeedsRecreation(const Common::Rectangle<u32>& screen);

View File

@@ -65,8 +65,8 @@ GLuint Layer::ConfigureDraw(std::array<GLfloat, 3 * 2>& out_matrix,
break; break;
case Settings::AntiAliasing::Taa: case Settings::AntiAliasing::Taa:
CreateTAA(); CreateTAA();
texture = taa->Draw(program_manager, info.display_texture, texture = taa->Draw(program_manager, info.display_texture, GL_NONE, GL_NONE, GL_NONE,
GL_NONE, GL_NONE, GL_NONE, 0); // TODO: Add proper motion vectors 0); // TODO: Add proper motion vectors
break; break;
default: default:
break; break;
@@ -75,12 +75,23 @@ GLuint Layer::ConfigureDraw(std::array<GLfloat, 3 * 2>& out_matrix,
glDisablei(GL_SCISSOR_TEST, 0); glDisablei(GL_SCISSOR_TEST, 0);
if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr ||
filters.get_scaling_filter() == Settings::ScalingFilter::Cas) {
if (!fsr || fsr->NeedsRecreation(layout.screen)) { if (!fsr || fsr->NeedsRecreation(layout.screen)) {
fsr = std::make_unique<FSR>(layout.screen.GetWidth(), layout.screen.GetHeight()); fsr = std::make_unique<FSR>(layout.screen.GetWidth(), layout.screen.GetHeight());
} }
texture = fsr->Draw(program_manager, texture, info.scaled_width, info.scaled_height, crop); float sharpening = 0.0f;
if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) {
sharpening =
static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
} else if (filters.get_scaling_filter() == Settings::ScalingFilter::Cas) {
sharpening =
static_cast<float>(Settings::values.cas_sharpening_slider.GetValue()) / 100.0f;
}
texture = fsr->Draw(program_manager, texture, info.scaled_width, info.scaled_height, crop,
sharpening);
crop = {0, 0, 1, 1}; crop = {0, 0, 1, 1};
} }
if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr2) { if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr2) {

View File

@@ -5,14 +5,16 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/host_shaders/present_bicubic_frag_spv.h" #include "video_core/host_shaders/present_bicubic_frag_spv.h"
#include "video_core/host_shaders/present_lanczos_frag_spv.h"
#include "video_core/host_shaders/present_gaussian_frag_spv.h" #include "video_core/host_shaders/present_gaussian_frag_spv.h"
#include "video_core/host_shaders/present_lanczos_frag_spv.h"
#include "video_core/host_shaders/vulkan_crt_easymode_frag_spv.h"
#include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp16_frag_spv.h"
#include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp32_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_frag_spv.h" #include "video_core/host_shaders/vulkan_present_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h" #include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h" #include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scalefx_fp16_frag_spv.h" #include "video_core/host_shaders/vulkan_present_scalefx_fp16_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scalefx_fp32_frag_spv.h" #include "video_core/host_shaders/vulkan_present_scalefx_fp32_frag_spv.h"
#include "video_core/host_shaders/vulkan_crt_easymode_frag_spv.h"
#include "video_core/renderer_vulkan/present/filters.h" #include "video_core/renderer_vulkan/present/filters.h"
#include "video_core/renderer_vulkan/present/util.h" #include "video_core/renderer_vulkan/present/util.h"
#include "video_core/renderer_vulkan/vk_shader_util.h" #include "video_core/renderer_vulkan/vk_shader_util.h"
@@ -72,7 +74,8 @@ std::unique_ptr<WindowAdaptPass> MakeScaleFx(const Device& device, VkFormat fram
} }
std::unique_ptr<WindowAdaptPass> MakeLanczos(const Device& device, VkFormat frame_format) { std::unique_ptr<WindowAdaptPass> MakeLanczos(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(device, frame_format, CreateNearestNeighborSampler(device), return std::make_unique<WindowAdaptPass>(device, frame_format,
CreateNearestNeighborSampler(device),
BuildShader(device, PRESENT_LANCZOS_FRAG_SPV)); BuildShader(device, PRESENT_LANCZOS_FRAG_SPV));
} }

View File

@@ -24,8 +24,8 @@ using PushConstants = std::array<u32, 4 * 4>;
FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count,
VkExtent2D extent) VkExtent2D extent)
: m_device{device}, m_memory_allocator{memory_allocator}, : m_device{device}, m_memory_allocator{memory_allocator}, m_image_count{image_count},
m_image_count{image_count}, m_extent{extent} { m_extent{extent} {
CreateImages(); CreateImages();
CreateRenderPasses(); CreateRenderPasses();
@@ -157,7 +157,7 @@ void FSR::UploadImages(Scheduler& scheduler) {
VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
VkImageView source_image_view, VkExtent2D input_image_extent, VkImageView source_image_view, VkExtent2D input_image_extent,
const Common::Rectangle<f32>& crop_rect) { const Common::Rectangle<f32>& crop_rect, float sharpening) {
Images& images = m_dynamic_images[image_index]; Images& images = m_dynamic_images[image_index];
VkImage easu_image = *images.images[Easu]; VkImage easu_image = *images.images[Easu];
@@ -188,8 +188,6 @@ VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_i
input_image_height, output_image_width, output_image_height, viewport_x, input_image_height, output_image_width, output_image_height, viewport_x,
viewport_y); viewport_y);
const float sharpening =
static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
FsrRcasCon(rcas_con.data(), sharpening); FsrRcasCon(rcas_con.data(), sharpening);
UploadImages(scheduler); UploadImages(scheduler);

View File

@@ -18,7 +18,7 @@ public:
VkExtent2D extent); VkExtent2D extent);
VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
VkImageView source_image_view, VkExtent2D input_image_extent, VkImageView source_image_view, VkExtent2D input_image_extent,
const Common::Rectangle<f32>& crop_rect); const Common::Rectangle<f32>& crop_rect, float sharpening);
private: private:
void CreateImages(); void CreateImages();

View File

@@ -57,7 +57,8 @@ Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Schedule
device_memory(device_memory_), filters(filters_), image_count(image_count_) { device_memory(device_memory_), filters(filters_), image_count(image_count_) {
CreateDescriptorPool(); CreateDescriptorPool();
CreateDescriptorSets(layout); CreateDescriptorSets(layout);
if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr ||
filters.get_scaling_filter() == Settings::ScalingFilter::Cas) {
CreateFSR(output_size); CreateFSR(output_size);
} }
if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr2) { if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr2) {
@@ -109,8 +110,16 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants,
}; };
if (fsr) { if (fsr) {
float sharpening = 0.0f;
if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) {
sharpening =
static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
} else if (filters.get_scaling_filter() == Settings::ScalingFilter::Cas) {
sharpening =
static_cast<float>(Settings::values.cas_sharpening_slider.GetValue()) / 100.0f;
}
source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view,
render_extent, crop_rect); render_extent, crop_rect, sharpening);
crop_rect = {0, 0, 1, 1}; crop_rect = {0, 0, 1, 1};
} }
if (fsr2) { if (fsr2) {
@@ -257,7 +266,8 @@ void Layer::UpdateDescriptorSet(VkImageView image_view, VkSampler sampler, size_
const VkDescriptorImageInfo image_info{ const VkDescriptorImageInfo image_info{
.sampler = sampler, .sampler = sampler,
.imageView = image_view, .imageView = image_view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // Correct layout for texture sampling .imageLayout =
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // Correct layout for texture sampling
}; };
const VkWriteDescriptorSet sampler_write{ const VkWriteDescriptorSet sampler_write{

View File

@@ -2,8 +2,10 @@
// SPDX-FileCopyrightText: Copyright 2026 citron Emulator Project // SPDX-FileCopyrightText: Copyright 2026 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/frontend/framebuffer_layout.h" #include "core/frontend/framebuffer_layout.h"
#include "video_core/framebuffer_config.h" #include "video_core/framebuffer_config.h"
#include "video_core/fsr.h"
#include "video_core/host_shaders/vulkan_present_vert_spv.h" #include "video_core/host_shaders/vulkan_present_vert_spv.h"
#include "video_core/renderer_vulkan/present/layer.h" #include "video_core/renderer_vulkan/present/layer.h"
#include "video_core/renderer_vulkan/present/present_push_constants.h" #include "video_core/renderer_vulkan/present/present_push_constants.h"
@@ -13,7 +15,6 @@
#include "video_core/renderer_vulkan/vk_shader_util.h" #include "video_core/renderer_vulkan/vk_shader_util.h"
#include "video_core/vulkan_common/vulkan_device.h" #include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_memory_allocator.h" #include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "common/settings.h"
namespace Vulkan { namespace Vulkan {
@@ -93,7 +94,8 @@ void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, s
cmdbuf.ClearAttachments({clear_attachment}, {clear_rect}); cmdbuf.ClearAttachments({clear_attachment}, {clear_rect});
const auto current_scaling_filter = Settings::values.scaling_filter.GetValue(); const auto current_scaling_filter = Settings::values.scaling_filter.GetValue();
const bool is_crt_enabled = current_scaling_filter == Settings::ScalingFilter::CRTEasyMode || const bool is_crt_enabled =
current_scaling_filter == Settings::ScalingFilter::CRTEasyMode ||
current_scaling_filter == Settings::ScalingFilter::CRTRoyale; current_scaling_filter == Settings::ScalingFilter::CRTRoyale;
for (size_t i = 0; i < layer_count; i++) { for (size_t i = 0; i < layer_count; i++) {
@@ -139,6 +141,7 @@ void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, s
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline_layout, 0, cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline_layout, 0,
descriptor_sets[i], {}); descriptor_sets[i], {});
cmdbuf.Draw(4, 1, 0, 0); cmdbuf.Draw(4, 1, 0, 0);
} }

View File

@@ -55,6 +55,7 @@ void BlitScreen::SetWindowAdaptPass() {
case Settings::ScalingFilter::CRTRoyale: case Settings::ScalingFilter::CRTRoyale:
window_adapt = MakeCRT(device, swapchain_view_format); window_adapt = MakeCRT(device, swapchain_view_format);
break; break;
case Settings::ScalingFilter::Cas:
case Settings::ScalingFilter::Fsr: case Settings::ScalingFilter::Fsr:
case Settings::ScalingFilter::Fsr2: case Settings::ScalingFilter::Fsr2:
case Settings::ScalingFilter::Bilinear: case Settings::ScalingFilter::Bilinear: