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::BindWidgetToBoolSetting(sif, m_ui.disableFramebufferFetch, "EmuCore/GS", "DisableFramebufferFetch", 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
@ -290,9 +290,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
connect(m_ui.swTextureFiltering, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onSWTextureFilteringChange);
updateRendererDependentOptions();
// only allow disabling readbacks for per-game settings, it's too dangerous
#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.
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 "
"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. "
"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."));

View File

@ -1429,8 +1429,15 @@
</item>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="5" column="0" colspan="2">
<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">
<widget class="QCheckBox" name="useBlitSwapChain">
<property name="text">
@ -1438,6 +1445,13 @@
</property>
</widget>
</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">
<widget class="QCheckBox" name="useDebugDevice">
<property name="text">
@ -1452,37 +1466,16 @@
</property>
</widget>
</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>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="label_34">
<property name="text">
<string>GS Dump Compression:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<widget class="QComboBox" name="gsDumpCompression">
<item>
<property name="text">
@ -1501,6 +1494,37 @@
</item>
</widget>
</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>
</widget>
</item>

View File

@ -199,6 +199,14 @@ enum class GSDumpCompressionMethod : u8
Zstandard,
};
enum class GSHardwareDownloadMode : u8
{
Enabled,
NoReadbacks,
Unsynchronized,
Disabled
};
// Template function for casting enumerations to their underlying type
template <typename Enumeration>
typename std::underlying_type<Enumeration>::type enum_cast(Enumeration E)
@ -488,7 +496,6 @@ struct Pcsx2Config
OsdShowInputs : 1;
bool
HWDisableReadbacks : 1,
GPUPaletteConversion : 1,
AutoFlushSW : 1,
PreloadFrameWithGSData : 1,
@ -561,6 +568,7 @@ struct Pcsx2Config
BiFiltering TextureFiltering{BiFiltering::PS2};
TexturePreloadingLevel TexturePreloading{TexturePreloadingLevel::Full};
GSDumpCompressionMethod GSDumpCompression{GSDumpCompressionMethod::LZMA};
GSHardwareDownloadMode HWDownloadMode{GSHardwareDownloadMode::Enabled};
int Dithering{2};
int MaxAnisotropy{0};
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_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_hw_download[] = {"Accurate (Recommended)", "Disable Readbacks (Synchronize GS Thread)",
"Unsynchronized (Non-Deterministic)", "Disabled (Ignore Transfers)"};
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.",
"EmuCore/GS", "texture_preloading", static_cast<int>(TexturePreloadingLevel::Off), 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",
"Applies palettes to textures on the GPU instead of the CPU. Can result in speed improvements in some games.", "EmuCore/GS",
"paltex", false);
@ -2780,9 +2784,6 @@ void FullscreenUI::DrawGraphicsSettingsPage()
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.",
"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",
"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",

View File

@ -1023,16 +1023,16 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset& off, const GSVector4i& r
r.z,
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.
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);
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)
{
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)
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));
}

View File

@ -244,9 +244,13 @@ void SysMtgsThread::PostVsyncStart(bool registers_written)
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;
}
@ -936,9 +940,8 @@ void SysMtgsThread::ApplySettings()
// 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
// the GS renderer being reopened.
if (EmuConfig.GS.HWDisableReadbacks)
if (EmuConfig.GS.HWDownloadMode == GSHardwareDownloadMode::Unsynchronized)
WaitGS(false, false, false);
}
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.
if (EmuConfig.GS.HWDisableReadbacks)
if (EmuConfig.GS.HWDownloadMode == GSHardwareDownloadMode::Unsynchronized)
WaitGS(false, false, false);
}

View File

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