rsx/lv2: Refactor DMA control stuff after VSH work

This commit is contained in:
kd-11 2023-01-10 16:00:47 +03:00 committed by kd-11
parent 3dba894369
commit 73cda2324a
3 changed files with 60 additions and 60 deletions

View File

@ -34,11 +34,46 @@ void fmt_class_string<sys_rsx_error>::format(std::string& out, u64 arg)
}); });
} }
u64 rsxTimeStamp() static u64 rsx_timeStamp()
{ {
return get_timebased_time(); return get_timebased_time();
} }
static void set_rsx_dmactl(rsx::thread* render, u64 get_put)
{
{
rsx::eng_lock rlock(render);
render->fifo_ctrl->abort();
// Unconditional set
while (!render->new_get_put.compare_and_swap_test(u64{umax}, get_put))
{
utils::pause();
}
// Schedule FIFO interrupt to deal with this immediately
render->m_eng_interrupt_mask |= rsx::dma_control_interrupt;
}
if (auto cpu = cpu_thread::get_current())
{
// Wait for the first store to complete (or be aborted)
while (render->new_get_put != usz{umax})
{
if (Emu.IsStopped())
{
if (render->new_get_put.compare_and_swap_test(get_put, umax))
{
// Retry
cpu->state += cpu_flag::again;
}
}
thread_ctrl::wait_for(1000);
}
}
}
bool rsx::thread::send_event(u64 data1, u64 event_flags, u64 data3) bool rsx::thread::send_event(u64 data1, u64 event_flags, u64 data3)
{ {
// Filter event bits, send them only if they are masked by gcm // Filter event bits, send them only if they are masked by gcm
@ -473,43 +508,9 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
const u64 get = static_cast<u32>(a3); const u64 get = static_cast<u32>(a3);
const u64 put = static_cast<u32>(a4); const u64 put = static_cast<u32>(a4);
const u64 get_put = put << 32 | get; const u64 get_put = put << 32 | get;
bool changed_value = false;
{
rsx::eng_lock rlock(render);
std::lock_guard lock(render->sys_rsx_mtx);
render->fifo_ctrl->abort();
while (render->new_get_put == umax)
{
if (render->new_get_put.compare_and_swap_test(u64{umax}, get_put))
{
changed_value = true;
break;
}
// Assume CAS can fail spuriously here
}
}
// Wait for the first store to complete (or be aborted)
while (render->new_get_put != umax)
{
if (Emu.IsStopped() && changed_value)
{
// Abort
if (render->new_get_put.compare_and_swap_test(get_put, u64{umax}))
{
if (auto cpu = cpu_thread::get_current())
{
cpu->state += cpu_flag::again;
break;
}
}
}
thread_ctrl::wait_for(1000);
}
std::lock_guard lock(render->sys_rsx_mtx);
set_rsx_dmactl(render, get_put);
break; break;
} }
@ -835,7 +836,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
{ {
// we only ever use head 1 for now // we only ever use head 1 for now
driverInfo.head[1].flipFlags |= 0x80000000; driverInfo.head[1].flipFlags |= 0x80000000;
driverInfo.head[1].lastFlipTime = rsxTimeStamp(); // should rsxthread set this? driverInfo.head[1].lastFlipTime = rsx_timeStamp(); // should rsxthread set this?
driverInfo.head[1].flipBufferId = static_cast<u32>(a3); driverInfo.head[1].flipBufferId = static_cast<u32>(a3);
// seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip // seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip
@ -865,7 +866,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
}); });
// Time point is supplied in argument 4 (todo: convert it to MFTB rate and use it) // Time point is supplied in argument 4 (todo: convert it to MFTB rate and use it)
const u64 current_time = rsxTimeStamp(); const u64 current_time = rsx_timeStamp();
// Note: not atomic // Note: not atomic

View File

@ -1274,9 +1274,9 @@ namespace rsx
handle_emu_flip(async_flip_buffer); handle_emu_flip(async_flip_buffer);
} }
if (!in_begin_end && state != FIFO::state::lock_wait) if (state != FIFO::state::lock_wait)
{ {
if (atomic_storage<u32>::load(m_invalidated_memory_range.end) != 0) if (!in_begin_end && atomic_storage<u32>::load(m_invalidated_memory_range.end) != 0)
{ {
std::lock_guard lock(m_mtx_task); std::lock_guard lock(m_mtx_task);
@ -1285,6 +1285,22 @@ namespace rsx
handle_invalidated_memory_range(); handle_invalidated_memory_range();
} }
} }
if (m_eng_interrupt_mask & rsx::dma_control_interrupt && !is_stopped())
{
if (const u64 get_put = new_get_put.exchange(u64{umax});
get_put != umax)
{
vm::_ref<atomic_be_t<u64>>(dma_address + ::offset32(&RsxDmaControl::put)).release(get_put);
fifo_ctrl->set_get(static_cast<u32>(get_put));
fifo_ctrl->abort();
fifo_ret_addr = RSX_CALL_STACK_EMPTY;
last_known_code_start = static_cast<u32>(get_put);
sync_point_request.release(true);
}
m_eng_interrupt_mask.clear(rsx::dma_control_interrupt);
}
} }
if (m_eng_interrupt_mask & rsx::pipe_flush_interrupt) if (m_eng_interrupt_mask & rsx::pipe_flush_interrupt)
@ -1299,21 +1315,6 @@ namespace rsx
m_invalidated_memory_range = utils::address_range::start_end(0x2 << 28, constants::local_mem_base + local_mem_size - 1); m_invalidated_memory_range = utils::address_range::start_end(0x2 << 28, constants::local_mem_base + local_mem_size - 1);
handle_invalidated_memory_range(); handle_invalidated_memory_range();
} }
else if (new_get_put != umax && state != FIFO_state::lock_wait)
{
const u64 get_put = new_get_put.exchange(u64{umax});
// Recheck in case aborted externally
if (get_put != umax)
{
vm::_ref<atomic_be_t<u64>>(dma_address + ::offset32(&RsxDmaControl::put)).release(get_put);
fifo_ctrl->set_get(static_cast<u32>(get_put));
fifo_ctrl->abort();
fifo_ret_addr = RSX_CALL_STACK_EMPTY;
last_known_code_start = static_cast<u32>(get_put);
sync_point_request.release(true);
}
}
} }
std::array<u32, 4> thread::get_color_surface_addresses() const std::array<u32, 4> thread::get_color_surface_addresses() const
@ -3268,11 +3269,8 @@ namespace rsx
{ {
external_interrupt_lock++; external_interrupt_lock++;
while (!external_interrupt_ack) while (!external_interrupt_ack && !is_stopped())
{ {
if (is_stopped())
break;
utils::pause(); utils::pause();
} }
} }

View File

@ -98,6 +98,7 @@ namespace rsx
memory_config_interrupt = 0x0002, // Memory configuration changed memory_config_interrupt = 0x0002, // Memory configuration changed
display_interrupt = 0x0004, // Display handling display_interrupt = 0x0004, // Display handling
pipe_flush_interrupt = 0x0008, // Flush pipelines pipe_flush_interrupt = 0x0008, // Flush pipelines
dma_control_interrupt = 0x0010, // DMA interrupt
all_interrupt_bits = memory_config_interrupt | backend_interrupt | display_interrupt | pipe_flush_interrupt all_interrupt_bits = memory_config_interrupt | backend_interrupt | display_interrupt | pipe_flush_interrupt
}; };