1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

SPURS limiter tweaks

This commit is contained in:
Elad Ashkenazi 2024-10-07 12:54:08 +03:00 committed by Elad
parent 36da83592a
commit d51d5ce86d
2 changed files with 70 additions and 30 deletions

View File

@ -1839,11 +1839,7 @@ void spu_thread::cpu_task()
if (group->name.ends_with("CellSpursKernelGroup"sv) && vm::check_addr(arg)) if (group->name.ends_with("CellSpursKernelGroup"sv) && vm::check_addr(arg))
{ {
spurs_addr = arg; spurs_addr = arg;
group->spurs_running++;
if (group->max_run != group->max_num)
{
group->spurs_running++;
}
} }
else else
{ {
@ -1900,7 +1896,7 @@ void spu_thread::cpu_task()
allow_interrupts_in_cpu_work = false; allow_interrupts_in_cpu_work = false;
} }
if (spurs_addr != invalid_spurs && group->max_run != group->max_num) if (spurs_addr != invalid_spurs)
{ {
if (group->spurs_running.exchange(0)) if (group->spurs_running.exchange(0))
{ {
@ -4894,20 +4890,54 @@ bool spu_thread::process_mfc_cmd()
// Avoid logging useless commands if there is no reservation // Avoid logging useless commands if there is no reservation
const bool dump = g_cfg.core.mfc_debug && raddr; const bool dump = g_cfg.core.mfc_debug && raddr;
const bool is_spurs_task_wait = pc == 0x11e4 && spurs_addr == raddr && group->max_run != group->max_num && !spurs_waited; const bool is_spurs_task_wait = pc == 0x11e4 && spurs_addr == raddr && g_cfg.core.max_spurs_threads != g_cfg.core.max_spurs_threads.def && !spurs_waited;
if (is_spurs_task_wait) if (is_spurs_task_wait)
{ {
// Wait for other threads to complete their tasks (temporarily) // Wait for other threads to complete their tasks (temporarily)
u32 max_run = group->max_run; u32 max_run = group->max_run;
u32 prev_running = group->spurs_running; u32 prev_running = group->spurs_running.fetch_op([max_run](u32& x)
{
if (x >= max_run)
{
x--;
return true;
}
if (prev_running > max_run) return false;
}).first;
if (prev_running == max_run && prev_running != group->max_num)
{
group->spurs_running.notify_one();
if (group->spurs_running == max_run - 1)
{
// Try to let another thread slip in and take over execution
thread_ctrl::wait_for(300);
// Try to quit waiting
prev_running = group->spurs_running.fetch_op([max_run](u32& x)
{
if (x < max_run)
{
x++;
return true;
}
return false;
}).first;
}
}
if (prev_running >= max_run)
{ {
const u64 before = get_system_time(); const u64 before = get_system_time();
u64 current = before; u64 current = before;
lv2_obj::prepare_for_sleep(*this);
while (true) while (true)
{ {
if (is_stopped()) if (is_stopped())
@ -4915,24 +4945,37 @@ bool spu_thread::process_mfc_cmd()
break; break;
} }
thread_ctrl::wait_on(group->spurs_running, prev_running, 5000 - (current - before)); thread_ctrl::wait_on(group->spurs_running, prev_running, 10000 - (current - before));
max_run = group->max_run; max_run = group->max_run;
prev_running = group->spurs_running;
prev_running = group->spurs_running.fetch_op([max_run](u32& x)
{
if (x < max_run)
{
x++;
return true;
}
if (prev_running <= max_run) return false;
}).first;
if (prev_running < max_run)
{ {
break; break;
} }
current = get_system_time(); current = get_system_time();
if (current - before >= 5000u) if (current - before >= 10000u)
{ {
// Timed-out // Timed-out
break; break;
} }
} }
state += cpu_flag::temp;
static_cast<void>(test_stopped());
} }
} }
@ -5545,7 +5588,7 @@ s64 spu_thread::get_ch_value(u32 ch)
return events.events & mask1; return events.events & mask1;
} }
const bool is_spurs_task_wait = pc == 0x11a8 && spurs_addr == raddr && group->max_run != group->max_num && !spurs_waited; const bool is_spurs_task_wait = pc == 0x11a8 && spurs_addr == raddr && g_cfg.core.max_spurs_threads != g_cfg.core.max_spurs_threads.def && !spurs_waited;
const auto wait_spurs_task = [&] const auto wait_spurs_task = [&]
{ {
@ -5572,6 +5615,8 @@ s64 spu_thread::get_ch_value(u32 ch)
const u64 before = get_system_time(); const u64 before = get_system_time();
u64 current = before; u64 current = before;
lv2_obj::prepare_for_sleep(*this);
spurs_waited = true; spurs_waited = true;
while (true) while (true)
@ -5581,7 +5626,7 @@ s64 spu_thread::get_ch_value(u32 ch)
break; break;
} }
thread_ctrl::wait_on(group->spurs_running, prev_running, 5000 - (current - before)); thread_ctrl::wait_on(group->spurs_running, prev_running, 10000u - (current - before));
max_run = group->max_run; max_run = group->max_run;
@ -5603,7 +5648,7 @@ s64 spu_thread::get_ch_value(u32 ch)
current = get_system_time(); current = get_system_time();
if (current - before >= 5000u) if (current - before >= 10000u)
{ {
// Timed-out // Timed-out
group->spurs_running++; group->spurs_running++;
@ -5628,9 +5673,17 @@ s64 spu_thread::get_ch_value(u32 ch)
return false; return false;
}).first; }).first;
if (prev_running == group->max_run) if (prev_running == group->max_run && prev_running < group->max_num)
{ {
group->spurs_running.notify_one(); group->spurs_running.notify_one();
spurs_waited = true;
if (group->spurs_running == prev_running - 1)
{
// Try to let another thread slip in and take over execution
thread_ctrl::wait_for(300);
}
} }
} }

View File

@ -731,19 +731,6 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
if (++group->init == group->max_num) if (++group->init == group->max_num)
{ {
if (u32 max_threads = std::min<u32>(g_cfg.core.max_spurs_threads, group->max_num); group->max_num > max_threads)
{
constexpr std::string_view spurs_suffix = "CellSpursKernelGroup"sv;
if (group->name.ends_with(spurs_suffix) && !group->name.substr(0, group->name.size() - spurs_suffix.size()).ends_with("_libsail"))
{
// Hack: don't run more SPURS threads than specified.
group->max_run = max_threads;
spu_log.success("HACK: '%s' (0x%x) limited to %u threads.", group->name, group_id, max_threads);
}
}
const auto old = group->run_state.compare_and_swap(SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED, SPU_THREAD_GROUP_STATUS_INITIALIZED); const auto old = group->run_state.compare_and_swap(SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED, SPU_THREAD_GROUP_STATUS_INITIALIZED);
if (old == SPU_THREAD_GROUP_STATUS_DESTROYED) if (old == SPU_THREAD_GROUP_STATUS_DESTROYED)