GS-HW: Don't bilinear dirty rects by default, added as upscale hack.

This commit is contained in:
refractionpcsx2 2023-03-16 02:50:59 +00:00
parent fa439a465d
commit 2b49614df9
13 changed files with 47 additions and 7 deletions

View File

@ -3448,6 +3448,7 @@ SCES-51635:
halfPixelOffset: 2 # Fixes lighting/shadows. halfPixelOffset: 2 # Fixes lighting/shadows.
preloadFrameData: 1 # Fixes sun flickering. preloadFrameData: 1 # Fixes sun flickering.
autoFlush: 1 # Fixes sun through objects. autoFlush: 1 # Fixes sun through objects.
bilinearUpscale: 1 # Smooths out sun glare textures like native.
SCES-51648: SCES-51648:
name: "Everquest - Online Adventures" name: "Everquest - Online Adventures"
region: "PAL-E-I" region: "PAL-E-I"
@ -46538,6 +46539,7 @@ SLUS-21127:
halfPixelOffset: 2 # Fixes lighting/shadows. halfPixelOffset: 2 # Fixes lighting/shadows.
preloadFrameData: 1 # Fixes sun flickering. preloadFrameData: 1 # Fixes sun flickering.
autoFlush: 1 # Fixes sun through objects. autoFlush: 1 # Fixes sun through objects.
bilinearUpscale: 1 # Smooths out sun glare textures like native.
SLUS-21128: SLUS-21128:
name: "Blitz - The League" name: "Blitz - The League"
region: "NTSC-U" region: "NTSC-U"

View File

@ -224,7 +224,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
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);
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Texture Replacements // Texture Replacements
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -587,6 +587,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
dialog->registerWidgetHelp(m_ui.wildHack, tr("Wild Arms Hack"), tr("Unchecked"), dialog->registerWidgetHelp(m_ui.wildHack, tr("Wild Arms Hack"), tr("Unchecked"),
tr("Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games.")); tr("Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games."));
dialog->registerWidgetHelp(m_ui.bilinearHack, tr("Bilinear Upscale"), tr("Unchecked"),
tr("Can smooth out textures due to be bilinear filtered when upscaling. E.g. Brave sun glare."));
dialog->registerWidgetHelp(m_ui.mergeSprite, tr("Merge Sprite"), tr("Unchecked"), dialog->registerWidgetHelp(m_ui.mergeSprite, tr("Merge Sprite"), tr("Unchecked"),
tr("Replaces post-processing multiple paving sprites by a single fat sprite. It reduces various upscaling lines.")); tr("Replaces post-processing multiple paving sprites by a single fat sprite. It reduces various upscaling lines."));
} }
@ -1075,6 +1078,7 @@ void GraphicsSettingsWidget::resetManualHardwareFixes()
check_bool("EmuCore/GS", "UserHacks_align_sprite_X", false); check_bool("EmuCore/GS", "UserHacks_align_sprite_X", false);
check_bool("EmuCore/GS", "UserHacks_merge_pp_sprite", false); check_bool("EmuCore/GS", "UserHacks_merge_pp_sprite", false);
check_bool("EmuCore/GS", "UserHacks_WildHack", false); check_bool("EmuCore/GS", "UserHacks_WildHack", false);
check_bool("EmuCore/GS", "UserHacks_BilinearHack", false);
} }
if (changed) if (changed)

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>720</width> <width>720</width>
<height>466</height> <height>476</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -58,7 +58,7 @@
<item> <item>
<widget class="QTabWidget" name="tabs"> <widget class="QTabWidget" name="tabs">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>4</number>
</property> </property>
<property name="documentMode"> <property name="documentMode">
<bool>true</bool> <bool>true</bool>
@ -1222,6 +1222,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QCheckBox" name="bilinearHack">
<property name="text">
<string>Bilinear Dirty Upscale</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View File

@ -677,6 +677,7 @@ struct Pcsx2Config
UserHacks_DisableSafeFeatures : 1, UserHacks_DisableSafeFeatures : 1,
UserHacks_MergePPSprite : 1, UserHacks_MergePPSprite : 1,
UserHacks_WildHack : 1, UserHacks_WildHack : 1,
UserHacks_BilinearHack : 1,
UserHacks_TargetPartialInvalidation : 1, UserHacks_TargetPartialInvalidation : 1,
UserHacks_EstimateTextureRegion : 1, UserHacks_EstimateTextureRegion : 1,
FXAA : 1, FXAA : 1,

View File

