GS/HW: Extend bilinear dirty upscale fix to force nearest

This commit is contained in:
Stenzek 2023-07-26 00:00:49 +10:00 committed by Connor McLaughlin
parent 460a2dbbd3
commit 3692d7d090
9 changed files with 67 additions and 34 deletions

View File

@ -218,12 +218,12 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfPixelOffset, "EmuCore/GS", "UserHacks_HalfPixelOffset", 0); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfPixelOffset, "EmuCore/GS", "UserHacks_HalfPixelOffset", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.roundSprite, "EmuCore/GS", "UserHacks_round_sprite_offset", 0); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.roundSprite, "EmuCore/GS", "UserHacks_round_sprite_offset", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.bilinearHack, "EmuCore/GS", "UserHacks_BilinearHack", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetX, "EmuCore/GS", "UserHacks_TCOffsetX", 0); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetX, "EmuCore/GS", "UserHacks_TCOffsetX", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetY, "EmuCore/GS", "UserHacks_TCOffsetY", 0); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetY, "EmuCore/GS", "UserHacks_TCOffsetY", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.bilinearHack, "EmuCore/GS", "UserHacks_BilinearHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.nativePaletteDraw, "EmuCore/GS", "UserHacks_NativePaletteDraw", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.nativePaletteDraw, "EmuCore/GS", "UserHacks_NativePaletteDraw", false);
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Texture Replacements // Texture Replacements

View File

@ -1168,14 +1168,14 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QLabel" name="textureOffsetLabel"> <widget class="QLabel" name="textureOffsetLabel">
<property name="text"> <property name="text">
<string>Texture Offsets:</string> <string>Texture Offsets:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="3" column="1">
<layout class="QHBoxLayout" name="textureOffsetLayout" stretch="0,1,0,1"> <layout class="QHBoxLayout" name="textureOffsetLayout" stretch="0,1,0,1">
<item> <item>
<widget class="QLabel" name="textureOffsetXLabel"> <widget class="QLabel" name="textureOffsetXLabel">
@ -1207,7 +1207,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="3" column="0" colspan="2"> <item row="4" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QCheckBox" name="alignSprite"> <widget class="QCheckBox" name="alignSprite">
@ -1216,20 +1216,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QCheckBox" name="bilinearHack">
<property name="text">
<string>Bilinear Dirty Upscale</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="mergeSprite">
<property name="text">
<string>Merge Sprite</string>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QCheckBox" name="nativePaletteDraw"> <widget class="QCheckBox" name="nativePaletteDraw">
<property name="text"> <property name="text">
@ -1244,8 +1230,41 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QCheckBox" name="mergeSprite">
<property name="text">
<string>Merge Sprite</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Bilinear Dirty Upscale:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="bilinearHack">
<item>
<property name="text">
<string>Automatic (Default)</string>
</property>
</item>
<item>
<property name="text">
<string>Force Bilinear</string>
</property>
</item>
<item>
<property name="text">
<string>Force Nearest</string>
</property>
</item>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">

View File

@ -364,6 +364,14 @@ enum class GSTextureInRtMode : u8
MergeTargets, MergeTargets,
}; };
enum class GSBilinearDirtyMode : u8
{
Automatic,
ForceBilinear,
ForceNearest,
MaxCount
};
// Template function for casting enumerations to their underlying type // Template function for casting enumerations to their underlying type
template <typename Enumeration> template <typename Enumeration>
typename std::underlying_type<Enumeration>::type enum_cast(Enumeration E) typename std::underlying_type<Enumeration>::type enum_cast(Enumeration E)
@ -683,7 +691,6 @@ struct Pcsx2Config
UserHacks_DisableRenderFixes : 1, UserHacks_DisableRenderFixes : 1,
UserHacks_MergePPSprite : 1, UserHacks_MergePPSprite : 1,
UserHacks_WildHack : 1, UserHacks_WildHack : 1,
UserHacks_BilinearHack : 1,
UserHacks_NativePaletteDraw : 1, UserHacks_NativePaletteDraw : 1,
UserHacks_TargetPartialInvalidation : 1, UserHacks_TargetPartialInvalidation : 1,
UserHacks_EstimateTextureRegion : 1, UserHacks_EstimateTextureRegion : 1,
@ -763,6 +770,7 @@ struct Pcsx2Config
u8 UserHacks_CPUCLUTRender = 0; u8 UserHacks_CPUCLUTRender = 0;
GSGPUTargetCLUTMode UserHacks_GPUTargetCLUTMode = GSGPUTargetCLUTMode::Disabled; GSGPUTargetCLUTMode UserHacks_GPUTargetCLUTMode = GSGPUTargetCLUTMode::Disabled;
GSTextureInRtMode UserHacks_TextureInsideRt = GSTextureInRtMode::Disabled; GSTextureInRtMode UserHacks_TextureInsideRt = GSTextureInRtMode::Disabled;
GSBilinearDirtyMode UserHacks_BilinearHack = GSBilinearDirtyMode::Automatic;
TriFiltering TriFilter = TriFiltering::Automatic; TriFiltering TriFilter = TriFiltering::Automatic;
s8 OverrideTextureBarriers = -1; s8 OverrideTextureBarriers = -1;

View File

@ -175,7 +175,7 @@
"bilinearUpscale": { "bilinearUpscale": {
"type": "integer", "type": "integer",
"minimum": 0, "minimum": 0,
"maximum": 1 "maximum": 2
}, },
"nativePaletteDraw": { "nativePaletteDraw": {
"type": "integer", "type": "integer",

View File

@ -5131,8 +5131,8 @@ void GSTextureCache::Target::Update()
// Bilinear filtering this is probably not a good thing, at least in native, but upscaling Nearest can be gross and messy. // Bilinear filtering this is probably not a good thing, at least in native, but upscaling Nearest can be gross and messy.
// It's needed for depth, though.. filtering depth doesn't make much sense, but SMT3 needs it.. // It's needed for depth, though.. filtering depth doesn't make much sense, but SMT3 needs it..
const bool upscaled = (m_scale != 1.0f); const bool upscaled = (m_scale != 1.0f);
const bool override_linear = upscaled && GSConfig.UserHacks_BilinearHack; const bool override_linear = (upscaled && GSConfig.UserHacks_BilinearHack == GSBilinearDirtyMode::ForceBilinear);
const bool linear = (m_type == RenderTarget && upscaled); const bool linear = (m_type == RenderTarget && upscaled && GSConfig.UserHacks_BilinearHack != GSBilinearDirtyMode::ForceNearest);
GSDevice::MultiStretchRect* drects = static_cast<GSDevice::MultiStretchRect*>( GSDevice::MultiStretchRect* drects = static_cast<GSDevice::MultiStretchRect*>(
alloca(sizeof(GSDevice::MultiStretchRect) * static_cast<u32>(m_dirty.size()))); alloca(sizeof(GSDevice::MultiStretchRect) * static_cast<u32>(m_dirty.size())));

View File

@ -728,8 +728,11 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
break; break;
case GSHWFixId::BilinearUpscale: case GSHWFixId::BilinearUpscale:
config.UserHacks_BilinearHack = (value > 0); {
break; if (value >= 0 && value < static_cast<int>(GSBilinearDirtyMode::MaxCount))
config.UserHacks_BilinearHack = static_cast<GSBilinearDirtyMode>(value);
}
break;
case GSHWFixId::NativePaletteDraw: case GSHWFixId::NativePaletteDraw:
config.UserHacks_NativePaletteDraw = (value > 0); config.UserHacks_NativePaletteDraw = (value > 0);

View File

@ -3228,6 +3228,7 @@ void FullscreenUI::DrawGraphicsSettingsPage()
static constexpr const char* s_half_pixel_offset_options[] = { static constexpr const char* s_half_pixel_offset_options[] = {
"Off (Default)", "Normal (Vertex)", "Special (Texture)", "Special (Texture - Aggressive)"}; "Off (Default)", "Normal (Vertex)", "Special (Texture)", "Special (Texture - Aggressive)"};
static constexpr const char* s_round_sprite_options[] = {"Off (Default)", "Half", "Full"}; static constexpr const char* s_round_sprite_options[] = {"Off (Default)", "Half", "Full"};
static constexpr const char* s_bilinear_dirty_options[] = {"Automatic (Default)", "Force Bilinear", "Force Nearest"};
static constexpr const char* s_auto_flush_options[] = { static constexpr const char* s_auto_flush_options[] = {
"Disabled (Default)", "Enabled (Sprites Only)", "Enabled (All Primitives)"}; "Disabled (Default)", "Enabled (Sprites Only)", "Enabled (All Primitives)"};
@ -3280,6 +3281,10 @@ void FullscreenUI::DrawGraphicsSettingsPage()
"UserHacks_HalfPixelOffset", 0, s_half_pixel_offset_options, std::size(s_half_pixel_offset_options)); "UserHacks_HalfPixelOffset", 0, s_half_pixel_offset_options, std::size(s_half_pixel_offset_options));
DrawIntListSetting(bsi, "Round Sprite", "Adjusts sprite coordinates.", "EmuCore/GS", "UserHacks_round_sprite_offset", 0, DrawIntListSetting(bsi, "Round Sprite", "Adjusts sprite coordinates.", "EmuCore/GS", "UserHacks_round_sprite_offset", 0,
s_round_sprite_options, std::size(s_round_sprite_options)); s_round_sprite_options, std::size(s_round_sprite_options));
DrawIntListSetting(bsi, "Bilinear Upscale",
"Can smooth out textures due to be bilinear filtered when upscaling. E.g. Brave sun glare.", "EmuCore/GS",
"UserHacks_BilinearHack", static_cast<int>(GSBilinearDirtyMode::Automatic),
s_bilinear_dirty_options, std::size(s_bilinear_dirty_options));
DrawIntSpinBoxSetting( DrawIntSpinBoxSetting(
bsi, "TC Offset X", "Adjusts target texture offsets.", "EmuCore/GS", "UserHacks_TCOffsetX", 0, -4096, 4096, 1); bsi, "TC Offset X", "Adjusts target texture offsets.", "EmuCore/GS", "UserHacks_TCOffsetX", 0, -4096, 4096, 1);
DrawIntSpinBoxSetting( DrawIntSpinBoxSetting(
@ -3290,10 +3295,7 @@ void FullscreenUI::DrawGraphicsSettingsPage()
"UserHacks_merge_pp_sprite", false, manual_hw_fixes); "UserHacks_merge_pp_sprite", false, manual_hw_fixes);
DrawToggleSetting(bsi, "Wild Arms Hack", DrawToggleSetting(bsi, "Wild Arms Hack",
"Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games.", "EmuCore/GS", "Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games.", "EmuCore/GS",
"UserHacks_WildHack", false, manual_hw_fixes); "UserHacks_WildHack", false, manual_hw_fixes);
DrawToggleSetting(bsi, "Bilinear Upscale",
"Can smooth out textures due to be bilinear filtered when upscaling. E.g. Brave sun glare.", "EmuCore/GS",
"UserHacks_BilinearHack", false, manual_hw_fixes);
DrawToggleSetting(bsi, "Unscaled Palette Texture Draws", "Can fix some broken effects which rely on pixel perfect precision.", DrawToggleSetting(bsi, "Unscaled Palette Texture Draws", "Can fix some broken effects which rely on pixel perfect precision.",
"EmuCore/GS", "UserHacks_NativePaletteDraw", false, manual_hw_fixes); "EmuCore/GS", "UserHacks_NativePaletteDraw", false, manual_hw_fixes);
} }

