mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
2487322e47
commit
f9dcac8cd0
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -126,6 +126,11 @@
|
|||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"readTCOnClose": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"disableDepthSupport": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace GameDatabaseSchema
|
|||
// boolean settings
|
||||
AutoFlush,
|
||||
CPUFramebufferConversion,
|
||||
FlushTCOnClose,
|
||||
DisableDepthSupport,
|
||||
WrapGSMem,
|
||||
PreloadFrameData,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue