GS: Add hardware download mode option

This commit is contained in:
Connor McLaughlin 2022-06-06 21:01:31 +10:00 committed by refractionpcsx2
parent 0b09c259aa
commit cb1817f440
7 changed files with 88 additions and 46 deletions

View File

@ -245,7 +245,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.gsDumpCompression, "EmuCore/GS", "GSDumpCompression", static_cast<int>(GSDumpCompressionMethod::LZMA)); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.gsDumpCompression, "EmuCore/GS", "GSDumpCompression", static_cast<int>(GSDumpCompressionMethod::LZMA));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableFramebufferFetch, "EmuCore/GS", "DisableFramebufferFetch", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableFramebufferFetch, "EmuCore/GS", "DisableFramebufferFetch", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableDualSource, "EmuCore/GS", "DisableDualSourceBlend", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableDualSource, "EmuCore/GS", "DisableDualSourceBlend", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableHardwareReadbacks, "EmuCore/GS", "HWDisableReadbacks", false); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.gsDownloadMode, "EmuCore/GS", "HWDownloadMode", static_cast<int>(GSHardwareDownloadMode::Enabled));
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// SW Settings // SW Settings
@ -290,9 +290,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
connect(m_ui.swTextureFiltering, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onSWTextureFilteringChange); connect(m_ui.swTextureFiltering, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onSWTextureFilteringChange);
updateRendererDependentOptions(); updateRendererDependentOptions();
// only allow disabling readbacks for per-game settings, it's too dangerous
#ifndef PCSX2_DEVBUILD #ifndef PCSX2_DEVBUILD
m_ui.disableHardwareReadbacks->setEnabled(m_dialog->isPerGameSettings()); // only allow disabling readbacks for per-game settings, it's too dangerous
m_ui.gsDownloadMode->setEnabled(m_dialog->isPerGameSettings());
// Remove texture offset and skipdraw range for global settings. // Remove texture offset and skipdraw range for global settings.
if (!m_dialog->isPerGameSettings()) if (!m_dialog->isPerGameSettings())
@ -477,7 +477,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
"the GPU has more time to complete it (this is NOT frame skipping). Can smooth our frame time fluctuations when the CPU/GPU are near maximum " "the GPU has more time to complete it (this is NOT frame skipping). Can smooth our frame time fluctuations when the CPU/GPU are near maximum "
"utilization, but makes frame pacing more inconsistent and can increase input lag.")); "utilization, but makes frame pacing more inconsistent and can increase input lag."));
dialog->registerWidgetHelp(m_ui.disableHardwareReadbacks, tr("Disable Hardware Readbacks"), tr("Unchecked"), dialog->registerWidgetHelp(m_ui.gsDownloadMode, tr("GS Download Mode"), tr("Accurate"),
tr("Skips synchronizing with the GS thread and host GPU for GS downloads. " tr("Skips synchronizing with the GS thread and host GPU for GS downloads. "
"Can result in a large speed boost on slower systems, at the cost of many broken graphical effects. " "Can result in a large speed boost on slower systems, at the cost of many broken graphical effects. "
"If games are broken and you have this option enabled, please disable it first.")); "If games are broken and you have this option enabled, please disable it first."));

View File

