diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 775e76330..f9b82b504 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -92,6 +92,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector if (syncpoint_manager.IsSyncpointExpired(params.syncpt_id, params.threshold)) { params.value = syncpoint_manager.GetSyncpointMin(params.syncpt_id); std::memcpy(output.data(), ¶ms, sizeof(params)); + events_interface.failed[event_id] = false; return NvResult::Success; } @@ -99,6 +100,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector syncpoint_manager.IsSyncpointExpired(params.syncpt_id, params.threshold)) { params.value = new_value; std::memcpy(output.data(), ¶ms, sizeof(params)); + events_interface.failed[event_id] = false; return NvResult::Success; } @@ -111,13 +113,13 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector event.event->GetWritableEvent().Signal(); return NvResult::Success; } - auto lock = gpu.LockSync(); const u32 current_syncpoint_value = event.fence.value; const s32 diff = current_syncpoint_value - params.threshold; if (diff >= 0) { event.event->GetWritableEvent().Signal(); params.value = current_syncpoint_value; std::memcpy(output.data(), ¶ms, sizeof(params)); + events_interface.failed[event_id] = false; return NvResult::Success; } const u32 target_value = current_syncpoint_value - diff; @@ -132,23 +134,34 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector } EventState status = events_interface.status[event_id]; - if (event_id < MaxNvEvents || status == EventState::Free || status == EventState::Registered) { - events_interface.SetEventStatus(event_id, EventState::Waiting); - events_interface.assigned_syncpt[event_id] = params.syncpt_id; - events_interface.assigned_value[event_id] = target_value; - if (is_async) { - params.value = params.syncpt_id << 4; - } else { - params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; + const bool bad_parameter = status != EventState::Free && status != EventState::Registered; + if (bad_parameter) { + std::memcpy(output.data(), ¶ms, sizeof(params)); + return NvResult::BadParameter; + } + events_interface.SetEventStatus(event_id, EventState::Waiting); + events_interface.assigned_syncpt[event_id] = params.syncpt_id; + events_interface.assigned_value[event_id] = target_value; + if (is_async) { + params.value = params.syncpt_id << 4; + } else { + params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; + } + params.value |= event_id; + event.event->GetWritableEvent().Clear(); + if (events_interface.failed[event_id]) { + { + auto lk = system.StallCPU(); + gpu.WaitFence(params.syncpt_id, target_value); + system.UnstallCPU(); } - params.value |= event_id; - event.event->GetWritableEvent().Clear(); - gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); std::memcpy(output.data(), ¶ms, sizeof(params)); - return NvResult::Timeout; + events_interface.failed[event_id] = false; + return NvResult::Success; } + gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); std::memcpy(output.data(), ¶ms, sizeof(params)); - return NvResult::BadParameter; + return NvResult::Timeout; } NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) { @@ -201,6 +214,7 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::v if (events_interface.status[event_id] == EventState::Waiting) { events_interface.LiberateEvent(event_id); } + events_interface.failed[event_id] = true; syncpoint_manager.RefreshSyncpoint(events_interface.events[event_id].fence.id); |