diff options
author | Fernando Sahmkow <fsahmkow27@gmail.com> | 2019-06-08 03:13:20 +0200 |
---|---|---|
committer | FernandoS27 <fsahmkow27@gmail.com> | 2019-07-05 21:49:15 +0200 |
commit | a45643cb3b07e76e73814baf1d472d636dd2cd91 (patch) | |
tree | 8cea1037fcfdaa473f8362686ff2d46ee10745d5 | |
parent | Gpu: Implement Hardware Interrupt Manager and manage GPU interrupts (diff) | |
download | yuzu-a45643cb3b07e76e73814baf1d472d636dd2cd91.tar yuzu-a45643cb3b07e76e73814baf1d472d636dd2cd91.tar.gz yuzu-a45643cb3b07e76e73814baf1d472d636dd2cd91.tar.bz2 yuzu-a45643cb3b07e76e73814baf1d472d636dd2cd91.tar.lz yuzu-a45643cb3b07e76e73814baf1d472d636dd2cd91.tar.xz yuzu-a45643cb3b07e76e73814baf1d472d636dd2cd91.tar.zst yuzu-a45643cb3b07e76e73814baf1d472d636dd2cd91.zip |
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 44 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 2 | ||||
-rw-r--r-- | src/video_core/gpu.cpp | 11 | ||||
-rw-r--r-- | src/video_core/gpu.h | 4 |
4 files changed, 48 insertions, 13 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index ef6731a8f..8f47d63e3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -33,6 +33,8 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector< return IocCtrlEventRegister(input, output); case IoctlCommand::IocCtrlEventUnregisterCommand: return IocCtrlEventUnregister(input, output); + case IoctlCommand::IocCtrlEventSignalCommand: + return IocCtrlEventSignal(input, output); } UNIMPLEMENTED_MSG("Unimplemented ioctl"); return 0; @@ -74,30 +76,29 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& return NvResult::Timeout; } - u32 event_index; + u32 event_id; if (is_async) { - event_index = params.value; - if (event_index >= 64) { + event_id = params.value & 0x00FF; + if (event_id >= 64) { std::memcpy(output.data(), ¶ms, sizeof(params)); return NvResult::BadParameter; } } else { - event_index = events_interface.GetFreeEvent(); + event_id = events_interface.GetFreeEvent(); } - EventState status = events_interface.status[event_index]; - if (event_index < MaxNvEvents || status == EventState::Free || - status == EventState::Registered) { - events_interface.SetEventStatus(event_index, EventState::Waiting); - events_interface.assigned_syncpt[event_index] = params.syncpt_id; - events_interface.assigned_value[event_index] = params.threshold; + 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] = params.threshold; if (is_async) { params.value = params.syncpt_id << 4; } else { params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; } - params.value |= event_index; - gpu.RegisterEvent(event_index, params.syncpt_id, params.threshold); + params.value |= event_id; + gpu.RegisterEvent(event_id, params.syncpt_id, params.threshold); std::memcpy(output.data(), ¶ms, sizeof(params)); return NvResult::Timeout; } @@ -131,4 +132,23 @@ u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, std::vecto return NvResult::Success; } +u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector<u8>& input, std::vector<u8>& output) { + IocCtrlEventSignalParams params{}; + std::memcpy(¶ms, input.data(), sizeof(params)); + // TODO(Blinkhawk): This is normally called when an NvEvents timeout on WaitSynchronization + // It is believed to cancel the GPU Event. However, better research is required + u32 event_id = params.user_event_id & 0x00FF; + LOG_WARNING(Service_NVDRV, "(STUBBED) called, user_event_id: {:X}", event_id); + if (event_id >= MaxNvEvents) { + return NvResult::BadParameter; + } + if (events_interface.status[event_id] == EventState::Waiting) { + auto& gpu = Core::System::GetInstance().GPU(); + gpu.CancelEvent(event_id, events_interface.assigned_syncpt[event_id], + events_interface.assigned_value[event_id]); + events_interface.LiberateEvent(event_id); + } + return NvResult::Success; +} + } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 2985e7f75..b5bc9337b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -139,6 +139,8 @@ private: u32 IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); + u32 IocCtrlEventSignal(const std::vector<u8>& input, std::vector<u8>& output); + EventsInterface& events_interface; }; diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 06eb570ab..1fa6770ca 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -95,6 +95,17 @@ void GPU::RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 va events[syncpoint_id].emplace_back(event_id, value); } +void GPU::CancelEvent(const u32 event_id, const u32 syncpoint_id, const u32 value) { + auto it = events[syncpoint_id].begin(); + while (it != events[syncpoint_id].end()) { + if (value == it->value) { + it = events[syncpoint_id].erase(it); + return; + } + it++; + } +} + u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { ASSERT(format != RenderTargetFormat::NONE); diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index c3e5311fa..4805a5fbc 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -171,7 +171,9 @@ public: u32 GetSyncpointValue(const u32 syncpoint_id) const; - void RegisterEvent(const u32 event_id, const u32 sync_point_id, const u32 value); + void RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 value); + + void CancelEvent(const u32 event_id, const u32 syncpoint_id, const u32 value); /// Returns a const reference to the GPU DMA pusher. const Tegra::DmaPusher& DmaPusher() const; |