SPU: Add Disable SPU GETLLAR Spin Optimization checkbox

This commit is contained in:
Megamouse 2025-03-17 19:00:55 +01:00
parent ae83c28bc8
commit bb3eac2131
6 changed files with 52 additions and 40 deletions

View file

@ -4615,15 +4615,15 @@ bool spu_thread::process_mfc_cmd()
if (getllar_busy_waiting_switch == umax && getllar_spin_count == 4)
{
const u32 percent = g_cfg.core.spu_getllar_busy_waiting_percentage;
// Hidden value to force busy waiting (100 to 1 are dynamically adjusted, 0 is not)
if (percent != 101)
if (!g_cfg.core.spu_getllar_spin_optimization_disabled)
{
const u32 percent = g_cfg.core.spu_getllar_busy_waiting_percentage;
// Predict whether or not to use operating system sleep based on history
auto& stats = getllar_wait_time[(addr % SPU_LS_SIZE) / 128];
const auto old_stats = stats;
const std::array<u8, 4> old_stats = stats;
std::array<u8, 4> new_stats{};
// Rotate history (prepare newest entry)
@ -4640,7 +4640,7 @@ bool spu_thread::process_mfc_cmd()
for (u8 val : old_stats)
{
total_wait += val;
zero_count += (val == 0 ? 1 : 0);
if (val == 0) ++zero_count;
}
// Add to chance if previous wait was long enough
@ -4675,10 +4675,8 @@ bool spu_thread::process_mfc_cmd()
// Don't be stubborn, force operating sleep if too much time has passed
else if (getllar_busy_waiting_switch == 1 && perf0.get() > getllar_evaluate_time && perf0.get() - getllar_evaluate_time >= 400'000)
{
const u32 percent = g_cfg.core.spu_getllar_busy_waiting_percentage;
// Hidden value to force busy waiting
if (percent != 101)
if (!g_cfg.core.spu_getllar_spin_optimization_disabled)
{
spu_log.trace("SPU wait for 0x%x", addr);
getllar_wait_time[(addr % SPU_LS_SIZE) / 128].front() = 1;

View file

@ -32,7 +32,8 @@ struct cfg_root : cfg::node
cfg::_bool set_daz_and_ftz{ this, "Set DAZ and FTZ", false };
cfg::_enum<spu_decoder_type> spu_decoder{ this, "SPU Decoder", spu_decoder_type::llvm };
cfg::uint<0, 100> spu_reservation_busy_waiting_percentage{ this, "SPU Reservation Busy Waiting Percentage", 0, true };
cfg::uint<0, 101> spu_getllar_busy_waiting_percentage{ this, "SPU GETLLAR Busy Waiting Percentage", 100, true };
cfg::uint<0, 100> spu_getllar_busy_waiting_percentage{ this, "SPU GETLLAR Busy Waiting Percentage", 100, true };
cfg::_bool spu_getllar_spin_optimization_disabled{ this, "Disable SPU GETLLAR Spin Optimization", false, true };
cfg::_bool spu_debug{ this, "SPU Debug" };
cfg::_bool mfc_debug{ this, "MFC Debug" };
cfg::_int<0, 6> preferred_spu_threads{ this, "Preferred SPU Threads", 0, true }; // Number of hardware threads dedicated to heavy simultaneous spu tasks

View file

@ -51,6 +51,7 @@ enum class emu_settings_type
AccuratePPUFPCC,
MaxPreemptCount,
SPUProfiler,
DisableSpinOptimization,
// Graphics
Renderer,
@ -248,6 +249,7 @@ inline static const std::map<emu_settings_type, cfg_location> settings_location
{ emu_settings_type::AccuratePPUFPCC, { "Core", "PPU Set FPCC Bits"}},
{ emu_settings_type::MaxPreemptCount, { "Core", "Max CPU Preempt Count"}},
{ emu_settings_type::SPUProfiler, { "Core", "SPU Profiler"}},
{ emu_settings_type::DisableSpinOptimization, { "Core", "Disable SPU GETLLAR Spin Optimization"}},
// Graphics Tab
{ emu_settings_type::Renderer, { "Video", "Renderer"}},

View file

@ -1585,6 +1585,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
m_emu_settings->EnhanceCheckBox(ui->disableAsyncHostMM, emu_settings_type::DisableAsyncHostMM);
SubscribeTooltip(ui->disableAsyncHostMM, tooltips.settings.disable_async_host_mm);
m_emu_settings->EnhanceCheckBox(ui->disableSpinOptimization, emu_settings_type::DisableSpinOptimization);
SubscribeTooltip(ui->disableSpinOptimization, tooltips.settings.disable_spin_optimization);
// Comboboxes
m_emu_settings->EnhanceComboBox(ui->maxSPURSThreads, emu_settings_type::MaxSPURSThreads, true);

View file

@ -265,7 +265,7 @@
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="coreTabRightLayout" stretch="0,0,0,0,0">
<layout class="QVBoxLayout" name="coreTabRightLayout" stretch="0,0,0,0">
<item>
<widget class="QGroupBox" name="gb_tsx">
<property name="sizePolicy">
@ -2422,6 +2422,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="disableSpinOptimization">
<property name="text">
<string>Disable SPU GETLLAR Spin Optimization</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="ppuNJFixup">
<property name="text">
@ -4242,16 +4249,16 @@
</item>
<item>
<widget class="QCheckBox" name="disableAsyncHostMM">
<property name="text">
<string>Disable Asynchronous Memory Manager</string>
</property>
<property name="text">
<string>Disable Asynchronous Memory Manager</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="disableOnDiskShaderCache">
<property name="text">
<string>Disable On-Disk Shader Cache</string>
</property>
<property name="text">
<string>Disable On-Disk Shader Cache</string>
</property>
</widget>
</item>
<item>
@ -4365,16 +4372,16 @@
</item>
<item>
<widget class="QCheckBox" name="fixupPPUVNAN">
<property name="text">
<string>PPU Vector NaN Fixup</string>
</property>
<property name="text">
<string>PPU Vector NaN Fixup</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="spuProfiler">
<property name="text">
<string>SPU Profiler</string>
</property>
<property name="text">
<string>SPU Profiler</string>
</property>
</widget>
</item>
<item>
@ -4398,7 +4405,7 @@
</item>
<item>
<widget class="QWidget" name="debug_more_stuff" native="true">
<layout class="QVBoxLayout" name="debug_more_stuff_layout" stretch="0,0,0,0,1">
<layout class="QVBoxLayout" name="debug_more_stuff_layout" stretch="0,0,0,0,0,1">
<property name="leftMargin">
<number>0</number>
</property>
@ -4459,23 +4466,23 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_vulkansched">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Vulkan Queue Scheduler</string>
</property>
<layout class="QVBoxLayout" name="gb_vksched_layout">
<item>
<widget class="QComboBox" name="vulkansched"/>
</item>
</layout>
</widget>
</item>
<widget class="QGroupBox" name="gb_vulkansched">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Vulkan Queue Scheduler</string>
</property>
<layout class="QVBoxLayout" name="gb_vksched_layout">
<item>
<widget class="QComboBox" name="vulkansched"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_debug_io">
<property name="title">

View file

@ -41,6 +41,7 @@ public:
const QString force_hw_MSAA = tr("Forces MSAA to use the host GPU's resolve capabilities for all sampling operations.\nThis option incurs a performance penalty as well as the risk of visual artifacts but can yield crisper visuals when MSAA is enabled.");
const QString disable_vertex_cache = tr("Disables the vertex cache.\nMight resolve missing or flickering graphics output.\nMay degrade performance.");
const QString disable_async_host_mm = tr("Force host memory management calls to be inlined instead of handled asynchronously.\nThis can cause severe performance degradation and stuttering in some games.\nThis option is only needed by developers to debug problems with texture cache memory protection.");
const QString disable_spin_optimization = tr("Disable SPU GETLLAR spin optimization.\nThis can cause severe performance degradation and stuttering in many games.\nThis option is only needed for a select number of games.");
const QString zcull_operation_mode = tr("Changes ZCULL report synchronization behaviour. Experiment to find the best option for your game. Approximate mode is recommended for most games.\n· Precise is the most accurate to PS3 behaviour. Required for accurate visuals in some titles such as Demon's Souls and The Darkness.\n· Approximate is a much faster way to generate occlusion data which may not always match what the PS3 would generate. Works well with most PS3 games.\n· Relaxed changes the synchronization method completely and can greatly improve performance in some games or completely break others.");
const QString max_spurs_threads = tr("Limits the maximum number of SPURS threads in each thread group.\nMay improve performance in some cases, especially on systems with limited number of hardware threads.\nLimiting the number of threads is likely to cause crashes; it's recommended to keep this at the default value.");
const QString sleep_timers_accuracy = tr("Changes the sleep period accuracy.\n'As Host' uses default accuracy of the underlying operating system, while 'All Timers' attempts to improve it.\n'Usleep Only' limits the adjustments to usleep syscall only.\nCan affect performance in unexpected ways.");