GS/HW: Make readback-on-close a HW fix

Unfortunately it's too risky to enable by default all the time. So,
we'll make it a hw fix, and hopefully one day can make it default on.

Also makes save states readback the TC as well.
This commit is contained in:
Stenzek 2023-02-23 21:00:48 +10:00 committed by refractionpcsx2
parent 2487322e47
commit f9dcac8cd0
19 changed files with 96 additions and 37 deletions

View File

@ -12860,6 +12860,8 @@ SLES-51504:
SLES-51507:
name: "Futurama"
region: "PAL-M5"
gsHWFixes:
readTCOnClose: 1 # Fixes render to target getting lost on state/switch.
SLES-51508:
name: "Hulk, The"
region: "PAL-M5"
@ -42646,6 +42648,8 @@ SLUS-20439:
name: "Futurama"
region: "NTSC-U"
compat: 5
gsHWFixes:
readTCOnClose: 1 # Fixes render to target getting lost on state/switch.
SLUS-20440:
name: "Kya - Dark Lineage"
region: "NTSC-U"

View File

@ -198,6 +198,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(
sif, m_ui.disablePartialInvalidation, "EmuCore/GS", "UserHacks_DisablePartialInvalidation", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.textureInsideRt, "EmuCore/GS", "UserHacks_TextureInsideRt", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.readTCOnClose, "EmuCore/GS", "UserHacks_ReadTCOnClose", false);
//////////////////////////////////////////////////////////////////////////
// HW Upscaling Fixes
@ -537,6 +538,10 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
dialog->registerWidgetHelp(m_ui.textureInsideRt, tr("Texture Inside RT"), tr("Unchecked"),
tr("Allows the texture cache to reuse as an input texture the inner portion of a previous framebuffer. "
"In some selected games this is enabled by default regardless of this setting."));
dialog->registerWidgetHelp(m_ui.readTCOnClose, tr("Read Targets When Closing"), tr("Unchecked"),
tr("Flushes all targets in the texture cache back to local memory when shutting down. Can prevent lost visuals when saving "
"state or switching renderers, but can also cause graphical corruption."));
}
// Upscaling Fixes tab

View File

@ -947,13 +947,6 @@
</item>
<item row="5" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="hwAutoFlush">
<property name="text">
<string>Auto Flush</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="frameBufferConversion">
<property name="text">
@ -961,6 +954,13 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="hwAutoFlush">
<property name="text">
<string>Auto Flush</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="disableDepthEmulation">
<property name="text">
@ -968,10 +968,10 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="disableSafeFeatures">
<item row="1" column="1">
<widget class="QCheckBox" name="preloadFrameData">
<property name="text">
<string>Disable Safe Features</string>
<string>Preload Frame Data</string>
</property>
</widget>
</item>
@ -982,10 +982,10 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="preloadFrameData">
<item row="2" column="0">
<widget class="QCheckBox" name="disableSafeFeatures">
<property name="text">
<string>Preload Frame Data</string>
<string>Disable Safe Features</string>
</property>
</widget>
</item>
@ -996,6 +996,13 @@
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="readTCOnClose">
<property name="text">
<string>Read Targets When Closing</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">

View File

@ -664,6 +664,7 @@ struct Pcsx2Config
UserHacks_AlignSpriteX : 1,
UserHacks_AutoFlush : 1,
UserHacks_CPUFBConversion : 1,
UserHacks_ReadTCOnClose : 1,
UserHacks_DisableDepthSupport : 1,
UserHacks_DisablePartialInvalidation : 1,
UserHacks_DisableSafeFeatures : 1,

View File

@ -126,6 +126,11 @@
"minimum": 0,
"maximum": 1
},
"readTCOnClose": {
"type": "integer",
"minimum": 0,
"maximum": 1
},
"disableDepthSupport": {
"type": "integer",
"minimum": 0,

View File

@ -3196,6 +3196,9 @@ void FullscreenUI::DrawGraphicsSettingsPage()
DrawToggleSetting(bsi, "Texture Inside Render Target",
"Allows the texture cache to reuse as an input texture the inner portion of a previous framebuffer.", "EmuCore/GS",
"UserHacks_TextureInsideRt", false, manual_hw_fixes);
DrawToggleSetting(bsi, "Read Targets When Closing",
"Flushes all targets in the texture cache back to local memory when shutting down.", "EmuCore/GS",
"UserHacks_ReadTCOnClose", false, manual_hw_fixes);
MenuHeading("Upscaling Fixes");
DrawIntListSetting(bsi, "Half-Pixel Offset", "Adjusts vertices relative to upscaling.", "EmuCore/GS",

View File

@ -421,6 +421,8 @@ void ImGuiManager::DrawSettingsOverlay()
APPEND("AF ");
if (GSConfig.UserHacks_CPUFBConversion)
APPEND("FBC ");
if (GSConfig.UserHacks_ReadTCOnClose)
APPEND("FTC ");
if(GSConfig.UserHacks_DisableDepthSupport)
APPEND("DDE ");
if (GSConfig.UserHacks_DisablePartialInvalidation)

View File

@ -252,6 +252,9 @@ bool GSreopen(bool recreate_display, bool recreate_renderer, const Pcsx2Config::
if (recreate_renderer)
g_gs_renderer->Flush(GSState::GSFlushReason::GSREOPEN);
if (GSConfig.UserHacks_ReadTCOnClose)
g_gs_renderer->ReadbackTextureCache();
freezeData fd = {};
std::unique_ptr<u8[]> fd_data;
if (recreate_renderer)
@ -273,8 +276,8 @@ bool GSreopen(bool recreate_display, bool recreate_renderer, const Pcsx2Config::
else
{
// Make sure nothing is left over.
g_gs_renderer->PurgePool();
g_gs_renderer->PurgeTextureCache();
g_gs_renderer->PurgePool();
}
if (recreate_display)
@ -762,6 +765,8 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
GSConfig.UserHacks_CPUCLUTRender != old_config.UserHacks_CPUCLUTRender ||
GSConfig.UserHacks_GPUTargetCLUTMode != old_config.UserHacks_GPUTargetCLUTMode)
{
if (GSConfig.UserHacks_ReadTCOnClose)
g_gs_renderer->ReadbackTextureCache();
g_gs_renderer->PurgeTextureCache();
g_gs_renderer->PurgePool();
}
@ -800,8 +805,6 @@ void GSSwitchRenderer(GSRendererType new_renderer)
if (existing_api == RenderAPI::OpenGLES)
existing_api = RenderAPI::OpenGL;
g_gs_renderer->PurgeTextureCache();
const bool is_software_switch = (new_renderer == GSRendererType::SW || GSConfig.Renderer == GSRendererType::SW);
const bool recreate_display = (!is_software_switch && existing_api != GetAPIForRenderer(new_renderer));
const Pcsx2Config::GSOptions old_config(GSConfig);

View File

@ -2126,6 +2126,19 @@ void GSState::ReadLocalMemoryUnsync(u8* mem, int qwc, GIFRegBITBLTBUF BITBLTBUF,
m_mem.ReadImageX(tb.x, tb.y, mem, len, BITBLTBUF, TRXPOS, TRXREG);
}
void GSState::PurgePool()
{
g_gs_device->PurgePool();
}
void GSState::PurgeTextureCache()
{
}
void GSState::ReadbackTextureCache()
{
}
template void GSState::Transfer<0>(const u8* mem, u32 size);
template void GSState::Transfer<1>(const u8* mem, u32 size);
template void GSState::Transfer<2>(const u8* mem, u32 size);
@ -2345,6 +2358,9 @@ int GSState::Freeze(freezeData* fd, bool sizeonly)
Flush(GSFlushReason::SAVESTATE);
if (GSConfig.UserHacks_ReadTCOnClose)
ReadbackTextureCache();
u8* data = fd->data;
const u32 version = STATE_VERSION;

View File

@ -886,7 +886,9 @@ public:
bool TestDrawChanged();
void FlushWrite();
virtual void Draw() = 0;
virtual void PurgePool() = 0;
virtual void PurgePool();
virtual void PurgeTextureCache();
virtual void ReadbackTextureCache();
virtual void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool eewrite = false) {}
virtual void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut = false) {}
virtual void ExpandTarget(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) {}

View File

@ -829,15 +829,6 @@ void GSRenderer::EndCapture()
GSCapture::EndCapture();
}
void GSRenderer::PurgePool()
{
g_gs_device->PurgePool();
}
void GSRenderer::PurgeTextureCache()
{
}
GSTexture* GSRenderer::LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, const GSVector2i& size)
{
return nullptr;

View File

@ -53,9 +53,6 @@ public:
virtual GSVector2 GetTextureScaleFactor() { return { 1.0f, 1.0f }; }
GSVector2i GetInternalResolution();
virtual void PurgePool() override;
virtual void PurgeTextureCache();
virtual GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, const GSVector2i& size);
bool SaveSnapshotToMemory(u32 window_width, u32 window_height, bool apply_aspect, bool crop_borders,

View File

@ -71,8 +71,12 @@ void GSRendererHW::Destroy()
void GSRendererHW::PurgeTextureCache()
{
GSRenderer::PurgeTextureCache();
m_tc->RemoveAll(true);
m_tc->RemoveAll();
}
void GSRendererHW::ReadbackTextureCache()
{
m_tc->ReadbackAll();
}
GSTexture* GSRendererHW::LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, const GSVector2i& size)