@ -169,6 +169,7 @@ The clamp modes are also numerically based.
* alignSprite [`0` or `1`] {Off or On} Default: Off (`0`) * alignSprite [`0` or `1`] {Off or On} Default: Off (`0`)
* mergeSprite [`0` or `1`] {Off or On} Default: Off (`0`) * mergeSprite [`0` or `1`] {Off or On} Default: Off (`0`)
* wildArmsHack [`0` or `1`] {Off or On} Default: Off (`0`) * wildArmsHack [`0` or `1`] {Off or On} Default: Off (`0`)
* bilinearUpscale [`0` or `1`] {Off or On} Default: Off (`0`)
* skipDrawStart [Value between `0` to `10000`] {0-10000} Default: Off (`0`) * skipDrawStart [Value between `0` to `10000`] {0-10000} Default: Off (`0`)
* skipDrawEnd [Value between `0` to `10000`] {0-10000} Default: Off (`0`) * skipDrawEnd [Value between `0` to `10000`] {0-10000} Default: Off (`0`)
* halfPixelOffset [`0` or `1` or `2` or `3`] {Off, Normal Vertex, Special Texture or Special Texture Aggressive} Default: Off (`0`) * halfPixelOffset [`0` or `1` or `2` or `3`] {Off, Normal Vertex, Special Texture or Special Texture Aggressive} Default: Off (`0`)

View File

@ -171,6 +171,11 @@
"minimum": 0, "minimum": 0,
"maximum": 1 "maximum": 1
}, },
"bilinearUpscale": {
"type": "integer",
"minimum": 0,
"maximum": 1
},
"estimateTextureRegion": { "estimateTextureRegion": {
"type": "integer", "type": "integer",
"minimum": 0, "minimum": 0,

View File

@ -3234,6 +3234,9 @@ void FullscreenUI::DrawGraphicsSettingsPage()
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);
} }
} }

View File

@ -415,6 +415,8 @@ void ImGuiManager::DrawSettingsOverlay()
APPEND("TexRT={} ", static_cast<int>(GSConfig.UserHacks_TextureInsideRt)); APPEND("TexRT={} ", static_cast<int>(GSConfig.UserHacks_TextureInsideRt));
if (GSConfig.UserHacks_WildHack) if (GSConfig.UserHacks_WildHack)
APPEND("WA "); APPEND("WA ");
if (GSConfig.UserHacks_BilinearHack)
APPEND("BLU ");
if (GSConfig.UserHacks_MergePPSprite) if (GSConfig.UserHacks_MergePPSprite)
APPEND("MS "); APPEND("MS ");
if (GSConfig.UserHacks_AlignSpriteX) if (GSConfig.UserHacks_AlignSpriteX)

View File

