mirror of
https://github.com/ARMSX2/ARMSX3.git
synced 2026-08-24 16:58:52 -07:00
RSX: publish GET only when it has advanced
The drain fix made every path that can idle or block publish GET immediately, which is required for correctness: a producer waiting on ring space needs to see the progress we made before we stopped consuming. It publishes far more often than that requires. The empty and busy cases return straight to the run loop, so a ring that has gone quiet re-enters them once per iteration with GET unmoved. Web of Shadows measured 137000 loop iterations per frame against 46000 method dispatches; the remaining 91000 were republishing a value the guest already had. GET shares a 64-byte line with put, which the guest PPU writes from another cluster, so each of those is a coherence miss taken against the thread feeding the ring. The cost lands on the producer rather than on the RSX, which is why it presented as a freeze with sound still playing: the PPU stalls on the contended line while threads that never touch it keep running. GET is ours to write, so tracking the last published value and skipping an unchanged store keeps the guarantee -- progress is still announced exactly once after the last advance -- without the repeats.
This commit is contained in:
@@ -46,13 +46,27 @@ namespace rsx
|
||||
return;
|
||||
}
|
||||
|
||||
m_ctrl->get.release(m_internal_get);
|
||||
m_ctrl->get.release(m_published_get = m_internal_get);
|
||||
}
|
||||
|
||||
void FIFO_control::sync_get_force() const
|
||||
{
|
||||
m_get_sync_counter = 0;
|
||||
m_ctrl->get.release(m_internal_get);
|
||||
|
||||
// Publish real progress only. The drain paths call this every time they are entered,
|
||||
// and while the ring is empty or blocked that is once per run loop iteration with GET
|
||||
// unmoved: measured at ~91000 of 137000 iterations per frame in Spider-Man: Web of
|
||||
// Shadows, every one of them a coherence miss on the line holding put.
|
||||
//
|
||||
// The cost lands on the guest rather than on us, which is why it reads as a freeze
|
||||
// with sound: the PPU feeding the ring is the thread contending for that line, so it
|
||||
// stops producing while threads that never touch it carry on.
|
||||
if (m_published_get == m_internal_get)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_ctrl->get.release(m_published_get = m_internal_get);
|
||||
}
|
||||
|
||||
void FIFO_control::restore_state(u32 cmd, u32 count)
|
||||
@@ -266,7 +280,7 @@ namespace rsx
|
||||
}
|
||||
|
||||
// Update ctrl registers
|
||||
m_ctrl->get.release(m_internal_get = get);
|
||||
m_ctrl->get.release(m_published_get = m_internal_get = get);
|
||||
m_remaining_commands = 0;
|
||||
}
|
||||
|
||||
@@ -471,7 +485,7 @@ namespace rsx
|
||||
|
||||
if (!count)
|
||||
{
|
||||
m_ctrl->get.release(m_internal_get += 4);
|
||||
m_ctrl->get.release(m_published_get = (m_internal_get += 4));
|
||||
data.reg = FIFO_NOP;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -198,6 +198,17 @@ namespace rsx
|
||||
void sync_get_force() const;
|
||||
mutable u32 m_get_sync_counter = 0;
|
||||
|
||||
// Last value actually stored into ctrl->get. GET is ours to write -- the guest only
|
||||
// writes put -- so an unchanged value need not be republished.
|
||||
//
|
||||
// This matters because the force paths are re-entered continuously while GET stands
|
||||
// still. An empty or blocked ring returns to the run loop immediately, so a producer
|
||||
// that has gone quiet leaves us taking the cross-cluster miss above tens of thousands
|
||||
// of times a frame against a line the guest PPU is trying to write. Announcing
|
||||
// progress once is the whole requirement; announcing it repeatedly holds up the
|
||||
// producer we are waiting for.
|
||||
mutable u32 m_published_get = umax;
|
||||
|
||||
// Snapshot of g_cfg.core.rsx_fifo_accuracy, refreshed once per packet. Reading the
|
||||
// config goes through a seq_cst atomic load, an ldar on ARM64 the compiler cannot
|
||||
// hoist, and it was consulted once per FIFO argument.
|
||||
|
||||
Reference in New Issue
Block a user