From e6714db7b3595c030083489d46f829622c41b29b Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Wed, 12 Jun 2024 20:27:23 +0100 Subject: [PATCH 01/12] GS/HW: Don't kill old targets unless completely dirty or targets overlap --- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 014c2e3efeafae..640f6f3929804e 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -4296,7 +4296,7 @@ void GSTextureCache::IncAge() AgeHashCache(); - // As of 04/15/2024 this is s et to 60 (just 1 second of targets), which should be fine now as it doesn't destroy targets which haven't been coevred. + // As of 04/15/2024 this is s et to 60 (just 1 second of targets), which should be fine now as it doesn't destroy targets which haven't been covered. // // For reference, here are some games sensitive to killing old targets: // Original maxage was 4 here, Xenosaga 2 needs at least 240, else it flickers on scene transitions. @@ -4318,7 +4318,7 @@ void GSTextureCache::IncAge() { const Target* overlapping_tgt = FindOverlappingTarget(t); - if (!t->m_dirty.empty() || overlapping_tgt != nullptr) + if (overlapping_tgt != nullptr || t->m_dirty.GetTotalRect(t->m_TEX0, GSVector2i(t->m_valid.width(), t->m_valid.height())).rintersect(t->m_valid).eq(t->m_valid)) { i = list.erase(i); GL_CACHE("TC: Remove Target(%s): (0x%x) due to age", to_string(type), From 9c57ac34e319da547b21f7907f999d98d540a57a Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Wed, 12 Jun 2024 22:15:15 +0100 Subject: [PATCH 02/12] GS/HW: Include block offsets on invalidation by page --- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 640f6f3929804e..2f0a94122dadb5 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -544,7 +544,7 @@ void GSTextureCache::DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVe const bool matched_format = (src_info->bpp == dst_info->bpp); const bool block_matched_format = matched_format && block_aligned_rect; const bool req_depth_offset = (src_info->depth > 0 && !page_aligned_rect); - + bool address_offset = block_offset > 0; // If there is block offset left over, try to adjust to that. if (block_matched_format && (block_offset || req_depth_offset)) { @@ -586,6 +586,7 @@ void GSTextureCache::DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVe b2a_offset.x = 0; } + address_offset = false; in_rect = (in_rect + b2a_offset.xyxy()).max_i32(GSVector4i(0)); if (block_offset > 0 && !req_depth_offset) @@ -647,6 +648,17 @@ void GSTextureCache::DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVe const int block_y = in_rect.y & (src_info->pgs.y - 1); x_offset += block_x; y_offset += block_y; + + if (address_offset) + { + const int blocks_wide = src_info->pgs.x / src_info->bs.x; + const int block_x_offset = (block_offset % blocks_wide) * src_info->bs.x; + const int block_y_offset = (block_offset / blocks_wide) * src_info->bs.y; + + x_offset += block_x_offset; + y_offset += block_y_offset; + } + if (block_x) in_rect = GSVector4i(in_rect.x - block_x, in_rect.y, in_rect.z - block_x, in_rect.w); if (block_y) From 6fcd5d0aff278d0de2244854a0515a610ea1358a Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 15 Jun 2024 17:42:56 +1000 Subject: [PATCH 03/12] GzippedFileReader: Don't write OOB in last chunk zlib_indexed can write the full span to the block, despite the length being shorter. This code can die in a fire. Closes #11398. --- pcsx2/CDVD/GzippedFileReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcsx2/CDVD/GzippedFileReader.cpp b/pcsx2/CDVD/GzippedFileReader.cpp index 8791d2a69db55f..ee2e5e2b916c37 100644 --- a/pcsx2/CDVD/GzippedFileReader.cpp +++ b/pcsx2/CDVD/GzippedFileReader.cpp @@ -223,7 +223,7 @@ ThreadedFileReader::Chunk GzippedFileReader::ChunkForOffset(u64 offset) else { chunk.chunkID = static_cast(offset) / m_index->span; - chunk.length = static_cast(std::min(m_index->uncompressed_size - offset, m_index->span)); + chunk.length = m_index->span; chunk.offset = static_cast(chunk.chunkID) * m_index->span; } From 4e3431585fd67731ec8cdbfe2eb0e5359d1ef014 Mon Sep 17 00:00:00 2001 From: lightningterror <18107717+lightningterror@users.noreply.github.com> Date: Sat, 15 Jun 2024 00:57:04 +0200 Subject: [PATCH 04/12] CDVD: Fix -Wsign-compare warnings. --- pcsx2/CDVD/CDVD.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index abd513e7aa78d2..fe99ef6e73132b 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -230,7 +230,7 @@ void cdvdSaveNVRAM() static void cdvdReadNVM(u8* dst, int offset, int bytes) { int to_read = bytes; - if ((offset + bytes) > sizeof(s_nvram)) [[unlikely]] + if (static_cast(offset + bytes) > sizeof(s_nvram)) [[unlikely]] { WARNING_LOG("CDVD: Out of bounds NVRAM read: offset={}, bytes={}", offset, bytes); to_read = std::max(static_cast(sizeof(s_nvram)) - offset, 0); @@ -245,7 +245,7 @@ static void cdvdReadNVM(u8* dst, int offset, int bytes) static void cdvdWriteNVM(const u8* src, int offset, int bytes) { int to_write = bytes; - if ((offset + bytes) > sizeof(s_nvram)) [[unlikely]] + if (static_cast(offset + bytes) > sizeof(s_nvram)) [[unlikely]] { WARNING_LOG("CDVD: Out of bounds NVRAM write: offset={}, bytes={}", offset, bytes); to_write = std::max(static_cast(sizeof(s_nvram)) - offset, 0); From 707d61f54d9a3b4b3295bdaa641fab9ad3003080 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 16 Jun 2024 00:06:55 +1000 Subject: [PATCH 05/12] CDVD: Remove leftover debug log Didn't mean to commit this. --- pcsx2/CDVD/CDVD.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index fe99ef6e73132b..b1c2d14ffe5cc4 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -339,7 +339,6 @@ s32 cdvdReadConfig(u8* config) default: { cdvdReadNVM(config, nvmLayout->config1 + (cdvd.CBlockIndex * 16), 16); - DEV_LOG("CONF1: {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}", config[0], config[1], config[2], config[3], config[4], config[5]); if (cdvd.CBlockIndex == 1 && (NoOSD || VMManager::Internal::WasFastBooted())) { // HACK: Set the "initialized" flag when fast booting, otherwise some games crash (e.g. Jak 1). From b1f051df403dbee1e94935c1146bed2dfea5a4da Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sat, 15 Jun 2024 20:36:41 +0100 Subject: [PATCH 06/12] GS/HW: Fix up Tekken 5 CRC to get rid of boxes when upscaling --- pcsx2/GS/Renderers/HW/GSHwHack.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pcsx2/GS/Renderers/HW/GSHwHack.cpp b/pcsx2/GS/Renderers/HW/GSHwHack.cpp index 8fdb347f587c56..ee8417915a9fc9 100644 --- a/pcsx2/GS/Renderers/HW/GSHwHack.cpp +++ b/pcsx2/GS/Renderers/HW/GSHwHack.cpp @@ -194,10 +194,12 @@ bool GSHwHack::GSC_Tekken5(GSRendererHW& r, int& skip) return true; } - if (!s_nativeres && RTME && RTEX0.TFX == 1 && RFPSM == RTPSM && std::abs(static_cast(RFBP - RTBP0)) == 0x180 && RTPSM == PSMCT32 && RFBMSK == 0xFF000000) + if (!s_nativeres && r.PRIM->PRIM == GS_SPRITE && RTME && RTEX0.TFX == 1 && RFPSM == RTPSM && RTPSM == PSMCT32 && RFBMSK == 0xFF000000 && r.m_index.tail > 2) { // Don't enable hack on native res. // Fixes ghosting/blur effect and white lines appearing in stages: Moonfit Wilderness, Acid Rain - caused by upscaling. + // Game copies the framebuffer as individual page rects with slight offsets (like 1/16 of a pixel etc) which doesn't wokr well with upscaling. + // This should catch all the scenarios, maybe overdoes it, but it's for 1 game and it's non-detrimental, it's better than squares all over the screen. const GSVector4i draw_size(r.m_vt.m_min.p.x, r.m_vt.m_min.p.y, r.m_vt.m_max.p.x + 1.0f, r.m_vt.m_max.p.y + 1.0f); const GSVector4i read_size(r.m_vt.m_min.t.x, r.m_vt.m_min.t.y, r.m_vt.m_max.t.x + 0.5f, r.m_vt.m_max.t.y + 0.5f); r.ReplaceVerticesWithSprite(draw_size, read_size, GSVector2i(read_size.width(), read_size.height()), draw_size); From 8766d0b676f08fa8eb6dfd8268975d5efef26c05 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 15 Jun 2024 23:34:50 +1000 Subject: [PATCH 07/12] VMManager: Refactor Affinity Control to Thread Pinning 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. --- pcsx2-qt/Settings/AdvancedSettingsWidget.cpp | 4 + pcsx2-qt/Settings/AdvancedSettingsWidget.ui | 15 +- pcsx2-qt/Settings/EmulationSettingsWidget.cpp | 8 +- pcsx2-qt/Settings/EmulationSettingsWidget.ui | 170 +++++++----------- pcsx2/Config.h | 3 +- pcsx2/GS/Renderers/SW/GSRasterizer.cpp | 25 ++- pcsx2/GS/Renderers/SW/GSRasterizer.h | 2 +- pcsx2/ImGui/FullscreenUI.cpp | 37 ++-- pcsx2/Pcsx2Config.cpp | 7 +- pcsx2/VMManager.cpp | 155 ++++++++-------- pcsx2/VMManager.h | 7 +- 11 files changed, 182 insertions(+), 251 deletions(-) diff --git a/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp b/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp index 3279b700075527..b0e3663a492c31 100644 --- a/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp +++ b/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp @@ -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(FPRoundMode::ChopZero)); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeDivRoundingMode, "EmuCore/CPU", "FPUDiv.Roundmode", static_cast(FPRoundMode::Nearest)); @@ -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; modifying this setting when a game is not having a visible problem can cause instability.")); + 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.")); diff --git a/pcsx2-qt/Settings/AdvancedSettingsWidget.ui b/pcsx2-qt/Settings/AdvancedSettingsWidget.ui index cb816515dabd39..e645a7c1002cca 100644 --- a/pcsx2-qt/Settings/AdvancedSettingsWidget.ui +++ b/pcsx2-qt/Settings/AdvancedSettingsWidget.ui @@ -33,8 +33,8 @@ 0 0 - 807 - 723 + 790 + 765 @@ -202,7 +202,7 @@ - + Enable 128MB RAM (Dev Console) @@ -272,6 +272,13 @@ + + + + Enable Instant VU1 + + + @@ -494,7 +501,7 @@ - Qt::Vertical + Qt::Orientation::Vertical diff --git a/pcsx2-qt/Settings/EmulationSettingsWidget.cpp b/pcsx2-qt/Settings/EmulationSettingsWidget.cpp index 81cf8c1d802d6f..f67af89cf857e7 100644 --- a/pcsx2-qt/Settings/EmulationSettingsWidget.cpp +++ b/pcsx2-qt/Settings/EmulationSettingsWidget.cpp @@ -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); @@ -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"), diff --git a/pcsx2-qt/Settings/EmulationSettingsWidget.ui b/pcsx2-qt/Settings/EmulationSettingsWidget.ui index 8f49f935b477e1..424db2b38b608c 100644 --- a/pcsx2-qt/Settings/EmulationSettingsWidget.ui +++ b/pcsx2-qt/Settings/EmulationSettingsWidget.ui @@ -68,90 +68,6 @@ System Settings - - - - - - Enable Instant VU1 - - - - - - - Enable Cheats - - - - - - - Enable Multithreaded VU1 (MTVU) - - - - - - - Enable Host Filesystem - - - - - - - Enable Fast CDVD - - - - - - - Enable CDVD Precaching - - - - - - - - - EE Cycle Skipping: - - - - - - - - Disabled - - - - - Mild Underclock - - - - - Moderate Underclock - - - - - Maximum Underclock - - - - - - - - EE Cycle Rate: - - - @@ -191,15 +107,8 @@ - - - - Affinity Control: - - - - - + + Disabled @@ -207,34 +116,79 @@ - EE > VU > GS + Mild Underclock - EE > GS > VU + Moderate Underclock - VU > EE > GS + Maximum Underclock - - - VU > GS > EE - + + + + + + + + Enable Cheats + + - - - GS > EE > VU - + + + + Enable Multithreaded VU1 (MTVU) + + - - - GS > VU > EE - + + + + Enable Host Filesystem + + + + + + + Enable Fast CDVD + + + + + + + Enable CDVD Precaching + + + + + + Enable Thread Pinning + + + + + + + + + EE Cycle Rate: + + + + + + + EE Cycle Skipping: + diff --git a/pcsx2/Config.h b/pcsx2/Config.h index 28d861c9c71b83..7880bdec6ac596 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -545,8 +545,6 @@ struct Pcsx2Config FPControlRegister VU0FPCR; FPControlRegister VU1FPCR; - u32 AffinityControlMode; - CpuOptions(); void LoadSave(SettingsWrapper& wrap); void ApplySanityCheck(); @@ -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 diff --git a/pcsx2/GS/Renderers/SW/GSRasterizer.cpp b/pcsx2/GS/Renderers/SW/GSRasterizer.cpp index 61ab3e9af9c1d7..8533ef468e0fa1 100644 --- a/pcsx2/GS/Renderers/SW/GSRasterizer.cpp +++ b/pcsx2/GS/Renderers/SW/GSRasterizer.cpp @@ -1209,23 +1209,15 @@ GSRasterizerList::~GSRasterizerList() _aligned_free(m_scanline); } -void GSRasterizerList::OnWorkerStartup(int i) +void GSRasterizerList::OnWorkerStartup(int i, u64 affinity) { Threading::SetNameOfCurrentThread(StringUtil::StdStringFromFormat("GS-SW-%d", i).c_str()); Threading::ThreadHandle handle(Threading::ThreadHandle::GetForCallingThread()); - - if (EmuConfig.Cpu.AffinityControlMode != 0) + if (affinity != 0) { - const std::vector& procs = VMManager::GetSortedProcessorList(); - const u32 processor_index = (THREAD_VU1 ? 3 : 2) + i; - if (processor_index < procs.size()) - { - const u32 procid = procs[processor_index]; - const u64 affinity = static_cast(1) << procid; - Console.WriteLn("Pinning GS thread %d to CPU %u (0x%llx)", i, procid, affinity); - handle.SetAffinity(affinity); - } + INFO_LOG("Pinning GS thread {} to CPU {} (0x{:x})", i, std::countr_zero(affinity), affinity); + handle.SetAffinity(affinity); } PerformanceMetrics::SetGSSWThread(i, std::move(handle)); @@ -1306,11 +1298,18 @@ std::unique_ptr GSRasterizerList::Create(int threads) std::unique_ptr rl(new GSRasterizerList(threads)); + const std::vector& procs = VMManager::Internal::GetSoftwareRendererProcessorList(); + const bool pin = (EmuConfig.EnableThreadPinning && static_cast(threads) <= procs.size()); + if (EmuConfig.EnableThreadPinning && !pin) + WARNING_LOG("Not pinning SW threads, we need {} processors, but only have {}", threads, procs.size()); + for (int i = 0; i < threads; i++) { + const u64 affinity = pin ? (static_cast(1u) << procs[i]) : 0; rl->m_r.push_back(std::unique_ptr(new GSRasterizer(&rl->m_ds, i, threads))); auto& r = *rl->m_r[i]; - rl->m_workers.push_back(std::unique_ptr(new GSWorker([i]() { GSRasterizerList::OnWorkerStartup(i); }, + rl->m_workers.push_back(std::unique_ptr(new GSWorker( + [i, affinity]() { GSRasterizerList::OnWorkerStartup(i, affinity); }, [&r](GSRingHeap::SharedPtr& item) { r.Draw(*item.get()); }, [i]() { GSRasterizerList::OnWorkerShutdown(i); }))); } diff --git a/pcsx2/GS/Renderers/SW/GSRasterizer.h b/pcsx2/GS/Renderers/SW/GSRasterizer.h index ccf8a4285d7977..d17e08c13c92ce 100644 --- a/pcsx2/GS/Renderers/SW/GSRasterizer.h +++ b/pcsx2/GS/Renderers/SW/GSRasterizer.h @@ -166,7 +166,7 @@ class GSRasterizerList final : public IRasterizer GSRasterizerList(int threads); - static void OnWorkerStartup(int i); + static void OnWorkerStartup(int i, u64 affinity); static void OnWorkerShutdown(int i); public: diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index eb3e858cd5b176..6266c3190b2534 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -3275,15 +3275,6 @@ void FullscreenUI::DrawEmulationSettingsPage() FSUI_NSTR("Moderate Underclock"), FSUI_NSTR("Maximum Underclock"), }; - static constexpr const char* affinity_control_settings[] = { - FSUI_NSTR("Disabled"), - FSUI_NSTR("EE > VU > GS"), - FSUI_NSTR("EE > GS > VU"), - FSUI_NSTR("VU > EE > GS"), - FSUI_NSTR("VU > GS > EE"), - FSUI_NSTR("GS > EE > VU"), - FSUI_NSTR("GS > VU > EE"), - }; static constexpr const char* queue_entries[] = { FSUI_NSTR("0 Frames (Hard Sync)"), FSUI_NSTR("1 Frame"), @@ -3311,14 +3302,11 @@ void FullscreenUI::DrawEmulationSettingsPage() DrawIntListSetting(bsi, FSUI_CSTR("EE Cycle Skipping"), FSUI_CSTR("Makes the emulated Emotion Engine skip cycles. Helps a small subset of games like SOTC. Most of the time it's harmful to performance."), "EmuCore/Speedhacks", "EECycleSkip", 0, ee_cycle_skip_settings, std::size(ee_cycle_skip_settings), true); - DrawIntListSetting(bsi, FSUI_CSTR("Affinity Control Mode"), - FSUI_CSTR("Pins emulation threads to CPU cores to potentially improve performance/frame time variance."), "EmuCore/CPU", - "AffinityControlMode", 0, affinity_control_settings, std::size(affinity_control_settings), true); DrawToggleSetting(bsi, FSUI_CSTR("Enable MTVU (Multi-Threaded VU1)"), FSUI_CSTR("Generally a speedup on CPUs with 4 or more cores. Safe for most games, but a few are incompatible and may hang."), "EmuCore/Speedhacks", "vuThread", false); - DrawToggleSetting(bsi, FSUI_CSTR("Enable Instant VU1"), - FSUI_CSTR("Runs VU1 instantly. Provides a modest speed improvement in most games. Safe for most games, but a few games may exhibit graphical errors."), - "EmuCore/Speedhacks", "vu1Instant", true); + DrawToggleSetting(bsi, FSUI_CSTR("Thread Pinning"), + FSUI_CSTR("Pins emulation threads to CPU cores to potentially improve performance/frame time variance."), "EmuCore", + "EnableThreadPinning", false); DrawToggleSetting( bsi, FSUI_CSTR("Enable Cheats"), FSUI_CSTR("Enables loading cheats from pnach files."), "EmuCore", "EnableCheats", false); DrawToggleSetting(bsi, FSUI_CSTR("Enable Host Filesystem"), @@ -4769,6 +4757,9 @@ void FullscreenUI::DrawAdvancedSettingsPage() true); DrawToggleSetting(bsi, FSUI_CSTR("Enable VU Flag Optimization"), FSUI_CSTR("Good speedup and high compatibility, may cause graphical errors."), "EmuCore/Speedhacks", "vuFlagHack", true); + DrawToggleSetting(bsi, FSUI_CSTR("Enable Instant VU1"), + FSUI_CSTR("Runs VU1 instantly. Provides a modest speed improvement in most games. Safe for most games, but a few games may exhibit graphical errors."), + "EmuCore/Speedhacks", "vu1Instant", true); MenuHeading(FSUI_CSTR("I/O Processor")); DrawToggleSetting(bsi, FSUI_CSTR("Enable IOP Recompiler"), @@ -6944,12 +6935,10 @@ TRANSLATE_NOOP("FullscreenUI", "EE Cycle Rate"); TRANSLATE_NOOP("FullscreenUI", "Underclocks or overclocks the emulated Emotion Engine CPU."); TRANSLATE_NOOP("FullscreenUI", "EE Cycle Skipping"); TRANSLATE_NOOP("FullscreenUI", "Makes the emulated Emotion Engine skip cycles. Helps a small subset of games like SOTC. Most of the time it's harmful to performance."); -TRANSLATE_NOOP("FullscreenUI", "Affinity Control Mode"); -TRANSLATE_NOOP("FullscreenUI", "Pins emulation threads to CPU cores to potentially improve performance/frame time variance."); TRANSLATE_NOOP("FullscreenUI", "Enable MTVU (Multi-Threaded VU1)"); TRANSLATE_NOOP("FullscreenUI", "Generally a speedup on CPUs with 4 or more cores. Safe for most games, but a few are incompatible and may hang."); -TRANSLATE_NOOP("FullscreenUI", "Enable Instant VU1"); -TRANSLATE_NOOP("FullscreenUI", "Runs VU1 instantly. Provides a modest speed improvement in most games. Safe for most games, but a few games may exhibit graphical errors."); +TRANSLATE_NOOP("FullscreenUI", "Thread Pinning"); +TRANSLATE_NOOP("FullscreenUI", "Pins emulation threads to CPU cores to potentially improve performance/frame time variance."); TRANSLATE_NOOP("FullscreenUI", "Enable Cheats"); TRANSLATE_NOOP("FullscreenUI", "Enables loading cheats from pnach files."); TRANSLATE_NOOP("FullscreenUI", "Enable Host Filesystem"); @@ -7224,6 +7213,8 @@ TRANSLATE_NOOP("FullscreenUI", "New Vector Unit recompiler with much improved co TRANSLATE_NOOP("FullscreenUI", "Enable VU1 Recompiler"); TRANSLATE_NOOP("FullscreenUI", "Enable VU Flag Optimization"); TRANSLATE_NOOP("FullscreenUI", "Good speedup and high compatibility, may cause graphical errors."); +TRANSLATE_NOOP("FullscreenUI", "Enable Instant VU1"); +TRANSLATE_NOOP("FullscreenUI", "Runs VU1 instantly. Provides a modest speed improvement in most games. Safe for most games, but a few games may exhibit graphical errors."); TRANSLATE_NOOP("FullscreenUI", "I/O Processor"); TRANSLATE_NOOP("FullscreenUI", "Enable IOP Recompiler"); TRANSLATE_NOOP("FullscreenUI", "Performs just-in-time binary translation of 32-bit MIPS-I machine code to native code."); @@ -7391,13 +7382,6 @@ TRANSLATE_NOOP("FullscreenUI", "Normal (Default)"); TRANSLATE_NOOP("FullscreenUI", "Mild Underclock"); TRANSLATE_NOOP("FullscreenUI", "Moderate Underclock"); TRANSLATE_NOOP("FullscreenUI", "Maximum Underclock"); -TRANSLATE_NOOP("FullscreenUI", "Disabled"); -TRANSLATE_NOOP("FullscreenUI", "EE > VU > GS"); -TRANSLATE_NOOP("FullscreenUI", "EE > GS > VU"); -TRANSLATE_NOOP("FullscreenUI", "VU > EE > GS"); -TRANSLATE_NOOP("FullscreenUI", "VU > GS > EE"); -TRANSLATE_NOOP("FullscreenUI", "GS > EE > VU"); -TRANSLATE_NOOP("FullscreenUI", "GS > VU > EE"); TRANSLATE_NOOP("FullscreenUI", "0 Frames (Hard Sync)"); TRANSLATE_NOOP("FullscreenUI", "1 Frame"); TRANSLATE_NOOP("FullscreenUI", "2 Frames"); @@ -7491,6 +7475,7 @@ TRANSLATE_NOOP("FullscreenUI", "Sprites/Triangles"); TRANSLATE_NOOP("FullscreenUI", "Blended Sprites/Triangles"); TRANSLATE_NOOP("FullscreenUI", "1 (Normal)"); TRANSLATE_NOOP("FullscreenUI", "2 (Aggressive)"); +TRANSLATE_NOOP("FullscreenUI", "Disabled"); TRANSLATE_NOOP("FullscreenUI", "Inside Target"); TRANSLATE_NOOP("FullscreenUI", "Merge Targets"); TRANSLATE_NOOP("FullscreenUI", "Normal (Vertex)"); diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index 0bb970ab955371..4aa820765614f3 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -499,7 +499,7 @@ bool Pcsx2Config::CpuOptions::operator!=(const CpuOptions& right) const bool Pcsx2Config::CpuOptions::operator==(const CpuOptions& right) const { - return OpEqu(FPUFPCR) && OpEqu(FPUDivFPCR) && OpEqu(VU0FPCR) && OpEqu(VU1FPCR) && OpEqu(AffinityControlMode) && OpEqu(Recompiler); + return OpEqu(FPUFPCR) && OpEqu(FPUDivFPCR) && OpEqu(VU0FPCR) && OpEqu(VU1FPCR) && OpEqu(Recompiler); } Pcsx2Config::CpuOptions::CpuOptions() @@ -512,14 +512,11 @@ Pcsx2Config::CpuOptions::CpuOptions() VU0FPCR = DEFAULT_VU_FP_CONTROL_REGISTER; VU1FPCR = DEFAULT_VU_FP_CONTROL_REGISTER; - AffinityControlMode = 0; ExtraMemory = false; } void Pcsx2Config::CpuOptions::ApplySanityCheck() { - AffinityControlMode = std::min(AffinityControlMode, 6); - Recompiler.ApplySanityCheck(); } @@ -544,7 +541,6 @@ void Pcsx2Config::CpuOptions::LoadSave(SettingsWrapper& wrap) read_fpcr(VU0FPCR, "VU0"); read_fpcr(VU1FPCR, "VU1"); - SettingsWrapEntry(AffinityControlMode); SettingsWrapBitBool(ExtraMemory); Recompiler.LoadSave(wrap); @@ -1714,6 +1710,7 @@ void Pcsx2Config::LoadSaveCore(SettingsWrapper& wrap) SettingsWrapBitBool(EnableNoInterlacingPatches); SettingsWrapBitBool(EnableFastBoot); SettingsWrapBitBool(EnableFastBootFastForward); + SettingsWrapBitBool(EnableThreadPinning); SettingsWrapBitBool(EnableRecordingTools); SettingsWrapBitBool(EnableGameFixes); SettingsWrapBitBool(SaveStateOnShutdown); diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 8185fc3f423b02..49e7a52de2ccc0 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -178,6 +178,7 @@ static std::string s_input_profile_name; static u32 s_frame_advance_count = 0; static bool s_fast_boot_requested = false; static bool s_gs_open_on_initialize = false; +static bool s_thread_affinities_set = false; static LimiterModeType s_limiter_mode = LimiterModeType::Nominal; static s64 s_limiter_ticks_per_frame = 0; @@ -1659,6 +1660,7 @@ void VMManager::Shutdown(bool save_resume_state) FullscreenUI::OnVMDestroyed(); SaveStateSelectorUI::Clear(); UpdateInhibitScreensaver(false); + SetEmuThreadAffinities(); Host::OnVMDestroyed(); // clear out any potentially-incorrect settings from the last game @@ -2836,12 +2838,6 @@ void VMManager::CheckForCPUConfigChanges(const Pcsx2Config& old_config) // possible and reset next time we're called. s_cpu_implementation_changed = true; } - - if (EmuConfig.Cpu.AffinityControlMode != old_config.Cpu.AffinityControlMode || - EmuConfig.Speedhacks.vuThread != old_config.Speedhacks.vuThread) - { - SetEmuThreadAffinities(); - } } void VMManager::CheckForGSConfigChanges(const Pcsx2Config& old_config) @@ -2972,6 +2968,12 @@ void VMManager::CheckForMiscConfigChanges(const Pcsx2Config& old_config) else ShutdownDiscordPresence(); } + + if (HasValidVM() && (EmuConfig.EnableThreadPinning != old_config.EnableThreadPinning || + (s_thread_affinities_set && EmuConfig.Speedhacks.vuThread != old_config.Speedhacks.vuThread))) + { + SetEmuThreadAffinities(); + } } void VMManager::CheckForConfigChanges(const Pcsx2Config& old_config) @@ -3333,6 +3335,7 @@ void VMManager::SetTimerResolutionIncreased(bool enabled) #endif static std::vector s_processor_list; +static std::vector s_software_renderer_processor_list; static std::once_flag s_processor_list_initialized; #if defined(__linux__) || defined(_WIN32) @@ -3352,61 +3355,44 @@ static void InitializeProcessorList() { if (!cpuinfo_initialize()) { - Console.Error("cpuinfo_initialize() failed"); + ERROR_LOG("cpuinfo_initialize() failed"); return; } - const u32 cluster_count = cpuinfo_get_clusters_count(); - if (cluster_count == 0) - { - Console.Error("Invalid CPU count returned"); - return; - } + INFO_LOG("Processor count: {} cores, {} processors, {} clusters", + cpuinfo_get_cores_count(), cpuinfo_get_processors_count(), cpuinfo_get_clusters_count()); - Console.WriteLn(Color_StrongYellow, "Processor count: %u cores, %u processors", cpuinfo_get_cores_count(), - cpuinfo_get_processors_count()); - Console.WriteLn(Color_StrongYellow, "Cluster count: %u", cluster_count); - - static std::vector ordered_processors; - for (u32 i = 0; i < cluster_count; i++) + const u32 processor_count = cpuinfo_get_processors_count(); + std::vector processors; + for (u32 i = 0; i < processor_count; i++) { - const cpuinfo_cluster* cluster = cpuinfo_get_cluster(i); - for (u32 j = 0; j < cluster->processor_count; j++) - { - const cpuinfo_processor* proc = cpuinfo_get_processor(cluster->processor_start + j); - if (!proc) - continue; + // Ignore hyperthreads/SMT. They're not helpful for pinning. + const cpuinfo_processor* proc = cpuinfo_get_processor(i); + if (!proc || proc->smt_id != 0) + continue; - ordered_processors.push_back(proc); - } + processors.push_back(proc); } - // find the large and small clusters based on frequency - // this is assuming the large cluster is always clocked higher - // sort based on core, so that hyperthreads get pushed down - std::sort(ordered_processors.begin(), ordered_processors.end(), + + // Prioritize faster cores in heterogeneous CPUs. + std::sort(processors.begin(), processors.end(), [](const cpuinfo_processor* lhs, const cpuinfo_processor* rhs) { - return (lhs->core->frequency > rhs->core->frequency || lhs->smt_id < rhs->smt_id); + return (lhs->core->frequency > rhs->core->frequency); }); - s_processor_list.reserve(ordered_processors.size()); - std::stringstream ss; - ss << "Ordered processor list: "; - for (const cpuinfo_processor* proc : ordered_processors) + SmallString str; + str.assign("Ordered processor list: "); + s_processor_list.reserve(processors.size()); + for (const cpuinfo_processor* proc : processors) { - if (proc != ordered_processors.front()) - ss << ", "; - - const u32 procid = GetProcessorIdForProcessor(proc); - ss << procid; - if (proc->smt_id != 0) - ss << "[SMT " << proc->smt_id << "]"; - - s_processor_list.push_back(procid); + const u32 proc_id = GetProcessorIdForProcessor(proc); + str.append_format("{}{}", (proc == processors.front()) ? "" : ", ", proc_id); + s_processor_list.push_back(proc_id); } - Console.WriteLn(ss.str()); + Console.WriteLn(str.view()); } -static void SetMTVUAndAffinityControlDefault(SettingsInterface& si) +void VMManager::SetHardwareDependentDefaultSettings(SettingsInterface& si) { VMManager::EnsureCPUInfoInitialized(); @@ -3455,7 +3441,7 @@ static void InitializeProcessorList() } } -static void SetMTVUAndAffinityControlDefault(SettingsInterface& si) +void VMManager::SetHardwareDependentDefaultSettings(SettingsInterface& si) { VMManager::EnsureCPUInfoInitialized(); @@ -3480,12 +3466,9 @@ static void InitializeProcessorList() DevCon.WriteLn("(VMManager) InitializeCPUInfo() not implemented."); } -static void SetMTVUAndAffinityControlDefault(SettingsInterface& si) +void VMManager::SetHardwareDependentDefaultSettings(SettingsInterface& si) { -#ifdef __APPLE__ - // Everything we support Mac-wise has enough cores for MTVU. si.SetBoolValue("EmuCore/Speedhacks", "vuThread", true); -#endif } #endif @@ -3497,6 +3480,12 @@ void VMManager::EnsureCPUInfoInitialized() void VMManager::SetEmuThreadAffinities() { + const bool new_pin_enable = (GetState() != VMState::Shutdown && EmuConfig.EnableThreadPinning); + if (s_thread_affinities_set == new_pin_enable) + return; + + s_thread_affinities_set = EmuConfig.EnableThreadPinning; + EnsureCPUInfoInitialized(); if (s_processor_list.empty()) @@ -3505,45 +3494,33 @@ void VMManager::SetEmuThreadAffinities() return; } - if (EmuConfig.Cpu.AffinityControlMode == 0 || s_processor_list.size() < (EmuConfig.Speedhacks.vuThread ? 3 : 2)) + const bool mtvu = EmuConfig.Speedhacks.vuThread; + if (!new_pin_enable || s_processor_list.size() < (mtvu ? 3 : 2)) { - if (EmuConfig.Cpu.AffinityControlMode != 0) - Console.Error("Insufficient processors for affinity control."); + if (new_pin_enable) + ERROR_LOG("Insufficient processors for thread pinning."); MTGS::GetThreadHandle().SetAffinity(0); vu1Thread.GetThreadHandle().SetAffinity(0); s_vm_thread_handle.SetAffinity(0); + s_software_renderer_processor_list = {}; return; } - static constexpr u8 processor_assignment[7][2][3] = { - //EE xx GS EE VU GS - {{0, 2, 1}, {0, 1, 2}}, // Disabled - {{0, 2, 1}, {0, 1, 2}}, // EE > VU > GS - {{0, 2, 1}, {0, 2, 1}}, // EE > GS > VU - {{0, 2, 1}, {1, 0, 2}}, // VU > EE > GS - {{1, 2, 0}, {2, 0, 1}}, // VU > GS > EE - {{1, 2, 0}, {1, 2, 0}}, // GS > EE > VU - {{1, 2, 0}, {2, 1, 0}}, // GS > VU > EE - }; - // steal vu's thread if mtvu is off - const u8* this_proc_assigment = - processor_assignment[EmuConfig.Cpu.AffinityControlMode][EmuConfig.Speedhacks.vuThread]; - const u32 ee_index = s_processor_list[this_proc_assigment[0]]; - const u32 vu_index = s_processor_list[this_proc_assigment[1]]; - const u32 gs_index = s_processor_list[this_proc_assigment[2]]; - Console.WriteLn("Processor order assignment: EE=%u, VU=%u, GS=%u", this_proc_assigment[0], this_proc_assigment[1], - this_proc_assigment[2]); + const u32 ee_index = s_processor_list[0]; + const u32 vu_index = s_processor_list[1]; + const u32 gs_index = s_processor_list[mtvu ? 2 : 1]; + INFO_LOG("Processor order assignment: EE={}, VU={}, GS={}", ee_index, vu_index, gs_index); const u64 ee_affinity = static_cast(1) << ee_index; - Console.WriteLn(Color_StrongGreen, "EE thread is on processor %u (0x%llx)", ee_index, ee_affinity); + INFO_LOG(" EE thread is on processor {} (0x{:x})", ee_index, ee_affinity); s_vm_thread_handle.SetAffinity(ee_affinity); if (EmuConfig.Speedhacks.vuThread) { const u64 vu_affinity = static_cast(1) << vu_index; - Console.WriteLn(Color_StrongGreen, "VU thread is on processor %u (0x%llx)", vu_index, vu_affinity); + INFO_LOG(" VU thread is on processor {} (0x{:x})", vu_index, vu_affinity); vu1Thread.GetThreadHandle().SetAffinity(vu_affinity); } else @@ -3552,19 +3529,33 @@ void VMManager::SetEmuThreadAffinities() } const u64 gs_affinity = static_cast(1) << gs_index; - Console.WriteLn(Color_StrongGreen, "GS thread is on processor %u (0x%llx)", gs_index, gs_affinity); + INFO_LOG(" GS thread is on processor {} (0x{:x})", gs_index, gs_affinity); MTGS::GetThreadHandle().SetAffinity(gs_affinity); -} -void VMManager::SetHardwareDependentDefaultSettings(SettingsInterface& si) -{ - SetMTVUAndAffinityControlDefault(si); + // Try to find some threads for the software renderer. + // They should be in the same cluster as the main GS thread. If they're not, for example, + // we had 4 P cores and 6 E cores, let the OS schedule them instead. + s_software_renderer_processor_list.reserve(s_processor_list.size() - (mtvu ? 3 : 2)); + const u32 gs_cluster_id = cpuinfo_get_processor(gs_index)->cluster->cluster_id; + for (size_t i = mtvu ? 3 : 2; i < s_processor_list.size(); i++) + { + const u32 proc_index = s_processor_list[i]; + const u32 proc_cluster_id = cpuinfo_get_processor(proc_index)->cluster->cluster_id; + if (proc_cluster_id != gs_cluster_id) + { + WARNING_LOG(" Only using {} SW threads, processor {} is in cluster {}, but the GS thread is in cluster {}", + s_software_renderer_processor_list.size(), proc_index, proc_cluster_id, gs_cluster_id); + break; + } + + s_software_renderer_processor_list.push_back(proc_index); + } } -const std::vector& VMManager::GetSortedProcessorList() +const std::vector& VMManager::Internal::GetSoftwareRendererProcessorList() { EnsureCPUInfoInitialized(); - return s_processor_list; + return s_software_renderer_processor_list; } void VMManager::ReloadPINE() diff --git a/pcsx2/VMManager.h b/pcsx2/VMManager.h index 755958c04f6c1c..d09601faa16dcd 100644 --- a/pcsx2/VMManager.h +++ b/pcsx2/VMManager.h @@ -224,10 +224,6 @@ namespace VMManager /// Initializes default configuration in the specified file for the specified categories. void SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui); - /// Returns a list of processors in the system, and their corresponding affinity mask. - /// This list is ordered by most performant to least performant for pinning threads to. - const std::vector& GetSortedProcessorList(); - /// Returns the time elapsed in the current play session. u64 GetSessionPlayedTime(); @@ -285,6 +281,9 @@ namespace VMManager /// Resets/clears all execution/code caches. void ClearCPUExecutionCaches(); + /// Returns a list of processors in the system, suitable for pinning for the software renderer. + const std::vector& GetSoftwareRendererProcessorList(); + const std::string& GetELFOverride(); bool IsExecutionInterrupted(); void ELFLoadingOnCPUThread(std::string elf_path); From ab2874749e008003bddcfa818921c000c22170dd Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 16 Jun 2024 15:48:35 +1000 Subject: [PATCH 08/12] CI/AppImage: Explicitly remove libwayland-* --- .github/workflows/scripts/linux/appimage-qt.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/scripts/linux/appimage-qt.sh b/.github/workflows/scripts/linux/appimage-qt.sh index 6b10cee7d4a526..d7cb830b110986 100755 --- a/.github/workflows/scripts/linux/appimage-qt.sh +++ b/.github/workflows/scripts/linux/appimage-qt.sh @@ -55,6 +55,12 @@ declare -a MANUAL_QT_PLUGINS=( "wayland-shell-integration" ) +declare -a REMOVE_LIBS=( + 'libwayland-client.so*' + 'libwayland-cursor.so*' + 'libwayland-egl.so*' +) + set -e LINUXDEPLOY=./linuxdeploy-x86_64.AppImage @@ -158,6 +164,16 @@ for GROUP in "${MANUAL_QT_PLUGINS[@]}"; do done done +# Why do we have to manually remove these libs? Because the linuxdeploy Qt plugin +# copies them, not the "main" linuxdeploy binary, and plugins don't inherit the +# include list... +for lib in "${REMOVE_LIBS[@]}"; do + for libpath in $(find "$OUTDIR/usr/lib" -name "$lib"); do + echo " Removing problematic library ${libpath}." + rm -f "$libpath" + done +done + # Restore unstripped deps (for cache). rm -fr "$DEPSDIR" mv "$DEPSDIR.bak" "$DEPSDIR" From 9c45567d8d105ba1dced043e720382c055daf11b Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sun, 16 Jun 2024 04:00:14 +0100 Subject: [PATCH 09/12] GS/HW: Additional texture shuffle dimension check --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 73b75ada173b49..ba57ca1d1eabd2 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -489,7 +489,9 @@ void GSRendererHW::ConvertSpriteTextureShuffle(u32& process_rg, u32& process_ba, // Dogs will reuse the Z in a different size format for a completely unrelated draw with an FBW of 2, then go back to using it in full width const bool size_is_wrong = tex->m_target ? (static_cast(tex->m_from_target_TEX0.TBW * 64) < tex->m_from_target->m_valid.z / 2) : false; const u32 draw_page_width = std::max(static_cast(m_vt.m_max.p.x + (!(process_ba & SHUFFLE_WRITE) ? 8.9f : 0.9f)) / 64, 1); - if (size_is_wrong || (rt && (rt->m_TEX0.TBW % draw_page_width) == 0)) + const bool single_direction_doubled = (m_vt.m_max.p.y > rt->m_valid.w) != (m_vt.m_max.p.x > rt->m_valid.z); + + if (size_is_wrong || (rt && ((rt->m_TEX0.TBW % draw_page_width) == 0 || single_direction_doubled))) { unsigned int max_tex_draw_width = std::min(static_cast(floor(m_vt.m_max.t.x + (!(process_ba & SHUFFLE_READ) ? 8.9f : 0.9f))), 1 << m_cached_ctx.TEX0.TW); const unsigned int clamp_minu = m_context->CLAMP.MINU; From 8f72c4f4a646eaeada1d240bd2363e53ca954ca1 Mon Sep 17 00:00:00 2001 From: lightningterror <18107717+lightningterror@users.noreply.github.com> Date: Sat, 15 Jun 2024 14:52:50 +0200 Subject: [PATCH 10/12] VMManager: Make sure hw renderer is running for hw renderer OSD messages. --- pcsx2/VMManager.cpp | 91 ++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 49e7a52de2ccc0..2ca0033b84080a 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -3097,12 +3097,56 @@ void VMManager::WarnAboutUnsafeSettings() append(ICON_FA_TACHOMETER_ALT, TRANSLATE_SV("VMManager", "Cycle rate/skip is not at default, this may crash or make games run too slow.")); } - if (EmuConfig.GS.UpscaleMultiplier < 1.0f) - append(ICON_FA_TV, TRANSLATE_SV("VMManager", "Upscale multiplier is below native, this will break rendering.")); - if (!EmuConfig.GS.HWMipmap) + + const bool is_sw_renderer = EmuConfig.GS.Renderer == GSRendererType::SW; + if (!is_sw_renderer) { - append(ICON_FA_IMAGES, - TRANSLATE_SV("VMManager", "Mipmapping is disabled. This may break rendering in some games.")); + // HW renderer settings. + if (EmuConfig.GS.UpscaleMultiplier < 1.0f) + { + append(ICON_FA_TV, + TRANSLATE_SV("VMManager", "Upscale multiplier is below native, this will break rendering.")); + } + if (EmuConfig.GS.TriFilter != TriFiltering::Automatic) + { + append(ICON_FA_PAGER, + TRANSLATE_SV("VMManager", "Trilinear filtering is not set to automatic. This may break rendering in some games.")); + } + if (EmuConfig.GS.AccurateBlendingUnit <= AccBlendLevel::Minimum) + { + append(ICON_FA_PAINT_BRUSH, + TRANSLATE_SV("VMManager", "Blending Accuracy is below Basic, this may break effects in some games.")); + } + if (EmuConfig.GS.HWDownloadMode != GSHardwareDownloadMode::Enabled) + { + append(ICON_FA_DOWNLOAD, + TRANSLATE_SV("VMManager", "Hardware Download Mode is not set to Accurate, this may break rendering in some games.")); + } + if (EmuConfig.GS.GPUPaletteConversion) + { + append(ICON_FA_EXCLAMATION_CIRCLE, + TRANSLATE_SV("VMManager", "GPU Palette Conversion is enabled, this may reduce performance.")); + } + if (EmuConfig.GS.TexturePreloading != TexturePreloadingLevel::Full) + { + append(ICON_FA_EXCLAMATION_CIRCLE, + TRANSLATE_SV("VMManager", "Texture Preloading is not Full, this may reduce performance.")); + } + if (EmuConfig.GS.UserHacks_EstimateTextureRegion) + { + append(ICON_FA_EXCLAMATION_CIRCLE, + TRANSLATE_SV("VMManager", "Estimate texture region is enabled, this may reduce performance.")); + } + if (EmuConfig.GS.DumpReplaceableTextures) + { + append(ICON_FA_EXCLAMATION_CIRCLE, + TRANSLATE_SV("VMManager", "Texture dumping is enabled, this will continually dump textures to disk.")); + } + if (!EmuConfig.GS.HWMipmap) + { + append(ICON_FA_IMAGES, + TRANSLATE_SV("VMManager", "Mipmapping is disabled. This may break rendering in some games.")); + } } if (EmuConfig.GS.TextureFiltering != BiFiltering::PS2) { @@ -3110,23 +3154,6 @@ void VMManager::WarnAboutUnsafeSettings() TRANSLATE_SV("VMManager", "Texture filtering is not set to Bilinear (PS2). This will break rendering in some games.")); } - if (EmuConfig.GS.TriFilter != TriFiltering::Automatic) - { - append( - ICON_FA_PAGER, TRANSLATE_SV("VMManager", - "Trilinear filtering is not set to automatic. This may break rendering in some games.")); - } - if (EmuConfig.GS.AccurateBlendingUnit <= AccBlendLevel::Minimum) - { - append(ICON_FA_PAINT_BRUSH, - TRANSLATE_SV("VMManager", "Blending Accuracy is below Basic, this may break effects in some games.")); - } - if (EmuConfig.GS.HWDownloadMode != GSHardwareDownloadMode::Enabled) - { - append(ICON_FA_DOWNLOAD, - TRANSLATE_SV( - "VMManager", "Hardware Download Mode is not set to Accurate, this may break rendering in some games.")); - } if (EmuConfig.Cpu.FPUFPCR.GetRoundMode() != FPRoundMode::ChopZero) { append(ICON_PF_MICROCHIP, @@ -3237,26 +3264,6 @@ void VMManager::WarnAboutUnsafeSettings() append(ICON_FA_EXCLAMATION_CIRCLE, TRANSLATE_SV("VMManager", "mVU Flag Hack is not enabled, this may reduce performance.")); } - if (EmuConfig.GS.GPUPaletteConversion) - { - append(ICON_FA_EXCLAMATION_CIRCLE, - TRANSLATE_SV("VMManager", "GPU Palette Conversion is enabled, this may reduce performance.")); - } - if (EmuConfig.GS.TexturePreloading != TexturePreloadingLevel::Full) - { - append(ICON_FA_EXCLAMATION_CIRCLE, - TRANSLATE_SV("VMManager", "Texture Preloading is not Full, this may reduce performance.")); - } - if (EmuConfig.GS.UserHacks_EstimateTextureRegion) - { - append(ICON_FA_EXCLAMATION_CIRCLE, - TRANSLATE_SV("VMManager", "Estimate texture region is enabled, this may reduce performance.")); - } - if (EmuConfig.GS.DumpReplaceableTextures) - { - append(ICON_FA_EXCLAMATION_CIRCLE, - TRANSLATE_SV("VMManager", "Texture dumping is enabled, this will continually dump textures to disk.")); - } if (!messages.empty()) { From f565da6c583725d34870abe3e92317cd30656bea Mon Sep 17 00:00:00 2001 From: lightningterror <18107717+lightningterror@users.noreply.github.com> Date: Sat, 15 Jun 2024 15:14:27 +0200 Subject: [PATCH 11/12] GameDB: Make sure hw renderer is running for hw renderer OSD messages. --- pcsx2/GameDatabase.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pcsx2/GameDatabase.cpp b/pcsx2/GameDatabase.cpp index 10c5ee21ab8973..8e2fbb129a772a 100644 --- a/pcsx2/GameDatabase.cpp +++ b/pcsx2/GameDatabase.cpp @@ -688,6 +688,7 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions& // Only apply GS HW fixes if the user hasn't manually enabled HW fixes. const bool apply_auto_fixes = !config.ManualUserHacks; + const bool is_sw_renderer = EmuConfig.GS.Renderer == GSRendererType::SW; if (!apply_auto_fixes) Console.Warning("[GameDB] Manual GS hardware renderer fixes are enabled, not using automatic hardware renderer fixes from GameDB."); @@ -873,7 +874,7 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions& case GSHWFixId::RecommendedBlendingLevel: { - if (value >= 0 && value <= static_cast(AccBlendLevel::Maximum) && static_cast(EmuConfig.GS.AccurateBlendingUnit) < value) + if (!is_sw_renderer && value >= 0 && value <= static_cast(AccBlendLevel::Maximum) && static_cast(EmuConfig.GS.AccurateBlendingUnit) < value) { Host::AddKeyedOSDMessage("HWBlendingWarning", fmt::format(TRANSLATE_FS("GameDatabase", @@ -916,7 +917,7 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions& // fixup skipdraw range just in case the db has a bad range (but the linter should catch this) config.SkipDrawEnd = std::max(config.SkipDrawStart, config.SkipDrawEnd); - if (!disabled_fixes.empty()) + if (!is_sw_renderer && !disabled_fixes.empty()) { Host::AddKeyedOSDMessage("HWFixesWarning", fmt::format(ICON_FA_MAGIC " {}\n{}", From d62602820393953fd405a51bdf4d179dd0d8b26d Mon Sep 17 00:00:00 2001 From: void Date: Sun, 16 Jun 2024 23:45:47 +0200 Subject: [PATCH 12/12] UI: fix invert settings being incorrectly set in big picture mode --- pcsx2/ImGui/FullscreenUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index 6266c3190b2534..47aa60bde6f209 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -2649,7 +2649,7 @@ void FullscreenUI::DrawSettingInfoSetting(SettingsInterface* bsi, const char* se case SettingInfo::Type::IntegerList: DrawIntListSetting( - bsi, title.c_str(), si.description, section, key, si.IntegerDefaultValue(), si.options, 0, si.IntegerMinValue(), true); + bsi, title.c_str(), si.description, section, key, si.IntegerDefaultValue(), si.options, 0, true, si.IntegerMinValue()); break; case SettingInfo::Type::Float: