Merge branch 'master' into headers

This commit is contained in:
Megamouse 2025-12-01 10:14:51 +01:00 committed by GitHub
commit e03848576d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 67 additions and 25 deletions

View file

@ -8,11 +8,12 @@ Other instructions may be found [here](https://wiki.rpcs3.net/index.php?title=Bu
### Windows 10 or later
The following tools are required to build RPCS3 on Windows 10 or later:
- [Visual Studio 2022](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
- [Visual Studio 2022/2026](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
- **Optional** - [CMake 3.28.0+](https://www.cmake.org/download/) (add to PATH)
**NOTES:**
- **Visual Studio 2022** integrates **CMake 3.29+** and it also supports both the `sln` solution (`.sln`, `.vcxproj`) and `CMake` solution (`CMakeLists.txt`, `CMakePresets.json`).
- **Visual Studio 2026** needs at least **CMake 4.2.0+**.
- **Visual Studio 2022/2026** integrates **CMake 3.29+** and it also supports both the `sln` solution (`.sln`, `.vcxproj`) and `CMake` solution (`CMakeLists.txt`, `CMakePresets.json`).
See sections [Building with Visual Studio sln solution](#building-with-visual-studio-sln-solution) and [Building with Visual Studio CMake solution](#building-with-visual-studio-cmake-solution)
on how to build the project with **Visual Studio**.
- Install and use this standalone **CMake** tool just in case of your preference. See section [Building with standalone CMake tool](#building-with-standalone-cmake-tool) on how to build the project

View file

@ -720,9 +720,19 @@ void spu_cache::initialize(bool build_existing_cache)
}
// SPU cache file (version + block size type)
const std::string loc = ppu_cache + "spu-" + fmt::to_lower(g_cfg.core.spu_block_size.to_string()) + "-v1-tane.dat";
const std::string filename = "spu-" + fmt::to_lower(g_cfg.core.spu_block_size.to_string()) + "-v1-tane.dat";
const std::string loc = ppu_cache + filename;
const std::string loc_debug = fs::get_cache_dir() + "DEBUG/" + filename;
spu_cache cache(loc);
bool is_debug = false;
if (fs::is_file(loc_debug))
{
spu_log.success("SPU Cache override applied!");
is_debug = true;
}
spu_cache cache(is_debug ? loc_debug : loc);
if (!cache)
{
@ -4963,6 +4973,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
u32 lsa_last_pc = SPU_LS_SIZE; // PC of first LSA write
u32 get_pc = SPU_LS_SIZE; // PC of GETLLAR
u32 put_pc = SPU_LS_SIZE; // PC of PUTLLC
u32 rdatomic_pc = SPU_LS_SIZE; // PC of last RdAtomcStat read
reg_state_t ls{}; // state of LS load/store address register
reg_state_t ls_offs = reg_state_t::from_value(0); // Added value to ls
reg_state_t lsa{}; // state of LSA register on GETLLAR
@ -5008,7 +5019,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
ls_invalid = true;
ls_write |= write;
if (write)
if (ls_write)
{
return discard();
}
@ -6323,6 +6334,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
break;
}
atomic16->rdatomic_pc = pos;
const auto it = atomic16_all.find(pos);
if (it == atomic16_all.end())
@ -7263,7 +7276,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
for (const auto& [pc_commited, pattern] : atomic16_all)
{
if (!pattern.active)
if (!pattern.active || pattern.lsa_pc >= pattern.rdatomic_pc)
{
continue;
}
@ -7273,6 +7286,17 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
continue;
}
std::string pattern_hash;
{
sha1_context ctx;
u8 output[20]{};
sha1_starts(&ctx);
sha1_update(&ctx, reinterpret_cast<const u8*>(result.data.data()) + (pattern.lsa_pc - result.lower_bound), pattern.rdatomic_pc - pattern.lsa_pc);
sha1_finish(&ctx, output);
fmt::append(pattern_hash, "%s", fmt::base57(output));
}
union putllc16_or_0_info
{
u64 data;
@ -7295,8 +7319,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
value.required_pc = pattern.required_pc;
}
spu_log.success("PUTLLC0 Pattern Detected! (put_pc=0x%x, %s) (putllc0=%d, putllc16+0=%d, all=%d)", pattern.put_pc, func_hash, ++stats.nowrite, ++stats.single, +stats.all);
add_pattern(false, inst_attr::putllc0, pattern.put_pc - lsa, value.data);
// spu_log.success("PUTLLC0 Pattern Detected! (put_pc=0x%x, %s) (putllc0=%d, putllc16+0=%d, all=%d)", pattern.put_pc, func_hash, ++stats.nowrite, ++stats.single, +stats.all);
// add_pattern(false, inst_attr::putllc0, pattern.put_pc - lsa, value.data);
continue;
}
@ -7363,16 +7387,35 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
value.reg2 = pattern.reg2;
}
bool allow_pattern = true;
if (g_cfg.core.spu_accurate_reservations)
{
// Because enabling it is a hack, as it turns out
// continue;
// The problem with PUTLLC16 optimization, that it is in theory correct at the bounds of the spu function.
// But if the SPU code reuses the cache line data observed, it is not truly atomic.
// So we may enable it only for known cases where SPU atomic data is not used after the function leaves.
// So the two options are:
// 1. Atomic compare exchange 16 bytes operation. (rest of data is not read) -> good for RPCS3 to optimize.
// 2. Fetch 128 bytes (read them later), modify only 16 bytes. -> Bad for RPCS3 to optimize.
// This difference cannot be known at analyzer time but from observing callers.
static constexpr std::initializer_list<std::string_view> allowed_patterns =
{
"620oYSe8uQqq9eTkhWfMqoEXX0us"sv, // CellSpurs JobChain acquire pattern
};
allow_pattern = std::any_of(allowed_patterns.begin(), allowed_patterns.end(), FN(pattern_hash == x));
}
add_pattern(false, inst_attr::putllc16, pattern.put_pc - result.entry_point, value.data);
if (allow_pattern)
{
add_pattern(false, inst_attr::putllc16, pattern.put_pc - result.entry_point, value.data);
}
spu_log.success("PUTLLC16 Pattern Detected! (mem_count=%d, put_pc=0x%x, pc_rel=%d, offset=0x%x, const=%u, two_regs=%d, reg=%u, runtime=%d, 0x%x-%s) (putllc0=%d, putllc16+0=%d, all=%d)"
, pattern.mem_count, pattern.put_pc, value.type == v_relative, value.off18, value.type == v_const, value.type == v_reg2, value.reg, value.runtime16_select, entry_point, func_hash, +stats.nowrite, ++stats.single, +stats.all);
spu_log.success("PUTLLC16 Pattern Detected! (mem_count=%d, put_pc=0x%x, pc_rel=%d, offset=0x%x, const=%u, two_regs=%d, reg=%u, runtime=%d, 0x%x-%s, pattern-hash=%s) (putllc0=%d, putllc16+0=%d, all=%d)"
, pattern.mem_count, pattern.put_pc, value.type == v_relative, value.off18, value.type == v_const, value.type == v_reg2, value.reg, value.runtime16_select, entry_point, func_hash, pattern_hash, +stats.nowrite, ++stats.single, +stats.all);
}
for (const auto& [read_pc, pattern] : rchcnt_loop_all)

View file

@ -668,10 +668,9 @@ void emu_settings::EnhanceSpinBox(QSpinBox* spinbox, emu_settings_type type, con
spinbox->setRange(min, max);
spinbox->setValue(val);
connect(spinbox, &QSpinBox::textChanged, this, [type, spinbox, this](const QString& /* text*/)
connect(spinbox, &QSpinBox::valueChanged, this, [type, this](int value)
{
if (!spinbox) return;
SetSetting(type, spinbox->cleanText().toStdString());
SetSetting(type, fmt::format("%d", value));
});
connect(this, &emu_settings::RestoreDefaultsSignal, spinbox, [def, spinbox]()
@ -724,10 +723,9 @@ void emu_settings::EnhanceDoubleSpinBox(QDoubleSpinBox* spinbox, emu_settings_ty
spinbox->setRange(min, max);
spinbox->setValue(val);
connect(spinbox, &QDoubleSpinBox::textChanged, this, [type, spinbox, this](const QString& /* text*/)
connect(spinbox, &QDoubleSpinBox::valueChanged, this, [type, this](double value)
{
if (!spinbox) return;
SetSetting(type, spinbox->cleanText().toStdString());
SetSetting(type, fmt::format("%f", value));
});
connect(this, &emu_settings::RestoreDefaultsSignal, spinbox, [def, spinbox]()

View file

@ -432,9 +432,9 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDis
scroll(0); // Refresh
});
connect(sb_words, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [=, this]()
connect(sb_words, &QSpinBox::valueChanged, this, [this](int value)
{
m_colcount = 1 << sb_words->value();
m_colcount = 1 << value;
ShowMemory();
});

View file

@ -105,7 +105,7 @@ pad_motion_settings_dialog::pad_motion_settings_dialog(QDialog* parent, std::sha
m_config_entries[i]->mirrored.set(state != Qt::Unchecked);
});
connect(m_shifts[i], QOverload<int>::of(&QSpinBox::valueChanged), this, [this, i](int value)
connect(m_shifts[i], &QSpinBox::valueChanged, this, [this, i](int value)
{
std::lock_guard lock(m_config_mutex);
m_config_entries[i]->shift.set(value);

View file

@ -123,8 +123,8 @@ patch_manager_dialog::patch_manager_dialog(std::shared_ptr<gui_settings> gui_set
handle_config_value_changed(ui->configurable_combo_box->itemData(index).toDouble());
}
});
connect(ui->configurable_spin_box, QOverload<int>::of(&QSpinBox::valueChanged), this, &patch_manager_dialog::handle_config_value_changed);
connect(ui->configurable_double_spin_box, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &patch_manager_dialog::handle_config_value_changed);
connect(ui->configurable_spin_box, &QSpinBox::valueChanged, this, &patch_manager_dialog::handle_config_value_changed);
connect(ui->configurable_double_spin_box, &QDoubleSpinBox::valueChanged, this, &patch_manager_dialog::handle_config_value_changed);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close);
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button)
{

View file

@ -281,7 +281,7 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs)
m_accel_spin_boxes.push_back(mouse_acceleration_spin_box);
mouse_acceleration_spin_box->setRange(0.1, 10.0);
mouse_acceleration_spin_box->setValue(config->mouse_acceleration.get() / 100.0);
connect(mouse_acceleration_spin_box, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, [player](double value)
connect(mouse_acceleration_spin_box, &QDoubleSpinBox::valueChanged, this, [player](double value)
{
auto& config = ::at32(g_cfg_raw_mouse.players, player)->mouse_acceleration;
config.set(std::clamp(value * 100.0, config.min, config.max));