Qt/Fullscreenui/GS: Add Automatic blending option.

Automatic blending option will behave like basic level with the exception of gamedb if it forces a blend level then it will take that in to consideration, any other option will override the gamedb.
This commit is contained in:
lightningterror 2025-09-02 13:34:39 +02:00
parent 9864cd97de
commit 3b0a83c1ab
8 changed files with 34 additions and 19 deletions

View File

@ -116,6 +116,11 @@
</item>
<item row="5" column="1">
<widget class="QComboBox" name="blending">
<item>
<property name="text">
<string>Automatic (Default)</string>
</property>
</item>
<item>
<property name="text">
<string>Minimum</string>
@ -123,7 +128,7 @@
</item>
<item>
<property name="text">
<string>Basic (Recommended)</string>
<string>Basic</string>
</property>
</item>
<item>

View File

@ -121,7 +121,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_hw.dithering, "EmuCore/GS", "dithering_ps2", 2);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.mipmapping, "EmuCore/GS", "hw_mipmap", true);
SettingWidgetBinder::BindWidgetToIntSetting(
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Automatic), -1);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.enableHWFixes, "EmuCore/GS", "UserHacks", false);
connect(m_hw.upscaleMultiplier, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onUpscaleMultiplierChanged);

View File

@ -327,8 +327,9 @@ enum class TriFiltering : s8
Forced,
};
enum class AccBlendLevel : u8
enum class AccBlendLevel : s8
{
Automatic = -1,
Minimum,
Basic,
Medium,
@ -811,7 +812,7 @@ struct Pcsx2Config
GSRendererType Renderer = GSRendererType::Auto;
float UpscaleMultiplier = 1.0f;
AccBlendLevel AccurateBlendingUnit = AccBlendLevel::Basic;
AccBlendLevel AccurateBlendingUnit = AccBlendLevel::Automatic;
BiFiltering TextureFiltering = BiFiltering::PS2;
TexturePreloadingLevel TexturePreloading = TexturePreloadingLevel::Full;
GSDumpCompressionMethod GSDumpCompression = GSDumpCompressionMethod::Zstandard;

View File

@ -5180,6 +5180,8 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GS
enable_fbmask_emulation = true;
break;
case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Enable Fbmask emulation excluding triangle class because it is quite slow.
enable_fbmask_emulation = (m_vt.m_primclass != GS_TRIANGLE_CLASS);
break;
@ -5784,7 +5786,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
const bool blend_ad = m_conf.ps.blend_c == 1;
const bool alpha_mask = (m_cached_ctx.FRAME.FBMSK & 0xFF000000) == 0xFF000000;
bool blend_ad_alpha_masked = blend_ad && alpha_mask;
const bool is_basic_blend = GSConfig.AccurateBlendingUnit >= AccBlendLevel::Basic;
const bool is_basic_blend = GSConfig.AccurateBlendingUnit != AccBlendLevel::Minimum;
if (blend_ad_alpha_masked && (((is_basic_blend || (COLCLAMP.CLAMP == 0)) && (features.texture_barrier || features.multidraw_fb_copy))
|| ((GSConfig.AccurateBlendingUnit >= AccBlendLevel::Medium) || m_conf.require_one_barrier)))
{
@ -5894,6 +5896,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
sw_blending |= m_vt.m_primclass == GS_SPRITE_CLASS && m_drawlist.size() < 100;
[[fallthrough]];
case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !prefer_sw_blend;
@ -5935,6 +5939,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
sw_blending |= !(blend_ad_alpha_masked || ad_second_pass) && (alpha_c1_high_max_one || alpha_c1_high_no_rta_correct) && no_prim_overlap;
[[fallthrough]];
case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !prefer_sw_blend;

View File

@ -664,10 +664,10 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
return (config.GPUPaletteConversion == ((value > 1) ? (config.TexturePreloading == TexturePreloadingLevel::Full) : (value != 0)));
case GSHWFixId::MinimumBlendingLevel:
return (static_cast<int>(config.AccurateBlendingUnit) >= value);
return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) >= value);
case GSHWFixId::MaximumBlendingLevel:
return (static_cast<int>(config.AccurateBlendingUnit) <= value);
return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) <= value);
case GSHWFixId::RecommendedBlendingLevel:
return true;
@ -868,21 +868,23 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
case GSHWFixId::MinimumBlendingLevel:
{
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum))
config.AccurateBlendingUnit = std::max(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value));
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
}
break;
case GSHWFixId::MaximumBlendingLevel:
{
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum))
config.AccurateBlendingUnit = std::min(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value));
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
}
break;
case GSHWFixId::RecommendedBlendingLevel:
{
if (!is_sw_renderer && value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && static_cast<int>(EmuConfig.GS.AccurateBlendingUnit) < value)
// Need to increment by 1 because Automatic is -1.
const int blend_level = static_cast<int>(config.AccurateBlendingUnit) + 1;
if (!is_sw_renderer && value >= static_cast<int>(AccBlendLevel::Automatic) && value <= static_cast<int>(AccBlendLevel::Maximum) && blend_level < value)
{
Host::AddKeyedOSDMessage("HWBlendingWarning",
fmt::format(TRANSLATE_FS("GameDatabase",
@ -891,8 +893,7 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
"You can adjust the blending level in Game Properties to improve\n"
"graphical quality, but this will increase system requirements."),
ICON_FA_PAINTBRUSH,
Pcsx2Config::GSOptions::BlendingLevelNames[static_cast<int>(
EmuConfig.GS.AccurateBlendingUnit)],
Pcsx2Config::GSOptions::BlendingLevelNames[blend_level],
Pcsx2Config::GSOptions::BlendingLevelNames[value]),
Host::OSD_WARNING_DURATION);
}

View File

@ -4066,8 +4066,9 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
FSUI_NSTR("Force 32bit"),
};
static constexpr const char* s_blending_options[] = {
FSUI_NSTR("Automatic (Default)"),
FSUI_NSTR("Minimum"),
FSUI_NSTR("Basic (Recommended)"),
FSUI_NSTR("Basic"),
FSUI_NSTR("Medium"),
FSUI_NSTR("High"),
FSUI_NSTR("Full (Slow)"),
@ -4199,7 +4200,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
"EmuCore/GS", "dithering_ps2", 2, s_dithering_options, std::size(s_dithering_options), true);
DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_SPLOTCH, "Blending Accuracy"),
FSUI_CSTR("Determines the level of accuracy when emulating blend modes not supported by the host graphics API."), "EmuCore/GS",
"accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic), s_blending_options, std::size(s_blending_options), true);
"accurate_blending_unit", static_cast<int>(AccBlendLevel::Automatic), s_blending_options, std::size(s_blending_options), true);
DrawToggleSetting(
bsi, FSUI_ICONSTR(ICON_FA_BULLSEYE, "Mipmapping"), FSUI_CSTR("Enables emulation of the GS's texture mipmapping."), "EmuCore/GS", "hw_mipmap", true);
}

