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>
<item row="5" column="1"> <item row="5" column="1">
<widget class="QComboBox" name="blending"> <widget class="QComboBox" name="blending">
<item>
<property name="text">
<string>Automatic (Default)</string>
</property>
</item>
<item> <item>
<property name="text"> <property name="text">
<string>Minimum</string> <string>Minimum</string>
@ -123,7 +128,7 @@
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Basic (Recommended)</string> <string>Basic</string>
</property> </property>
</item> </item>
<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::BindWidgetToIntSetting(sif, m_hw.dithering, "EmuCore/GS", "dithering_ps2", 2);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.mipmapping, "EmuCore/GS", "hw_mipmap", true); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.mipmapping, "EmuCore/GS", "hw_mipmap", true);
SettingWidgetBinder::BindWidgetToIntSetting( 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); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.enableHWFixes, "EmuCore/GS", "UserHacks", false);
connect(m_hw.upscaleMultiplier, QOverload<int>::of(&QComboBox::currentIndexChanged), this, connect(m_hw.upscaleMultiplier, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onUpscaleMultiplierChanged); &GraphicsSettingsWidget::onUpscaleMultiplierChanged);

View File

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

View File

@ -5180,6 +5180,8 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GS
enable_fbmask_emulation = true; enable_fbmask_emulation = true;
break; break;
case AccBlendLevel::Basic: case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Enable Fbmask emulation excluding triangle class because it is quite slow. // Enable Fbmask emulation excluding triangle class because it is quite slow.
enable_fbmask_emulation = (m_vt.m_primclass != GS_TRIANGLE_CLASS); enable_fbmask_emulation = (m_vt.m_primclass != GS_TRIANGLE_CLASS);
break; 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 blend_ad = m_conf.ps.blend_c == 1;
const bool alpha_mask = (m_cached_ctx.FRAME.FBMSK & 0xFF000000) == 0xFF000000; const bool alpha_mask = (m_cached_ctx.FRAME.FBMSK & 0xFF000000) == 0xFF000000;
bool blend_ad_alpha_masked = blend_ad && alpha_mask; 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)) 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))) || ((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; sw_blending |= m_vt.m_primclass == GS_SPRITE_CLASS && m_drawlist.size() < 100;
[[fallthrough]]; [[fallthrough]];
case AccBlendLevel::Basic: case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Prefer sw blend if possible. // Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend; color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !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; sw_blending |= !(blend_ad_alpha_masked || ad_second_pass) && (alpha_c1_high_max_one || alpha_c1_high_no_rta_correct) && no_prim_overlap;
[[fallthrough]]; [[fallthrough]];
case AccBlendLevel::Basic: case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Prefer sw blend if possible. // Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend; color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !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))); return (config.GPUPaletteConversion == ((value > 1) ? (config.TexturePreloading == TexturePreloadingLevel::Full) : (value != 0)));
case GSHWFixId::MinimumBlendingLevel: case GSHWFixId::MinimumBlendingLevel:
return (static_cast<int>(config.AccurateBlendingUnit) >= value); return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) >= value);
case GSHWFixId::MaximumBlendingLevel: case GSHWFixId::MaximumBlendingLevel:
return (static_cast<int>(config.AccurateBlendingUnit) <= value); return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) <= value);
case GSHWFixId::RecommendedBlendingLevel: case GSHWFixId::RecommendedBlendingLevel:
return true; return true;
@ -868,21 +868,23 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
case GSHWFixId::MinimumBlendingLevel: case GSHWFixId::MinimumBlendingLevel:
{ {
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum)) if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
config.AccurateBlendingUnit = std::max(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value)); config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
} }
break; break;
case GSHWFixId::MaximumBlendingLevel: case GSHWFixId::MaximumBlendingLevel:
{ {
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum)) if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
config.AccurateBlendingUnit = std::min(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value)); config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
} }
break; break;
case GSHWFixId::RecommendedBlendingLevel: 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", Host::AddKeyedOSDMessage("HWBlendingWarning",
fmt::format(TRANSLATE_FS("GameDatabase", 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" "You can adjust the blending level in Game Properties to improve\n"
"graphical quality, but this will increase system requirements."), "graphical quality, but this will increase system requirements."),
ICON_FA_PAINTBRUSH, ICON_FA_PAINTBRUSH,
Pcsx2Config::GSOptions::BlendingLevelNames[static_cast<int>( Pcsx2Config::GSOptions::BlendingLevelNames[blend_level],
EmuConfig.GS.AccurateBlendingUnit)],
Pcsx2Config::GSOptions::BlendingLevelNames[value]), Pcsx2Config::GSOptions::BlendingLevelNames[value]),
Host::OSD_WARNING_DURATION); Host::OSD_WARNING_DURATION);
} }

View File

@ -4066,8 +4066,9 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
FSUI_NSTR("Force 32bit"), FSUI_NSTR("Force 32bit"),
}; };
static constexpr const char* s_blending_options[] = { static constexpr const char* s_blending_options[] = {
FSUI_NSTR("Automatic (Default)"),
FSUI_NSTR("Minimum"), FSUI_NSTR("Minimum"),
FSUI_NSTR("Basic (Recommended)"), FSUI_NSTR("Basic"),
FSUI_NSTR("Medium"), FSUI_NSTR("Medium"),
FSUI_NSTR("High"), FSUI_NSTR("High"),
FSUI_NSTR("Full (Slow)"), 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); "EmuCore/GS", "dithering_ps2", 2, s_dithering_options, std::size(s_dithering_options), true);
DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_SPLOTCH, "Blending Accuracy"), 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", 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( DrawToggleSetting(
bsi, FSUI_ICONSTR(ICON_FA_BULLSEYE, "Mipmapping"), FSUI_CSTR("Enables emulation of the GS's texture mipmapping."), "EmuCore/GS", "hw_mipmap", true); 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}; nullptr};
const char* Pcsx2Config::GSOptions::BlendingLevelNames[] = { const char* Pcsx2Config::GSOptions::BlendingLevelNames[] = {
"Automatic",
"Minimum", "Minimum",
"Basic", "Basic",
"Medium", "Medium",

View File

@ -3150,12 +3150,12 @@ void VMManager::WarnAboutUnsafeSettings()
if (EmuConfig.GS.TriFilter != TriFiltering::Automatic) if (EmuConfig.GS.TriFilter != TriFiltering::Automatic)
{ {
append(ICON_FA_PAGER, 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, 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) if (EmuConfig.GS.HWDownloadMode != GSHardwareDownloadMode::Enabled)
{ {