View File

@ -408,10 +408,10 @@ void ImGuiManager::DrawSettingsOverlay()
APPEND("SD={}/{} ", GSConfig.SkipDrawStart, GSConfig.SkipDrawEnd); APPEND("SD={}/{} ", GSConfig.SkipDrawStart, GSConfig.SkipDrawEnd);
if (GSConfig.UserHacks_TextureInsideRt != GSTextureInRtMode::Disabled) if (GSConfig.UserHacks_TextureInsideRt != GSTextureInRtMode::Disabled)
APPEND("TexRT={} ", static_cast<unsigned>(GSConfig.UserHacks_TextureInsideRt)); APPEND("TexRT={} ", static_cast<unsigned>(GSConfig.UserHacks_TextureInsideRt));
if (GSConfig.UserHacks_BilinearHack != GSBilinearDirtyMode::Automatic)
APPEND("BLU={}", static_cast<unsigned>(GSConfig.UserHacks_BilinearHack));
if (GSConfig.UserHacks_WildHack) if (GSConfig.UserHacks_WildHack)
APPEND("WA "); APPEND("WA ");
if (GSConfig.UserHacks_BilinearHack)
APPEND("BLU ");
if (GSConfig.UserHacks_NativePaletteDraw) if (GSConfig.UserHacks_NativePaletteDraw)
APPEND("NPD "); APPEND("NPD ");
if (GSConfig.UserHacks_MergePPSprite) if (GSConfig.UserHacks_MergePPSprite)

View File

@ -538,7 +538,7 @@ Pcsx2Config::GSOptions::GSOptions()
UserHacks_DisableRenderFixes = false; UserHacks_DisableRenderFixes = false;
UserHacks_MergePPSprite = false; UserHacks_MergePPSprite = false;
UserHacks_WildHack = false; UserHacks_WildHack = false;
UserHacks_BilinearHack = false; UserHacks_BilinearHack = GSBilinearDirtyMode::Automatic;
UserHacks_NativePaletteDraw = false; UserHacks_NativePaletteDraw = false;
DumpReplaceableTextures = false; DumpReplaceableTextures = false;
@ -625,6 +625,7 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
OpEqu(UserHacks_CPUCLUTRender) && OpEqu(UserHacks_CPUCLUTRender) &&
OpEqu(UserHacks_GPUTargetCLUTMode) && OpEqu(UserHacks_GPUTargetCLUTMode) &&
OpEqu(UserHacks_TextureInsideRt) && OpEqu(UserHacks_TextureInsideRt) &&
OpEqu(UserHacks_BilinearHack) &&
OpEqu(OverrideTextureBarriers) && OpEqu(OverrideTextureBarriers) &&
OpEqu(CAS_Sharpness) && OpEqu(CAS_Sharpness) &&
@ -758,7 +759,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
GSSettingBoolEx(UserHacks_DisableRenderFixes, "UserHacks_DisableRenderFixes"); GSSettingBoolEx(UserHacks_DisableRenderFixes, "UserHacks_DisableRenderFixes");
GSSettingBoolEx(UserHacks_MergePPSprite, "UserHacks_merge_pp_sprite"); GSSettingBoolEx(UserHacks_MergePPSprite, "UserHacks_merge_pp_sprite");
GSSettingBoolEx(UserHacks_WildHack, "UserHacks_WildHack"); GSSettingBoolEx(UserHacks_WildHack, "UserHacks_WildHack");
GSSettingBoolEx(UserHacks_BilinearHack, "UserHacks_BilinearHack"); GSSettingIntEnumEx(UserHacks_BilinearHack, "UserHacks_BilinearHack");
GSSettingBoolEx(UserHacks_NativePaletteDraw, "UserHacks_NativePaletteDraw"); GSSettingBoolEx(UserHacks_NativePaletteDraw, "UserHacks_NativePaletteDraw");
GSSettingIntEnumEx(UserHacks_TextureInsideRt, "UserHacks_TextureInsideRt"); GSSettingIntEnumEx(UserHacks_TextureInsideRt, "UserHacks_TextureInsideRt");
GSSettingBoolEx(UserHacks_TargetPartialInvalidation, "UserHacks_TargetPartialInvalidation"); GSSettingBoolEx(UserHacks_TargetPartialInvalidation, "UserHacks_TargetPartialInvalidation");
@ -877,7 +878,6 @@ void Pcsx2Config::GSOptions::MaskUserHacks()
UserHacks_AlignSpriteX = false; UserHacks_AlignSpriteX = false;
UserHacks_MergePPSprite = false; UserHacks_MergePPSprite = false;
UserHacks_WildHack = false; UserHacks_WildHack = false;
UserHacks_BilinearHack = false;
UserHacks_NativePaletteDraw = false; UserHacks_NativePaletteDraw = false;
UserHacks_DisableSafeFeatures = false; UserHacks_DisableSafeFeatures = false;
UserHacks_DisableRenderFixes = false; UserHacks_DisableRenderFixes = false;
@ -899,6 +899,7 @@ void Pcsx2Config::GSOptions::MaskUserHacks()
UserHacks_CPUSpriteRenderLevel = 0; UserHacks_CPUSpriteRenderLevel = 0;
UserHacks_CPUCLUTRender = 0; UserHacks_CPUCLUTRender = 0;
UserHacks_GPUTargetCLUTMode = GSGPUTargetCLUTMode::Disabled; UserHacks_GPUTargetCLUTMode = GSGPUTargetCLUTMode::Disabled;
UserHacks_BilinearHack = GSBilinearDirtyMode::Automatic;
SkipDrawStart = 0; SkipDrawStart = 0;
SkipDrawEnd = 0; SkipDrawEnd = 0;
} }
@ -911,7 +912,7 @@ void Pcsx2Config::GSOptions::MaskUpscalingHacks()
UserHacks_AlignSpriteX = false; UserHacks_AlignSpriteX = false;
UserHacks_MergePPSprite = false; UserHacks_MergePPSprite = false;
UserHacks_WildHack = false; UserHacks_WildHack = false;
UserHacks_BilinearHack = false; UserHacks_BilinearHack = GSBilinearDirtyMode::Automatic;
UserHacks_NativePaletteDraw = false; UserHacks_NativePaletteDraw = false;
UserHacks_HalfPixelOffset = 0; UserHacks_HalfPixelOffset = 0;
UserHacks_RoundSprite = 0; UserHacks_RoundSprite = 0;