sys_rsx: Minor atomicity fixes

This commit is contained in:
Eladash 2020-04-07 13:18:41 +03:00 committed by kd-11
parent a38d2461c9
commit 3f48450408
6 changed files with 75 additions and 19 deletions

View file

@ -38,6 +38,47 @@ u64 rsxTimeStamp()
return get_timebased_time();
}
void lv2_rsx_config::send_event(u64 data1, u64 data2, u64 data3) const
{
auto error = sys_event_port_send(rsx_event_port, data1, data2, data3);
while (error + 0u == CELL_EBUSY)
{
auto cpu = get_current_cpu_thread();
if (cpu && cpu->id_type() != 1)
{
cpu = nullptr;
}
if (cpu)
{
// Deschedule
lv2_obj::sleep(*cpu, 100);
}
else if (const auto rsx = rsx::get_current_renderer(); rsx->is_current_thread())
{
rsx->on_semaphore_acquire_wait();
}
// Wait a bit before resending event
thread_ctrl::wait_for(100);
if (cpu && cpu->check_state())
{
error = 0;
break;
}
error = sys_event_port_send(rsx_event_port, data1, data2, data3);
}
if (error)
{
fmt::throw_exception("rsx_event_port_send() Failed to send event! (error=%x)" HERE, +error);
}
}
error_code sys_rsx_device_open()
{
sys_rsx.todo("sys_rsx_device_open()");
@ -202,6 +243,8 @@ error_code sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u64> lpar_d
sys_event_queue_create(vm::get_addr(&driverInfo.handler_queue), attr, 0, 0x20);
sys_event_port_connect_local(rsx_cfg->rsx_event_port, driverInfo.handler_queue);
rsx_cfg->dma_address = vm::cast(*lpar_dma_control, HERE);
const auto render = rsx::get_current_renderer();
render->display_buffers_count = 0;
render->current_display_buffer = 0;
@ -350,12 +393,17 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
switch (package_id)
{
case 0x001: // FIFO
{
render->pause();
const u64 get = static_cast<u32>(a3);
const u64 put = static_cast<u32>(a4);
vm::_ref<atomic_be_t<u64>>(rsx_cfg->dma_address + ::offset32(&RsxDmaControl::put)).release(put << 32 | get);
render->ctrl->get = static_cast<u32>(a3);
render->ctrl->put = static_cast<u32>(a4);
render->restore_point = static_cast<u32>(a3);
render->sync_point_request.release(true);
render->unpause();
break;
}
case 0x100: // Display mode set
break;
@ -416,7 +464,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
verify(HERE), a3 < 2;
const u64 shift_offset = (a3 + 5);
sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1ull << shift_offset), 0);
rsx_cfg->send_event(0, (1ull << shift_offset), 0);
render->on_frame_end(static_cast<u32>(a4));
}
@ -465,9 +513,10 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
return SYS_RSX_CONTEXT_ATTRIBUTE_ERROR;
}
u32 flipStatus = driverInfo.head[a3].flipFlags;
driverInfo.head[a3].flipFlags.atomic_op([&](be_t<u32>& flipStatus)
{
flipStatus = (flipStatus & static_cast<u32>(a4)) | static_cast<u32>(a5);
driverInfo.head[a3].flipFlags = flipStatus;
});
}
break;
@ -549,29 +598,33 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
vm::_ref<u32>(render->label_addr + 0x10) = 0;
//if (a3 == 0)
// sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 3), 0);
// rsx_cfg->send_event(0, (1 << 3), 0);
//if (a3 == 1)
sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 4), 0);
rsx_cfg->send_event(0, (1 << 4), 0);
break;
case 0xFED: // hack: vblank command
{
// todo: this is wrong and should be 'second' vblank handler and freq, but since currently everything is reported as being 59.94, this should be fine
vm::_ref<u32>(render->device_addr + 0x30) = 1;
driverInfo.head[a3].vBlankCount++;
driverInfo.head[a3].lastSecondVTime = rsxTimeStamp();
sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 1), 0);
u64 event_flags = (1 << 1);
if (render->enable_second_vhandler)
sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 11), 0); // second vhandler
event_flags |= (1 << 11); // second vhandler
rsx_cfg->send_event(0, event_flags, 0);
break;
}
case 0xFEF: // hack: user command
// 'custom' invalid package id for now
// as i think we need custom lv1 interrupts to handle this accurately
// this also should probly be set by rsxthread
driverInfo.userCmdParam = static_cast<u32>(a4);
sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 7), 0);
rsx_cfg->send_event(0, (1 << 7), 0);
break;
default:

View file

@ -22,7 +22,7 @@ struct RsxDriverInfo
struct Head
{
be_t<u64> lastFlipTime; // 0x0 last flip time
be_t<u32> flipFlags; // 0x8 flags to handle flip/queue
atomic_be_t<u32> flipFlags; // 0x8 flags to handle flip/queue
be_t<u32> offset; // 0xC
be_t<u32> flipBufferId; // 0x10
be_t<u32> lastQueuedBufferId; // 0x14 todo: this is definately not this variable but its 'unused' so im using it for queueId to pass to flip handler
@ -30,7 +30,7 @@ struct RsxDriverInfo
be_t<u32> unk6; // 0x18 possible low bits of time stamp? used in getlastVBlankTime
be_t<u64> lastSecondVTime; // 0x20 last time for second vhandler freq
be_t<u64> unk4; // 0x28
be_t<u64> vBlankCount; // 0x30
atomic_be_t<u64> vBlankCount; // 0x30
be_t<u32> unk; // 0x38 possible u32, 'flip field', top/bottom for interlaced
be_t<u32> unk5; // 0x3C possible high bits of time stamp? used in getlastVBlankTime
} head[8]; // size = 0x40, 0x200
@ -114,6 +114,9 @@ struct lv2_rsx_config
u32 context_base{};
u32 device_addr{};
u32 driver_info{};
u32 dma_address{};
void send_event(u64, u64, u64) const;
};
// SysCalls

View file

@ -431,7 +431,7 @@ namespace rsx
if (performance_counters.state == FIFO_state::running)
{
performance_counters.FIFO_idle_timestamp = get_system_time();
sync_point_request = true;
sync_point_request.release(true);
}
performance_counters.state = FIFO_state::spinning;
@ -450,7 +450,7 @@ namespace rsx
if (performance_counters.state == FIFO_state::running)
{
performance_counters.FIFO_idle_timestamp = get_system_time();
sync_point_request = true;
sync_point_request.release(true);
}
performance_counters.state = FIFO_state::spinning;

View file

@ -615,7 +615,7 @@ namespace rsx
{
restore_point = ctrl->get;
saved_fifo_ret = fifo_ret_addr;
sync_point_request = false;
sync_point_request.release(false);
}
// Execute backend-local tasks first
@ -2425,7 +2425,7 @@ namespace rsx
{
// Each 64 entries are grouped by a bit
const u64 io_event = 0x100000000ull << i;
sys_event_port_send(g_fxo->get<lv2_rsx_config>()->rsx_event_port, 0, io_event, to_unmap);
g_fxo->get<lv2_rsx_config>()->send_event(0, io_event, to_unmap);
}
}
}

View file

@ -725,7 +725,7 @@ namespace rsx
bool capture_current_frame = false;
public:
bool sync_point_request = false;
atomic_t<bool> sync_point_request = false;
bool in_begin_end = false;
struct desync_fifo_cmd_info

View file

@ -50,7 +50,7 @@ namespace rsx
void semaphore_acquire(thread* rsx, u32 /*_reg*/, u32 arg)
{
rsx->sync_point_request = true;
rsx->sync_point_request.release(true);
const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e(), HERE);
const auto& sema = vm::_ref<atomic_be_t<u32>>(addr);
@ -132,7 +132,7 @@ namespace rsx
if (const bool is_flip_sema = (offset == 0x10 && ctxt == CELL_GCM_CONTEXT_DMA_SEMAPHORE_R);
!is_flip_sema)
{
rsx->sync_point_request = true;
rsx->sync_point_request.release(true);
}
const u32 addr = get_address(offset, ctxt, HERE);