@ -1429,8 +1429,15 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2"> <item row="5" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_7"> <layout class="QGridLayout" name="gridLayout_7">
<item row="2" column="0">
<widget class="QCheckBox" name="skipPresentingDuplicateFrames">
<property name="text">
<string>Skip Presenting Duplicate Frames</string>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QCheckBox" name="useBlitSwapChain"> <widget class="QCheckBox" name="useBlitSwapChain">
<property name="text"> <property name="text">
@ -1438,6 +1445,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QCheckBox" name="disableFramebufferFetch">
<property name="text">
<string>Disable Framebuffer Fetch</string>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QCheckBox" name="useDebugDevice"> <widget class="QCheckBox" name="useDebugDevice">
<property name="text"> <property name="text">
@ -1452,37 +1466,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QCheckBox" name="disableFramebufferFetch">
<property name="text">
<string>Disable Framebuffer Fetch</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="skipPresentingDuplicateFrames">
<property name="text">
<string>Skip Presenting Duplicate Frames</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="disableHardwareReadbacks">
<property name="text">
<string>Disable Hardware Readbacks</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label_34"> <widget class="QLabel" name="label_34">
<property name="text"> <property name="text">
<string>GS Dump Compression:</string> <string>GS Dump Compression:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="3" column="1">
<widget class="QComboBox" name="gsDumpCompression"> <widget class="QComboBox" name="gsDumpCompression">
<item> <item>
<property name="text"> <property name="text">
@ -1501,6 +1494,37 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="label_42">
<property name="text">
<string>Hardware Download Mode:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="gsDownloadMode">
<item>
<property name="text">
<string>Accurate (Recommended)</string>
</property>
</item>
<item>
<property name="text">
<string>Disable Readbacks (Synchronize GS Thread)</string>
</property>
</item>
<item>
<property name="text">
<string>Unsynchronized (Non-Deterministic)</string>
</property>
</item>
<item>
<property name="text">
<string>Disabled (Ignore Transfers)</string>
</property>
</item>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -199,6 +199,14 @@ enum class GSDumpCompressionMethod : u8
Zstandard, Zstandard,
}; };
enum class GSHardwareDownloadMode : u8
{
Enabled,
NoReadbacks,
Unsynchronized,
Disabled
};
// 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)
@ -488,7 +496,6 @@ struct Pcsx2Config
OsdShowInputs : 1; OsdShowInputs : 1;
bool bool
HWDisableReadbacks : 1,
GPUPaletteConversion : 1, GPUPaletteConversion : 1,
AutoFlushSW : 1, AutoFlushSW : 1,
PreloadFrameWithGSData : 1, PreloadFrameWithGSData : 1,
@ -561,6 +568,7 @@ struct Pcsx2Config
BiFiltering TextureFiltering{BiFiltering::PS2}; BiFiltering TextureFiltering{BiFiltering::PS2};
TexturePreloadingLevel TexturePreloading{TexturePreloadingLevel::Full}; TexturePreloadingLevel TexturePreloading{TexturePreloadingLevel::Full};
GSDumpCompressionMethod GSDumpCompression{GSDumpCompressionMethod::LZMA}; GSDumpCompressionMethod GSDumpCompression{GSDumpCompressionMethod::LZMA};
GSHardwareDownloadMode HWDownloadMode{GSHardwareDownloadMode::Enabled};
int Dithering{2}; int Dithering{2};
int MaxAnisotropy{0}; int MaxAnisotropy{0};
int SWExtraThreads{2}; int SWExtraThreads{2};

View File