@ -1426,14 +1426,14 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
GL_INS("Preloading the RT DATA"); GL_INS("Preloading the RT DATA");
eerect = eerect.rintersect(newrect); eerect = eerect.rintersect(newrect);
dst->UpdateValidity(newrect); dst->UpdateValidity(newrect);
AddDirtyRectTarget(dst, eerect, TEX0.PSM, TEX0.TBW, rgba/*, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16*/); AddDirtyRectTarget(dst, eerect, TEX0.PSM, TEX0.TBW, rgba, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16);
} }
} }
else else
{ {
GL_INS("Preloading the RT DATA"); GL_INS("Preloading the RT DATA");
dst->UpdateValidity(newrect); dst->UpdateValidity(newrect);
AddDirtyRectTarget(dst, newrect, TEX0.PSM, TEX0.TBW, rgba/*, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16*/); AddDirtyRectTarget(dst, newrect, TEX0.PSM, TEX0.TBW, rgba, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16);
} }
} }
dst->m_is_frame = is_frame; dst->m_is_frame = is_frame;
@ -4313,6 +4313,7 @@ void GSTextureCache::Target::Update(bool reset_age)
// 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 linear = (m_type == RenderTarget && upscaled); const bool linear = (m_type == RenderTarget && upscaled);
GSDevice::MultiStretchRect* drects = static_cast<GSDevice::MultiStretchRect*>( GSDevice::MultiStretchRect* drects = static_cast<GSDevice::MultiStretchRect*>(
@ -4344,7 +4345,8 @@ void GSTextureCache::Target::Update(bool reset_age)
drect.src = t; drect.src = t;
drect.src_rect = GSVector4(r - t_offset) / t_sizef; drect.src_rect = GSVector4(r - t_offset) / t_sizef;
drect.dst_rect = GSVector4(r) * GSVector4(m_scale); drect.dst_rect = GSVector4(r) * GSVector4(m_scale);
drect.linear = linear && m_dirty[i].req_linear; drect.linear = linear && (m_dirty[i].req_linear || override_linear);
// Copy the new GS memory content into the destination texture. // Copy the new GS memory content into the destination texture.
if (m_type == RenderTarget) if (m_type == RenderTarget)
{ {

View File

@ -421,7 +421,7 @@ public:
void Read(Source* t, const GSVector4i& r); void Read(Source* t, const GSVector4i& r);
void RemoveAll(); void RemoveAll();
void ReadbackAll(); void ReadbackAll();
void AddDirtyRectTarget(Target* target, GSVector4i rect, u32 psm, u32 bw, RGBAMask rgba, bool req_linear = true); void AddDirtyRectTarget(Target* target, GSVector4i rect, u32 psm, u32 bw, RGBAMask rgba, bool req_linear = false);
bool CanTranslate(u32 bp, u32 bw, u32 spsm, GSVector4i r, u32 dbp, u32 dpsm, u32 dbw); bool CanTranslate(u32 bp, u32 bw, u32 spsm, GSVector4i r, u32 dbp, u32 dpsm, u32 dbw);
GSVector4i TranslateAlignedRectByPage(u32 sbp, u32 spsm, u32 sbw, GSVector4i src_r, u32 dbp, u32 dpsm, u32 bw, bool is_invalidation = false); GSVector4i TranslateAlignedRectByPage(u32 sbp, u32 spsm, u32 sbw, GSVector4i src_r, u32 dbp, u32 dpsm, u32 bw, bool is_invalidation = false);
void DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVector4i src_r, u32 dbp, u32 dpsm, u32 bw); void DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVector4i src_r, u32 dbp, u32 dpsm, u32 bw);

View File

@ -352,6 +352,7 @@ static const char* s_gs_hw_fix_names[] = {
"alignSprite", "alignSprite",
"mergeSprite", "mergeSprite",
"wildArmsHack", "wildArmsHack",
"bilinearUpscale",
"estimateTextureRegion", "estimateTextureRegion",
"PCRTCOffsets", "PCRTCOffsets",
"PCRTCOverscan", "PCRTCOverscan",
@ -588,6 +589,9 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
case GSHWFixId::WildArmsHack: case GSHWFixId::WildArmsHack:
return (config.UpscaleMultiplier <= 1.0f || static_cast<int>(config.UserHacks_WildHack) == value); return (config.UpscaleMultiplier <= 1.0f || static_cast<int>(config.UserHacks_WildHack) == value);
case GSHWFixId::BilinearUpscale:
return (config.UpscaleMultiplier <= 1.0f || static_cast<int>(config.UserHacks_BilinearHack) == value);
case GSHWFixId::EstimateTextureRegion: case GSHWFixId::EstimateTextureRegion:
return (static_cast<int>(config.UserHacks_EstimateTextureRegion) == value); return (static_cast<int>(config.UserHacks_EstimateTextureRegion) == value);
@ -727,6 +731,10 @@ u32 GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
config.UserHacks_WildHack = (value > 0); config.UserHacks_WildHack = (value > 0);
break; break;
case GSHWFixId::BilinearUpscale:
config.UserHacks_BilinearHack = (value > 0);
break;
case GSHWFixId::EstimateTextureRegion: case GSHWFixId::EstimateTextureRegion:
config.UserHacks_EstimateTextureRegion = (value > 0); config.UserHacks_EstimateTextureRegion = (value > 0);
break; break;

View File

@ -71,6 +71,7 @@ namespace GameDatabaseSchema
AlignSprite, AlignSprite,
MergeSprite, MergeSprite,
WildArmsHack, WildArmsHack,
BilinearUpscale,
EstimateTextureRegion, EstimateTextureRegion,
PCRTCOffsets, PCRTCOffsets,
PCRTCOverscan, PCRTCOverscan,

View File

@ -443,6 +443,7 @@ Pcsx2Config::GSOptions::GSOptions()
UserHacks_DisableSafeFeatures = false; UserHacks_DisableSafeFeatures = false;
UserHacks_MergePPSprite = false; UserHacks_MergePPSprite = false;
UserHacks_WildHack = false; UserHacks_WildHack = false;
UserHacks_BilinearHack = false;
DumpReplaceableTextures = false; DumpReplaceableTextures = false;
DumpReplaceableMipmaps = false; DumpReplaceableMipmaps = false;
@ -656,6 +657,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
GSSettingBoolEx(UserHacks_DisableSafeFeatures, "UserHacks_Disable_Safe_Features"); GSSettingBoolEx(UserHacks_DisableSafeFeatures, "UserHacks_Disable_Safe_Features");
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_TextureInsideRt, "UserHacks_TextureInsideRt"); GSSettingIntEnumEx(UserHacks_TextureInsideRt, "UserHacks_TextureInsideRt");
GSSettingBoolEx(UserHacks_TargetPartialInvalidation, "UserHacks_TargetPartialInvalidation"); GSSettingBoolEx(UserHacks_TargetPartialInvalidation, "UserHacks_TargetPartialInvalidation");
GSSettingBoolEx(UserHacks_EstimateTextureRegion, "UserHacks_EstimateTextureRegion"); GSSettingBoolEx(UserHacks_EstimateTextureRegion, "UserHacks_EstimateTextureRegion");
@ -773,6 +775,7 @@ 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_DisableSafeFeatures = false; UserHacks_DisableSafeFeatures = false;
UserHacks_HalfBottomOverride = -1; UserHacks_HalfBottomOverride = -1;
UserHacks_HalfPixelOffset = 0; UserHacks_HalfPixelOffset = 0;
@ -803,6 +806,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_HalfPixelOffset = 0; UserHacks_HalfPixelOffset = 0;
UserHacks_RoundSprite = 0; UserHacks_RoundSprite = 0;
UserHacks_TCOffsetX = 0; UserHacks_TCOffsetX = 0;