View File

@ -653,6 +653,7 @@ const char* Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames[(size_t)FMVAspectR
nullptr};
const char* Pcsx2Config::GSOptions::BlendingLevelNames[] = {
"Automatic",
"Minimum",
"Basic",
"Medium",

View File

@ -3150,12 +3150,12 @@ void VMManager::WarnAboutUnsafeSettings()
if (EmuConfig.GS.TriFilter != TriFiltering::Automatic)
{
append(ICON_FA_PAGER,
TRANSLATE_SV("VMManager", "Trilinear filtering is not set to automatic. This may break rendering in some games."));
TRANSLATE_SV("VMManager", "Trilinear filtering is not set to Automatic. This may break rendering in some games."));
}
if (EmuConfig.GS.AccurateBlendingUnit <= AccBlendLevel::Minimum)
if (EmuConfig.GS.AccurateBlendingUnit == AccBlendLevel::Minimum)
{
append(ICON_FA_PAINTBRUSH,
TRANSLATE_SV("VMManager", "Blending Accuracy is below Basic, this may break effects in some games."));
TRANSLATE_SV("VMManager", "Blending Accuracy is set to Minimum. This may break rendering in some games."));
}
if (EmuConfig.GS.HWDownloadMode != GSHardwareDownloadMode::Enabled)
{