@ -2579,6 +2579,8 @@ void FullscreenUI::DrawGraphicsSettingsPage()
static constexpr const char* s_anisotropic_filtering_values[] = {"0", "2", "4", "8", "16"}; static constexpr const char* s_anisotropic_filtering_values[] = {"0", "2", "4", "8", "16"};
static constexpr const char* s_preloading_options[] = {"None", "Partial", "Full (Hash Cache)"}; static constexpr const char* s_preloading_options[] = {"None", "Partial", "Full (Hash Cache)"};
static constexpr const char* s_generic_options[] = {"Automatic (Default)", "Force Disabled", "Force Enabled"}; static constexpr const char* s_generic_options[] = {"Automatic (Default)", "Force Disabled", "Force Enabled"};
static constexpr const char* s_hw_download[] = {"Accurate (Recommended)", "Disable Readbacks (Synchronize GS Thread)",
"Unsynchronized (Non-Deterministic)", "Disabled (Ignore Transfers)"};
SettingsInterface* bsi = GetEditingSettingsInterface(); SettingsInterface* bsi = GetEditingSettingsInterface();
@ -2654,6 +2656,8 @@ void FullscreenUI::DrawGraphicsSettingsPage()
"Uploads full textures to the GPU on use, rather than only the utilized regions. Can improve performance in some games.", "Uploads full textures to the GPU on use, rather than only the utilized regions. Can improve performance in some games.",
"EmuCore/GS", "texture_preloading", static_cast<int>(TexturePreloadingLevel::Off), s_preloading_options, "EmuCore/GS", "texture_preloading", static_cast<int>(TexturePreloadingLevel::Off), s_preloading_options,
std::size(s_preloading_options)); std::size(s_preloading_options));
DrawIntListSetting(bsi, "Hardware Download Mode", "Changes synchronization behavior for GS downloads.", "EmuCore/GS", "HWDownloadMode",
static_cast<int>(GSHardwareDownloadMode::Enabled), s_hw_download, std::size(s_hw_download));
DrawToggleSetting(bsi, "GPU Palette Conversion", DrawToggleSetting(bsi, "GPU Palette Conversion",
"Applies palettes to textures on the GPU instead of the CPU. Can result in speed improvements in some games.", "EmuCore/GS", "Applies palettes to textures on the GPU instead of the CPU. Can result in speed improvements in some games.", "EmuCore/GS",
"paltex", false); "paltex", false);
@ -2780,9 +2784,6 @@ void FullscreenUI::DrawGraphicsSettingsPage()
DrawToggleSetting(bsi, "Skip Presenting Duplicate Frames", DrawToggleSetting(bsi, "Skip Presenting Duplicate Frames",
"Skips displaying frames that don't change in 25/30fps games. Can improve speed but increase input lag/make frame pacing worse.", "Skips displaying frames that don't change in 25/30fps games. Can improve speed but increase input lag/make frame pacing worse.",
"EmuCore/GS", "SkipDuplicateFrames", false); "EmuCore/GS", "SkipDuplicateFrames", false);
DrawToggleSetting(bsi, "Disable Hardware Readbacks",
"Skips thread synchronization for GS downloads. Can improve speed, but break graphical effects.", "EmuCore/GS",
"HWDisableReadbacks", false);
DrawIntListSetting(bsi, "Override Texture Barriers", "Forces texture barrier functionality to the specified value.", "EmuCore/GS", DrawIntListSetting(bsi, "Override Texture Barriers", "Forces texture barrier functionality to the specified value.", "EmuCore/GS",
"OverrideTextureBarriers", -1, s_generic_options, std::size(s_generic_options), -1); "OverrideTextureBarriers", -1, s_generic_options, std::size(s_generic_options), -1);
DrawIntListSetting(bsi, "Override Geometry Shaders", "Forces geometry shader functionality to the specified value.", "EmuCore/GS", DrawIntListSetting(bsi, "Override Geometry Shaders", "Forces geometry shader functionality to the specified value.", "EmuCore/GS",

View File

@ -1023,16 +1023,16 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset& off, const GSVector4i& r
r.z, r.z,
r.w); r.w);
if (GSConfig.HWDisableReadbacks)
{
Console.Error("Skipping readback of %ux%u @ %u,%u", r.width(), r.height(), r.left, r.top);
return;
}
// No depth handling please. // No depth handling please.
if (psm == PSM_PSMZ32 || psm == PSM_PSMZ24 || psm == PSM_PSMZ16 || psm == PSM_PSMZ16S) if (psm == PSM_PSMZ32 || psm == PSM_PSMZ24 || psm == PSM_PSMZ16 || psm == PSM_PSMZ16S)
{ {
GL_INS("ERROR: InvalidateLocalMem depth format isn't supported (%d,%d to %d,%d)", r.x, r.y, r.z, r.w); GL_INS("ERROR: InvalidateLocalMem depth format isn't supported (%d,%d to %d,%d)", r.x, r.y, r.z, r.w);
if (GSConfig.HWDownloadMode != GSHardwareDownloadMode::Enabled)
{
DevCon.Error("Skipping depth readback of %ux%u @ %u,%u", r.width(), r.height(), r.left, r.top);
return;
}
if (!GSConfig.UserHacks_DisableDepthSupport) if (!GSConfig.UserHacks_DisableDepthSupport)
{ {
auto& dss = m_dst[DepthStencil]; auto& dss = m_dst[DepthStencil];
@ -1082,7 +1082,12 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset& off, const GSVector4i& r
if (t->m_32_bits_fmt && t->m_TEX0.PSM > PSM_PSMCT24) if (t->m_32_bits_fmt && t->m_TEX0.PSM > PSM_PSMCT24)
t->m_TEX0.PSM = PSM_PSMCT32; t->m_TEX0.PSM = PSM_PSMCT32;
if (GSConfig.UserHacks_DisablePartialInvalidation) if (GSConfig.HWDownloadMode != GSHardwareDownloadMode::Enabled)
{
const GSVector4i rb_rc((!GSConfig.UserHacks_DisablePartialInvalidation && r.x == 0 && r.y == 0) ? t->m_valid : r.rintersect(t->m_valid));
DevCon.Error("Skipping depth readback of %ux%u @ %u,%u", rb_rc.width(), rb_rc.height(), rb_rc.left, rb_rc.top);
}
else if (GSConfig.UserHacks_DisablePartialInvalidation)
{ {
Read(t, r.rintersect(t->m_valid)); Read(t, r.rintersect(t->m_valid));
} }

View File

@ -244,9 +244,13 @@ void SysMtgsThread::PostVsyncStart(bool registers_written)
void SysMtgsThread::InitAndReadFIFO(u8* mem, u32 qwc) void SysMtgsThread::InitAndReadFIFO(u8* mem, u32 qwc)
{ {
if (EmuConfig.GS.HWDisableReadbacks && GSConfig.UseHardwareRenderer()) if (EmuConfig.GS.HWDownloadMode >= GSHardwareDownloadMode::Unsynchronized && GSConfig.UseHardwareRenderer())
{ {
GSReadLocalMemoryUnsync(mem, qwc, vif1.BITBLTBUF._u64, vif1.TRXPOS._u64, vif1.TRXREG._u64); if (EmuConfig.GS.HWDownloadMode == GSHardwareDownloadMode::Unsynchronized)
GSReadLocalMemoryUnsync(mem, qwc, vif1.BITBLTBUF._u64, vif1.TRXPOS._u64, vif1.TRXREG._u64);
else
std::memset(mem, 0, qwc * 16);
return; return;
} }
@ -936,9 +940,8 @@ void SysMtgsThread::ApplySettings()
// We need to synchronize the thread when changing any settings when the download mode // We need to synchronize the thread when changing any settings when the download mode
// is unsynchronized, because otherwise we might potentially read in the middle of // is unsynchronized, because otherwise we might potentially read in the middle of
// the GS renderer being reopened. // the GS renderer being reopened.
if (EmuConfig.GS.HWDisableReadbacks) if (EmuConfig.GS.HWDownloadMode == GSHardwareDownloadMode::Unsynchronized)
WaitGS(false, false, false); WaitGS(false, false, false);
} }
void SysMtgsThread::ResizeDisplayWindow(int width, int height, float scale) void SysMtgsThread::ResizeDisplayWindow(int width, int height, float scale)
@ -985,7 +988,7 @@ void SysMtgsThread::SwitchRenderer(GSRendererType renderer, bool display_message
}); });
// See note in ApplySettings() for reasoning here. // See note in ApplySettings() for reasoning here.
if (EmuConfig.GS.HWDisableReadbacks) if (EmuConfig.GS.HWDownloadMode == GSHardwareDownloadMode::Unsynchronized)
WaitGS(false, false, false); WaitGS(false, false, false);
} }