View File

@ -166,6 +166,7 @@ public:
void Draw() override;
void PurgeTextureCache() override;
void ReadbackTextureCache() override;
GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, const GSVector2i& size) override;
// Called by the texture cache to know if current texture is useful

View File

@ -46,18 +46,23 @@ GSTextureCache::~GSTextureCache()
_aligned_free(s_unswizzle_buffer);
}
void GSTextureCache::RemoveAll(bool readback_targets)
void GSTextureCache::ReadbackAll()
{
for (int type = 0; type < 2; type++)
{
for (auto t : m_dst[type])
Read(t, t->m_drawn_since_read);
}
}
void GSTextureCache::RemoveAll()
{
m_src.RemoveAll();
for (int type = 0; type < 2; type++)
{
for (auto t : m_dst[type])
{
if (readback_targets)
Read(t, t->m_drawn_since_read);
delete t;
}
m_dst[type].clear();
}

View File

@ -406,7 +406,8 @@ public:
void Read(Target* t, const GSVector4i& r);
void Read(Source* t, const GSVector4i& r);
void RemoveAll(bool readback_targets = false);
void RemoveAll();
void ReadbackAll();
void AddDirtyRectTarget(Target* target, GSVector4i rect, u32 psm, u32 bw);
GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, const GSVector2i& size);

View File

@ -342,6 +342,7 @@ void GameDatabase::parseAndInsert(const std::string_view& serial, const c4::yml:
static const char* s_gs_hw_fix_names[] = {
"autoFlush",
"cpuFramebufferConversion",
"readTCOnClose",
"disableDepthSupport",
"wrapGSMem",
"preloadFrameData",
@ -548,6 +549,9 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
case GSHWFixId::CPUFramebufferConversion:
return (static_cast<int>(config.UserHacks_CPUFBConversion) == value);
case GSHWFixId::FlushTCOnClose:
return (static_cast<int>(config.UserHacks_ReadTCOnClose) == value);
case GSHWFixId::DisableDepthSupport:
return (static_cast<int>(config.UserHacks_DisableDepthSupport) == value);
@ -654,6 +658,10 @@ u32 GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
config.UserHacks_CPUFBConversion = (value > 0);
break;
case GSHWFixId::FlushTCOnClose:
config.UserHacks_ReadTCOnClose = (value > 0);
break;
case GSHWFixId::DisableDepthSupport:
config.UserHacks_DisableDepthSupport = (value > 0);
break;

View File

@ -62,6 +62,7 @@ namespace GameDatabaseSchema
// boolean settings
AutoFlush,
CPUFramebufferConversion,
FlushTCOnClose,
DisableDepthSupport,
WrapGSMem,
PreloadFrameData,

View File

@ -429,6 +429,7 @@ Pcsx2Config::GSOptions::GSOptions()
UserHacks_AlignSpriteX = false;
UserHacks_AutoFlush = false;
UserHacks_CPUFBConversion = false;
UserHacks_ReadTCOnClose = false;
UserHacks_DisableDepthSupport = false;
UserHacks_DisablePartialInvalidation = false;
UserHacks_DisableSafeFeatures = false;
@ -640,6 +641,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
GSSettingBoolEx(UserHacks_AlignSpriteX, "UserHacks_align_sprite_X");
GSSettingBoolEx(UserHacks_AutoFlush, "UserHacks_AutoFlush");
GSSettingBoolEx(UserHacks_CPUFBConversion, "UserHacks_CPU_FB_Conversion");
GSSettingBoolEx(UserHacks_ReadTCOnClose, "UserHacks_ReadTCOnClose");
GSSettingBoolEx(UserHacks_DisableDepthSupport, "UserHacks_DisableDepthSupport");
GSSettingBoolEx(UserHacks_DisablePartialInvalidation, "UserHacks_DisablePartialInvalidation");
GSSettingBoolEx(UserHacks_DisableSafeFeatures, "UserHacks_Disable_Safe_Features");
@ -770,6 +772,7 @@ void Pcsx2Config::GSOptions::MaskUserHacks()
UserHacks_DisablePartialInvalidation = false;
UserHacks_DisableDepthSupport = false;
UserHacks_CPUFBConversion = false;
UserHacks_ReadTCOnClose = false;
UserHacks_TextureInsideRt = false;
UserHacks_TCOffsetX = 0;
UserHacks_TCOffsetY = 0;