mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 06:21:26 +12:00
SPU: Implement S1/S2 (SNR) events (closes #8789)
Add TSX path in push_snr() Add locks bits in ch_events
This commit is contained in:
parent
b57a9c31f0
commit
a806be8bc4
2 changed files with 92 additions and 13 deletions
|
@ -1248,15 +1248,79 @@ void spu_thread::push_snr(u32 number, u32 value)
|
||||||
// Get channel
|
// Get channel
|
||||||
const auto channel = number & 1 ? &ch_snr2 : &ch_snr1;
|
const auto channel = number & 1 ? &ch_snr2 : &ch_snr1;
|
||||||
|
|
||||||
// Check corresponding SNR register settings
|
// Prepare some data
|
||||||
if ((snr_config >> number) & 1)
|
const u32 event_bit = SPU_EVENT_S1 >> (number & 1);
|
||||||
|
const u32 bitor_bit = (snr_config >> number) & 1;
|
||||||
|
|
||||||
|
if (g_use_rtm)
|
||||||
{
|
{
|
||||||
channel->push_or(value);
|
bool channel_notify = false;
|
||||||
|
bool thread_notify = false;
|
||||||
|
|
||||||
|
const bool ok = utils::tx_start([&]
|
||||||
|
{
|
||||||
|
channel_notify = (channel->data.raw() & spu_channel::bit_wait) != 0;
|
||||||
|
thread_notify = (channel->data.raw() & spu_channel::bit_count) == 0;
|
||||||
|
|
||||||
|
if (bitor_bit)
|
||||||
|
{
|
||||||
|
channel->data.raw() &= ~spu_channel::bit_wait;
|
||||||
|
channel->data.raw() |= spu_channel::bit_count | value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
channel->push(value);
|
channel->data.raw() = spu_channel::bit_count | value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (thread_notify)
|
||||||
|
{
|
||||||
|
ch_events.raw().events |= event_bit;
|
||||||
|
|
||||||
|
if (ch_events.raw().mask & event_bit)
|
||||||
|
{
|
||||||
|
ch_events.raw().count = 1;
|
||||||
|
thread_notify = ch_events.raw().waiting != 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread_notify = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
if (channel_notify)
|
||||||
|
channel->data.notify_one();
|
||||||
|
if (thread_notify)
|
||||||
|
this->notify();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock event channel in case it needs event notification
|
||||||
|
ch_events.atomic_op([](ch_events_t& ev)
|
||||||
|
{
|
||||||
|
ev.locks++;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check corresponding SNR register settings
|
||||||
|
if (bitor_bit)
|
||||||
|
{
|
||||||
|
if (channel->push_or(value))
|
||||||
|
set_events(event_bit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (channel->push(value))
|
||||||
|
set_events(event_bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
ch_events.atomic_op([](ch_events_t& ev)
|
||||||
|
{
|
||||||
|
ev.locks--;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_thread::do_dma_transfer(const spu_mfc_cmd& args)
|
void spu_thread::do_dma_transfer(const spu_mfc_cmd& args)
|
||||||
|
@ -2465,6 +2529,7 @@ spu_thread::ch_events_t spu_thread::get_events(u32 mask_hint, bool waiting, bool
|
||||||
fmt::throw_exception("SPU Events not implemented (mask=0x%x)" HERE, mask1);
|
fmt::throw_exception("SPU Events not implemented (mask=0x%x)" HERE, mask1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
u32 collect = 0;
|
u32 collect = 0;
|
||||||
|
|
||||||
// Check reservation status and set SPU_EVENT_LR if lost
|
// Check reservation status and set SPU_EVENT_LR if lost
|
||||||
|
@ -2490,7 +2555,7 @@ spu_thread::ch_events_t spu_thread::get_events(u32 mask_hint, bool waiting, bool
|
||||||
set_events(collect);
|
set_events(collect);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ch_events.fetch_op([&](ch_events_t& events)
|
auto [res, ok] = ch_events.fetch_op([&](ch_events_t& events)
|
||||||
{
|
{
|
||||||
if (!reading)
|
if (!reading)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2499,7 +2564,15 @@ spu_thread::ch_events_t spu_thread::get_events(u32 mask_hint, bool waiting, bool
|
||||||
|
|
||||||
events.count = false;
|
events.count = false;
|
||||||
return true;
|
return true;
|
||||||
}).first;
|
});
|
||||||
|
|
||||||
|
if (reading && res.locks && mask_hint & (SPU_EVENT_S1 | SPU_EVENT_S2))
|
||||||
|
{
|
||||||
|
busy_wait(100);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_thread::set_events(u32 bits)
|
void spu_thread::set_events(u32 bits)
|
||||||
|
@ -2520,8 +2593,7 @@ void spu_thread::set_events(u32 bits)
|
||||||
return false;
|
return false;
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
// Preserved for external events implementation
|
notify();
|
||||||
//notify();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ enum : u32
|
||||||
SPU_EVENT_SN = 0x2, // MFC List Command stall-and-notify event
|
SPU_EVENT_SN = 0x2, // MFC List Command stall-and-notify event
|
||||||
SPU_EVENT_TG = 0x1, // MFC Tag Group status update event
|
SPU_EVENT_TG = 0x1, // MFC Tag Group status update event
|
||||||
|
|
||||||
SPU_EVENT_IMPLEMENTED = SPU_EVENT_LR | SPU_EVENT_TM | SPU_EVENT_SN, // Mask of implemented events
|
SPU_EVENT_IMPLEMENTED = SPU_EVENT_LR | SPU_EVENT_TM | SPU_EVENT_SN | SPU_EVENT_S1 | SPU_EVENT_S2, // Mask of implemented events
|
||||||
SPU_EVENT_INTR_IMPLEMENTED = SPU_EVENT_SN,
|
SPU_EVENT_INTR_IMPLEMENTED = SPU_EVENT_SN,
|
||||||
|
|
||||||
SPU_EVENT_INTR_TEST = SPU_EVENT_INTR_IMPLEMENTED,
|
SPU_EVENT_INTR_TEST = SPU_EVENT_INTR_IMPLEMENTED,
|
||||||
|
@ -187,7 +187,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push performing bitwise OR with previous value, may require notification
|
// Push performing bitwise OR with previous value, may require notification
|
||||||
void push_or(u32 value)
|
bool push_or(u32 value)
|
||||||
{
|
{
|
||||||
const u64 old = data.fetch_op([value](u64& data)
|
const u64 old = data.fetch_op([value](u64& data)
|
||||||
{
|
{
|
||||||
|
@ -199,6 +199,8 @@ public:
|
||||||
{
|
{
|
||||||
data.notify_one();
|
data.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (old & bit_count) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool push_and(u32 value)
|
bool push_and(u32 value)
|
||||||
|
@ -207,12 +209,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push unconditionally (overwriting previous value), may require notification
|
// Push unconditionally (overwriting previous value), may require notification
|
||||||
void push(u32 value)
|
bool push(u32 value)
|
||||||
{
|
{
|
||||||
if (data.exchange(bit_count | value) & bit_wait)
|
const u64 old = data.exchange(bit_count | value);
|
||||||
|
|
||||||
|
if (old & bit_wait)
|
||||||
{
|
{
|
||||||
data.notify_one();
|
data.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (old & bit_count) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true on success
|
// Returns true on success
|
||||||
|
@ -694,6 +700,7 @@ public:
|
||||||
{
|
{
|
||||||
u64 all;
|
u64 all;
|
||||||
bf_t<u64, 0, 16> events;
|
bf_t<u64, 0, 16> events;
|
||||||
|
bf_t<u64, 16, 8> locks;
|
||||||
bf_t<u64, 30, 1> waiting;
|
bf_t<u64, 30, 1> waiting;
|
||||||
bf_t<u64, 31, 1> count;
|
bf_t<u64, 31, 1> count;
|
||||||
bf_t<u64, 32, 32> mask;
|
bf_t<u64, 32, 32> mask;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue