Skip to content

Commit

Permalink
VMManager: Refactor Affinity Control to Thread Pinning
Browse files Browse the repository at this point in the history
Instead of having control over specific threads, thread pinning puts the
EE/VU/GS threads on the most performant cores, then the software threads
on the remaining cores, but only if they're in the same cluster.

This way we don't end up pinning across clusters with different
performance characteristics, which would harm instead of help software
renderer performance.

Also unpins on shutdown, that way we don't keep CPU cores awake.
  • Loading branch information
stenzek committed Jun 15, 2024
1 parent 4e34315 commit 7220a6d
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 203 deletions.
4 changes: 4 additions & 0 deletions pcsx2-qt/Settings/AdvancedSettingsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu0Recompiler, "EmuCore/CPU/Recompiler", "EnableVU0", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu1Recompiler, "EmuCore/CPU/Recompiler", "EnableVU1", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vuFlagHack, "EmuCore/Speedhacks", "vuFlagHack", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.instantVU1, "EmuCore/Speedhacks", "vu1Instant", true);

SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeRoundingMode, "EmuCore/CPU", "FPU.Roundmode", static_cast<int>(FPRoundMode::ChopZero));
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeDivRoundingMode, "EmuCore/CPU", "FPUDiv.Roundmode", static_cast<int>(FPRoundMode::Nearest));
Expand Down Expand Up @@ -101,6 +102,9 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* dialog, QWidget*
dialog->registerWidgetHelp(m_ui.vu1ClampMode, tr("VU1 Clamping Mode"), tr("Normal (Default)"), tr("Changes how PCSX2 handles keeping floats in a standard x86 range in the Emotion Engine's Vector Unit 1 (EE VU1). "
"The default value handles the vast majority of games; <b>modifying this setting when a game is not having a visible problem can cause instability.</b>"));

dialog->registerWidgetHelp(m_ui.instantVU1, tr("Enable Instant VU1"), tr("Checked"), tr("Runs VU1 instantly. Provides a modest speed improvement in most games. "
"Safe for most games, but a few games may exhibit graphical errors."));

//: VU0 = Vector Unit 0. One of the PS2's processors.
dialog->registerWidgetHelp(m_ui.vu0Recompiler, tr("Enable VU0 Recompiler (Micro Mode)"), tr("Checked"), tr("Enables VU0 Recompiler."));

Expand Down
15 changes: 11 additions & 4 deletions pcsx2-qt/Settings/AdvancedSettingsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>807</width>
<height>723</height>
<width>790</width>
<height>765</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
Expand Down Expand Up @@ -202,7 +202,7 @@
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="extraMemory">
<property name="text">
<property name="text">
<string>Enable 128MB RAM (Dev Console)</string>
</property>
</widget>
Expand Down Expand Up @@ -272,6 +272,13 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="instantVU1">
<property name="text">
<string>Enable Instant VU1</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
Expand Down Expand Up @@ -494,7 +501,7 @@
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
Expand Down
8 changes: 2 additions & 6 deletions pcsx2-qt/Settings/EmulationSettingsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
m_ui.optimalFramePacing->setTristate(dialog->isPerGameSettings());

SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeCycleSkipping, "EmuCore/Speedhacks", "EECycleSkip", DEFAULT_EE_CYCLE_SKIP);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.affinityControl, "EmuCore/CPU", "AffinityControlMode", 0);

SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.MTVU, "EmuCore/Speedhacks", "vuThread", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.instantVU1, "EmuCore/Speedhacks", "vu1Instant", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.threadPinning, "EmuCore", "EnableThreadPinning", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fastCDVD, "EmuCore/Speedhacks", "fastCDVD", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.precacheCDVD, "EmuCore", "CdvdPrecache", false);

Expand Down Expand Up @@ -113,16 +112,13 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
tr("Makes the emulated Emotion Engine skip cycles. "
//: SOTC = Shadow of the Colossus. A game's title, should not be translated unless an official translation exists.
"Helps a small subset of games like SOTC. Most of the time it's harmful to performance."));
dialog->registerWidgetHelp(m_ui.affinityControl, tr("Affinity Control"), tr("Disabled"),
dialog->registerWidgetHelp(m_ui.threadPinning, tr("Enable Thread Pinning"), tr("Unchecked"),
tr("Sets the priority for specific threads in a specific order ignoring the system scheduler. "
//: P-Core = Performance Core, E-Core = Efficiency Core. See if Intel has official translations for these terms.
"May help CPUs with big (P) and little (E) cores (e.g. Intel 12th or newer generation CPUs from Intel or other vendors such as AMD)."));
dialog->registerWidgetHelp(m_ui.MTVU, tr("Enable Multithreaded VU1 (MTVU1)"), tr("Checked"),
tr("Generally a speedup on CPUs with 4 or more cores. "
"Safe for most games, but a few are incompatible and may hang."));
dialog->registerWidgetHelp(m_ui.instantVU1, tr("Enable Instant VU1"), tr("Checked"),
tr("Runs VU1 instantly. Provides a modest speed improvement in most games. "
"Safe for most games, but a few games may exhibit graphical errors."));
dialog->registerWidgetHelp(m_ui.fastCDVD, tr("Enable Fast CDVD"), tr("Unchecked"),
tr("Fast disc access, less loading times. Check HDLoader compatibility lists for known games that have issues with this."));
dialog->registerWidgetHelp(m_ui.precacheCDVD, tr("Enable CDVD Precaching"), tr("Unchecked"),
Expand Down
170 changes: 62 additions & 108 deletions pcsx2-qt/Settings/EmulationSettingsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -68,90 +68,6 @@
<string>System Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="3" column="0" colspan="2">
<layout class="QGridLayout" name="systemSettingsLayout">
<item row="0" column="1">
<widget class="QCheckBox" name="instantVU1">
<property name="text">
<string>Enable Instant VU1</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="cheats">
<property name="text">
<string>Enable Cheats</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="MTVU">
<property name="text">
<string>Enable Multithreaded VU1 (MTVU)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="hostFilesystem">
<property name="text">
<string>Enable Host Filesystem</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="fastCDVD">
<property name="text">
<string>Enable Fast CDVD</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="precacheCDVD">
<property name="text">
<string>Enable CDVD Precaching</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>EE Cycle Skipping:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="eeCycleSkipping">
<item>
<property name="text">
<string>Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>Mild Underclock</string>
</property>
</item>
<item>
<property name="text">
<string>Moderate Underclock</string>
</property>
</item>
<item>
<property name="text">
<string>Maximum Underclock</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>EE Cycle Rate:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="eeCycleRate">
<item>
Expand Down Expand Up @@ -191,50 +107,88 @@
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Affinity Control:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="affinityControl">
<item row="1" column="1">
<widget class="QComboBox" name="eeCycleSkipping">
<item>
<property name="text">
<string>Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>EE &gt; VU &gt; GS</string>
<string>Mild Underclock</string>
</property>
</item>
<item>
<property name="text">
<string>EE &gt; GS &gt; VU</string>
<string>Moderate Underclock</string>
</property>
</item>
<item>
<property name="text">
<string>VU &gt; EE &gt; GS</string>
<string>Maximum Underclock</string>
</property>
</item>
<item>
<property name="text">
<string>VU &gt; GS &gt; EE</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<layout class="QGridLayout" name="systemSettingsLayout">
<item row="1" column="0">
<widget class="QCheckBox" name="cheats">
<property name="text">
<string>Enable Cheats</string>
</property>
</widget>
</item>
<item>
<property name="text">
<string>GS &gt; EE &gt; VU</string>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="MTVU">
<property name="text">
<string>Enable Multithreaded VU1 (MTVU)</string>
</property>
</widget>
</item>
<item>
<property name="text">
<string>GS &gt; VU &gt; EE</string>
</property>
<item row="1" column="1">
<widget class="QCheckBox" name="hostFilesystem">
<property name="text">
<string>Enable Host Filesystem</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="fastCDVD">
<property name="text">
<string>Enable Fast CDVD</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="precacheCDVD">
<property name="text">
<string>Enable CDVD Precaching</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="threadPinning">
<property name="text">
<string>Enable Thread Pinning</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>EE Cycle Rate:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>EE Cycle Skipping:</string>
</property>
</widget>
</item>
</layout>
Expand Down
3 changes: 1 addition & 2 deletions pcsx2/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,6 @@ struct Pcsx2Config
FPControlRegister VU0FPCR;
FPControlRegister VU1FPCR;

u32 AffinityControlMode;

CpuOptions();
void LoadSave(SettingsWrapper& wrap);
void ApplySanityCheck();
Expand Down Expand Up @@ -1119,6 +1117,7 @@ struct Pcsx2Config
EnableNoInterlacingPatches : 1,
EnableFastBoot : 1,
EnableFastBootFastForward : 1,
EnableThreadPinning : 1,
// TODO - Vaser - where are these settings exposed in the Qt UI?
EnableRecordingTools : 1,
EnableGameFixes : 1, // enables automatic game fixes
Expand Down
11 changes: 5 additions & 6 deletions pcsx2/GS/Renderers/SW/GSRasterizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1215,15 +1215,14 @@ void GSRasterizerList::OnWorkerStartup(int i)

Threading::ThreadHandle handle(Threading::ThreadHandle::GetForCallingThread());

if (EmuConfig.Cpu.AffinityControlMode != 0)
if (EmuConfig.EnableThreadPinning)
{
const std::vector<u32>& procs = VMManager::GetSortedProcessorList();
const u32 processor_index = (THREAD_VU1 ? 3 : 2) + i;
if (processor_index < procs.size())
const std::vector<u32>& procs = VMManager::Internal::GetSoftwareRendererProcessorList();
if (i < procs.size())
{
const u32 procid = procs[processor_index];
const u32 procid = procs[i];
const u64 affinity = static_cast<u64>(1) << procid;
Console.WriteLn("Pinning GS thread %d to CPU %u (0x%llx)", i, procid, affinity);
INFO_LOG("Pinning GS thread {} to CPU {} (0x{:x})", i, procid, affinity);
handle.SetAffinity(affinity);
}
}
Expand Down
Loading

0 comments on commit 7220a6d

Please sign in to comment.