mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
rsx: FIFO wake-up pause control
This commit is contained in:
parent
2984300385
commit
85695c8bac
@ -477,20 +477,21 @@ namespace rsx
|
|||||||
fmt::throw_exception("Unexpected command 0x%x" HERE, cmd);
|
fmt::throw_exception("Unexpected command 0x%x" HERE, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (performance_counters.state != FIFO_state::running)
|
if (const auto state = performance_counters.state;
|
||||||
|
state != FIFO_state::running)
|
||||||
{
|
{
|
||||||
//Update performance counters with time spent in idle mode
|
performance_counters.state = FIFO_state::running;
|
||||||
performance_counters.idle_time += (get_system_time() - performance_counters.FIFO_idle_timestamp);
|
|
||||||
|
|
||||||
if (performance_counters.state == FIFO_state::spinning)
|
// Hack: Delay FIFO wake-up according to setting
|
||||||
|
// NOTE: The typical spin setup is a NOP followed by a jump-to-self
|
||||||
|
// NOTE: There is a small delay when the jump address is dynamically edited by cell
|
||||||
|
if (state != FIFO_state::nop)
|
||||||
{
|
{
|
||||||
//TODO: Properly simulate FIFO wake delay.
|
fifo_wake_delay();
|
||||||
//NOTE: The typical spin setup is a NOP followed by a jump-to-self
|
|
||||||
//NOTE: There is a small delay when the jump address is dynamically edited by cell
|
|
||||||
busy_wait(3000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
performance_counters.state = FIFO_state::running;
|
// Update performance counters with time spent in idle mode
|
||||||
|
performance_counters.idle_time += (get_system_time() - performance_counters.FIFO_idle_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -2273,6 +2273,61 @@ namespace rsx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void thread::fifo_wake_delay(u64 div)
|
||||||
|
{
|
||||||
|
// TODO: Nanoseconds accuracy
|
||||||
|
u64 remaining = g_cfg.video.driver_wakeup_delay;
|
||||||
|
|
||||||
|
if (!remaining)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some cases do not need full delay
|
||||||
|
remaining = ::aligned_div(remaining, div);
|
||||||
|
const u64 until = get_system_time() + remaining;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
// NOTE: Assumption that timer initialization has succeeded
|
||||||
|
u64 host_min_quantum = remaining <= 1000 ? 10 : 50;
|
||||||
|
#else
|
||||||
|
// Host scheduler quantum for windows (worst case)
|
||||||
|
// NOTE: On ps3 this function has very high accuracy
|
||||||
|
constexpr u64 host_min_quantum = 500;
|
||||||
|
#endif
|
||||||
|
if (remaining >= host_min_quantum)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
// Do not wait for the last quantum to avoid loss of accuracy
|
||||||
|
thread_ctrl::wait_for(remaining - ((remaining % host_min_quantum) + host_min_quantum), false);
|
||||||
|
#else
|
||||||
|
// Wait on multiple of min quantum for large durations to avoid overloading low thread cpus
|
||||||
|
thread_ctrl::wait_for(remaining - (remaining % host_min_quantum), false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// TODO: Determine best value for yield delay
|
||||||
|
else if (remaining >= host_min_quantum / 2)
|
||||||
|
{
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
busy_wait(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
const u64 current = get_system_time();
|
||||||
|
|
||||||
|
if (current >= until)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
remaining = until - current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 thread::get_fifo_cmd()
|
u32 thread::get_fifo_cmd()
|
||||||
{
|
{
|
||||||
// Last fifo cmd for logging and utility
|
// Last fifo cmd for logging and utility
|
||||||
|
@ -607,6 +607,7 @@ namespace rsx
|
|||||||
atomic_t<bool> external_interrupt_ack{ false };
|
atomic_t<bool> external_interrupt_ack{ false };
|
||||||
void flush_fifo();
|
void flush_fifo();
|
||||||
void recover_fifo();
|
void recover_fifo();
|
||||||
|
void fifo_wake_delay(u64 div = 1);
|
||||||
u32 get_fifo_cmd();
|
u32 get_fifo_cmd();
|
||||||
|
|
||||||
// Performance approximation counters
|
// Performance approximation counters
|
||||||
|
@ -76,9 +76,23 @@ namespace rsx
|
|||||||
const auto& sema = vm::_ref<atomic_be_t<u32>>(addr);
|
const auto& sema = vm::_ref<atomic_be_t<u32>>(addr);
|
||||||
|
|
||||||
// TODO: Remove vblank semaphore hack
|
// TODO: Remove vblank semaphore hack
|
||||||
if (sema == arg || addr == rsx->device_addr + 0x30) return;
|
if (addr == rsx->device_addr + 0x30) return;
|
||||||
|
|
||||||
rsx->flush_fifo();
|
if (sema == arg)
|
||||||
|
{
|
||||||
|
// Flip semaphore doesnt need wake-up delay
|
||||||
|
if (addr != rsx->label_addr + 0x10)
|
||||||
|
{
|
||||||
|
rsx->flush_fifo();
|
||||||
|
rsx->fifo_wake_delay(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rsx->flush_fifo();
|
||||||
|
}
|
||||||
|
|
||||||
u64 start = get_system_time();
|
u64 start = get_system_time();
|
||||||
while (sema != arg)
|
while (sema != arg)
|
||||||
@ -113,6 +127,7 @@ namespace rsx
|
|||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rsx->fifo_wake_delay();
|
||||||
rsx->performance_counters.idle_time += (get_system_time() - start);
|
rsx->performance_counters.idle_time += (get_system_time() - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +502,8 @@ struct cfg_root : cfg::node
|
|||||||
cfg::_int<50, 800> resolution_scale_percent{this, "Resolution Scale", 100};
|
cfg::_int<50, 800> resolution_scale_percent{this, "Resolution Scale", 100};
|
||||||
cfg::_int<0, 16> anisotropic_level_override{this, "Anisotropic Filter Override", 0};
|
cfg::_int<0, 16> anisotropic_level_override{this, "Anisotropic Filter Override", 0};
|
||||||
cfg::_int<1, 1024> min_scalable_dimension{this, "Minimum Scalable Dimension", 16};
|
cfg::_int<1, 1024> min_scalable_dimension{this, "Minimum Scalable Dimension", 16};
|
||||||
cfg::_int<0, 30000000> driver_recovery_timeout{this, "Driver Recovery Timeout", 1000000};
|
cfg::_int<0, 30000000> driver_recovery_timeout{this, "Driver Recovery Timeout", 1000000, true};
|
||||||
|
cfg::_int<0, 16667> driver_wakeup_delay{this, "Driver Wake-Up Delay", 1, true};
|
||||||
cfg::_int<1, 500> vblank_rate{this, "Vblank Rate", 60}; // Changing this from 60 may affect game speed in unexpected ways
|
cfg::_int<1, 500> vblank_rate{this, "Vblank Rate", 60}; // Changing this from 60 may affect game speed in unexpected ways
|
||||||
|
|
||||||
struct node_vk : cfg::node
|
struct node_vk : cfg::node
|
||||||
|
Loading…
x
Reference in New Issue
Block a user