View File

@ -324,7 +324,7 @@ Pcsx2Config::GSOptions::GSOptions()
OsdShowSettings = false; OsdShowSettings = false;
OsdShowInputs = false; OsdShowInputs = false;
HWDisableReadbacks = false; HWDownloadMode = GSHardwareDownloadMode::Enabled;
GPUPaletteConversion = false; GPUPaletteConversion = false;
AutoFlushSW = true; AutoFlushSW = true;
PreloadFrameWithGSData = false; PreloadFrameWithGSData = false;
@ -405,6 +405,7 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
OpEqu(TextureFiltering) && OpEqu(TextureFiltering) &&
OpEqu(TexturePreloading) && OpEqu(TexturePreloading) &&
OpEqu(GSDumpCompression) && OpEqu(GSDumpCompression) &&
OpEqu(HWDownloadMode) &&
OpEqu(Dithering) && OpEqu(Dithering) &&
OpEqu(MaxAnisotropy) && OpEqu(MaxAnisotropy) &&
OpEqu(SWExtraThreads) && OpEqu(SWExtraThreads) &&
@ -545,7 +546,6 @@ void Pcsx2Config::GSOptions::ReloadIniSettings()
GSSettingBool(OsdShowSettings); GSSettingBool(OsdShowSettings);
GSSettingBool(OsdShowInputs); GSSettingBool(OsdShowInputs);
GSSettingBool(HWDisableReadbacks);
GSSettingBoolEx(GPUPaletteConversion, "paltex"); GSSettingBoolEx(GPUPaletteConversion, "paltex");
GSSettingBoolEx(AutoFlushSW, "autoflush_sw"); GSSettingBoolEx(AutoFlushSW, "autoflush_sw");
GSSettingBoolEx(PreloadFrameWithGSData, "preload_frame_with_gs_data"); GSSettingBoolEx(PreloadFrameWithGSData, "preload_frame_with_gs_data");
@ -592,6 +592,7 @@ void Pcsx2Config::GSOptions::ReloadIniSettings()
GSSettingIntEnumEx(TextureFiltering, "filter"); GSSettingIntEnumEx(TextureFiltering, "filter");
GSSettingIntEnumEx(TexturePreloading, "texture_preloading"); GSSettingIntEnumEx(TexturePreloading, "texture_preloading");
GSSettingIntEnumEx(GSDumpCompression, "GSDumpCompression"); GSSettingIntEnumEx(GSDumpCompression, "GSDumpCompression");
GSSettingIntEnumEx(HWDownloadMode, "HWDownloadMode");
GSSettingIntEx(Dithering, "dithering_ps2"); GSSettingIntEx(Dithering, "dithering_ps2");
GSSettingIntEx(MaxAnisotropy, "MaxAnisotropy"); GSSettingIntEx(MaxAnisotropy, "MaxAnisotropy");
GSSettingIntEx(SWExtraThreads, "extrathreads"); GSSettingIntEx(SWExtraThreads, "extrathreads");