diff options
| author | 2019-07-01 11:10:27 -0400 | |
|---|---|---|
| committer | 2019-07-05 15:49:33 -0400 | |
| commit | f3a39e0c9ce8468859da12e35a52fa088e264d28 (patch) | |
| tree | 1b8213a87e7cda7ccb5be0828770415d2d78000e /src | |
| parent | NVServices: Styling, define constructors as explicit and corrections (diff) | |
| download | yuzu-f3a39e0c9ce8468859da12e35a52fa088e264d28.tar.gz yuzu-f3a39e0c9ce8468859da12e35a52fa088e264d28.tar.xz yuzu-f3a39e0c9ce8468859da12e35a52fa088e264d28.zip | |
NVServices: Address Feedback
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 14 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 5 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/interface.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdata.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv.h | 23 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/buffer_queue.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 5 |
8 files changed, 38 insertions, 21 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index c918b4225..76494f0b7 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | |||
| @@ -36,9 +36,8 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 | |||
| 36 | addr, offset, width, height, stride, static_cast<PixelFormat>(format), | 36 | addr, offset, width, height, stride, static_cast<PixelFormat>(format), |
| 37 | transform, crop_rect}; | 37 | transform, crop_rect}; |
| 38 | 38 | ||
| 39 | auto& instance = system; | 39 | system.GetPerfStats().EndGameFrame(); |
| 40 | instance.GetPerfStats().EndGameFrame(); | 40 | system.GPU().SwapBuffers(framebuffer); |
| 41 | instance.GPU().SwapBuffers(framebuffer); | ||
| 42 | } | 41 | } |
| 43 | 42 | ||
| 44 | } // namespace Service::Nvidia::Devices | 43 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 749aa71d4..1f178d17d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | |||
| @@ -87,13 +87,19 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& | |||
| 87 | u32 event_id; | 87 | u32 event_id; |
| 88 | if (is_async) { | 88 | if (is_async) { |
| 89 | event_id = params.value & 0x00FF; | 89 | event_id = params.value & 0x00FF; |
| 90 | if (event_id >= 64) { | 90 | if (event_id >= MaxNvEvents) { |
| 91 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 91 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 92 | return NvResult::BadParameter; | 92 | return NvResult::BadParameter; |
| 93 | } | 93 | } |
| 94 | } else { | 94 | } else { |
| 95 | if (ctrl.fresh_call) { | 95 | if (ctrl.fresh_call) { |
| 96 | event_id = events_interface.GetFreeEvent(); | 96 | const auto result = events_interface.GetFreeEvent(); |
| 97 | if (result) { | ||
| 98 | event_id = *result; | ||
| 99 | } else { | ||
| 100 | LOG_CRITICAL(Service_NVDRV, "No Free Events available!"); | ||
| 101 | event_id = params.value & 0x00FF; | ||
| 102 | } | ||
| 97 | } else { | 103 | } else { |
| 98 | event_id = ctrl.event_id; | 104 | event_id = ctrl.event_id; |
| 99 | } | 105 | } |
| @@ -129,6 +135,7 @@ u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector< | |||
| 129 | IocCtrlEventRegisterParams params{}; | 135 | IocCtrlEventRegisterParams params{}; |
| 130 | std::memcpy(¶ms, input.data(), sizeof(params)); | 136 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 131 | const u32 event_id = params.user_event_id & 0x00FF; | 137 | const u32 event_id = params.user_event_id & 0x00FF; |
| 138 | LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); | ||
| 132 | if (event_id >= MaxNvEvents) { | 139 | if (event_id >= MaxNvEvents) { |
| 133 | return NvResult::BadParameter; | 140 | return NvResult::BadParameter; |
| 134 | } | 141 | } |
| @@ -143,6 +150,7 @@ u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, std::vecto | |||
| 143 | IocCtrlEventUnregisterParams params{}; | 150 | IocCtrlEventUnregisterParams params{}; |
| 144 | std::memcpy(¶ms, input.data(), sizeof(params)); | 151 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 145 | const u32 event_id = params.user_event_id & 0x00FF; | 152 | const u32 event_id = params.user_event_id & 0x00FF; |
| 153 | LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); | ||
| 146 | if (event_id >= MaxNvEvents) { | 154 | if (event_id >= MaxNvEvents) { |
| 147 | return NvResult::BadParameter; | 155 | return NvResult::BadParameter; |
| 148 | } | 156 | } |
| @@ -159,7 +167,7 @@ u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector<u8>& input, std::vector<u8 | |||
| 159 | // TODO(Blinkhawk): This is normally called when an NvEvents timeout on WaitSynchronization | 167 | // TODO(Blinkhawk): This is normally called when an NvEvents timeout on WaitSynchronization |
| 160 | // It is believed from RE to cancel the GPU Event. However, better research is required | 168 | // It is believed from RE to cancel the GPU Event. However, better research is required |
| 161 | u32 event_id = params.user_event_id & 0x00FF; | 169 | u32 event_id = params.user_event_id & 0x00FF; |
| 162 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, user_event_id: {:X}", event_id); | 170 | LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); |
| 163 | if (event_id >= MaxNvEvents) { | 171 | if (event_id >= MaxNvEvents) { |
| 164 | return NvResult::BadParameter; | 172 | return NvResult::BadParameter; |
| 165 | } | 173 | } |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 3ad8e1db1..d2e8fbae9 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/swap.h" | 11 | #include "common/swap.h" |
| 12 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 12 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 13 | #include "core/hle/service/nvdrv/nvdata.h" | ||
| 13 | 14 | ||
| 14 | namespace Service::Nvidia::Devices { | 15 | namespace Service::Nvidia::Devices { |
| 15 | 16 | ||
| @@ -114,10 +115,6 @@ private: | |||
| 114 | static_assert(sizeof(IoctlGetErrorNotification) == 16, | 115 | static_assert(sizeof(IoctlGetErrorNotification) == 16, |
| 115 | "IoctlGetErrorNotification is incorrect size"); | 116 | "IoctlGetErrorNotification is incorrect size"); |
| 116 | 117 | ||
| 117 | struct Fence { | ||
| 118 | u32_le id; | ||
| 119 | u32_le value; | ||
| 120 | }; | ||
| 121 | static_assert(sizeof(Fence) == 8, "Fence is incorrect size"); | 118 | static_assert(sizeof(Fence) == 8, "Fence is incorrect size"); |
| 122 | 119 | ||
| 123 | struct IoctlAllocGpfifoEx { | 120 | struct IoctlAllocGpfifoEx { |
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 6f7c7502a..b8877b6cb 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp | |||
| @@ -103,7 +103,7 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { | |||
| 103 | 103 | ||
| 104 | IPC::ResponseBuilder rb{ctx, 3, 1}; | 104 | IPC::ResponseBuilder rb{ctx, 3, 1}; |
| 105 | rb.Push(RESULT_SUCCESS); | 105 | rb.Push(RESULT_SUCCESS); |
| 106 | if (event_id < 64) { | 106 | if (event_id < MaxNvEvents) { |
| 107 | rb.PushCopyObjects(nvdrv->GetEvent(event_id)); | 107 | rb.PushCopyObjects(nvdrv->GetEvent(event_id)); |
| 108 | rb.Push<u32>(NvResult::Success); | 108 | rb.Push<u32>(NvResult::Success); |
| 109 | } else { | 109 | } else { |
diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h index 22b1dc79b..ac03cbc23 100644 --- a/src/core/hle/service/nvdrv/nvdata.h +++ b/src/core/hle/service/nvdrv/nvdata.h | |||
| @@ -35,9 +35,13 @@ enum class EventState { | |||
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | struct IoctlCtrl { | 37 | struct IoctlCtrl { |
| 38 | // First call done to the servioce for services that call itself again after a call. | ||
| 38 | bool fresh_call{true}; | 39 | bool fresh_call{true}; |
| 40 | // Tells the Ioctl Wrapper that it must delay the IPC response and send the thread to sleep | ||
| 39 | bool must_delay{}; | 41 | bool must_delay{}; |
| 42 | // Timeout for the delay | ||
| 40 | s64 timeout{}; | 43 | s64 timeout{}; |
| 44 | // NV Event Id | ||
| 41 | s32 event_id{-1}; | 45 | s32 event_id{-1}; |
| 42 | }; | 46 | }; |
| 43 | 47 | ||
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 8f7c59a21..a339ab672 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -27,25 +27,34 @@ class nvdevice; | |||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | struct EventInterface { | 29 | struct EventInterface { |
| 30 | // Mask representing currently busy events | ||
| 30 | u64 events_mask{}; | 31 | u64 events_mask{}; |
| 32 | // Each kernel event associated to an NV event | ||
| 31 | std::array<Kernel::EventPair, MaxNvEvents> events; | 33 | std::array<Kernel::EventPair, MaxNvEvents> events; |
| 34 | // The status of the current NVEvent | ||
| 32 | std::array<EventState, MaxNvEvents> status{}; | 35 | std::array<EventState, MaxNvEvents> status{}; |
| 36 | // Tells if an NVEvent is registered or not | ||
| 33 | std::array<bool, MaxNvEvents> registered{}; | 37 | std::array<bool, MaxNvEvents> registered{}; |
| 38 | // When an NVEvent is waiting on GPU interrupt, this is the sync_point | ||
| 39 | // associated with it. | ||
| 34 | std::array<u32, MaxNvEvents> assigned_syncpt{}; | 40 | std::array<u32, MaxNvEvents> assigned_syncpt{}; |
| 41 | // This is the value of the GPU interrupt for which the NVEvent is waiting | ||
| 42 | // for. | ||
| 35 | std::array<u32, MaxNvEvents> assigned_value{}; | 43 | std::array<u32, MaxNvEvents> assigned_value{}; |
| 36 | static constexpr u32 null_event = 0xFFFFFFFF; | 44 | // Constant to denote an unasigned syncpoint. |
| 37 | u32 GetFreeEvent() const { | 45 | static constexpr u32 unassigned_syncpt = 0xFFFFFFFF; |
| 46 | std::optional<u32> GetFreeEvent() const { | ||
| 38 | u64 mask = events_mask; | 47 | u64 mask = events_mask; |
| 39 | for (u32 i = 0; i < MaxNvEvents; i++) { | 48 | for (u32 i = 0; i < MaxNvEvents; i++) { |
| 40 | const bool is_free = (mask & 0x1) == 0; | 49 | const bool is_free = (mask & 0x1) == 0; |
| 41 | if (is_free) { | 50 | if (is_free) { |
| 42 | if (status[i] == EventState::Registered || status[i] == EventState::Free) { | 51 | if (status[i] == EventState::Registered || status[i] == EventState::Free) { |
| 43 | return i; | 52 | return {i}; |
| 44 | } | 53 | } |
| 45 | } | 54 | } |
| 46 | mask = mask >> 1; | 55 | mask = mask >> 1; |
| 47 | } | 56 | } |
| 48 | return null_event; | 57 | return {}; |
| 49 | } | 58 | } |
| 50 | void SetEventStatus(const u32 event_id, EventState new_status) { | 59 | void SetEventStatus(const u32 event_id, EventState new_status) { |
| 51 | EventState old_status = status[event_id]; | 60 | EventState old_status = status[event_id]; |
| @@ -57,7 +66,7 @@ struct EventInterface { | |||
| 57 | registered[event_id] = true; | 66 | registered[event_id] = true; |
| 58 | } | 67 | } |
| 59 | if (new_status == EventState::Waiting || new_status == EventState::Busy) { | 68 | if (new_status == EventState::Waiting || new_status == EventState::Busy) { |
| 60 | events_mask |= (1 << event_id); | 69 | events_mask |= (1ULL << event_id); |
| 61 | } | 70 | } |
| 62 | } | 71 | } |
| 63 | void RegisterEvent(const u32 event_id) { | 72 | void RegisterEvent(const u32 event_id) { |
| @@ -74,8 +83,8 @@ struct EventInterface { | |||
| 74 | } | 83 | } |
| 75 | void LiberateEvent(const u32 event_id) { | 84 | void LiberateEvent(const u32 event_id) { |
| 76 | status[event_id] = registered[event_id] ? EventState::Registered : EventState::Free; | 85 | status[event_id] = registered[event_id] ? EventState::Registered : EventState::Free; |
| 77 | events_mask &= ~(1 << event_id); | 86 | events_mask &= ~(1ULL << event_id); |
| 78 | assigned_syncpt[event_id] = 0xFFFFFFFF; | 87 | assigned_syncpt[event_id] = unassigned_syncpt; |
| 79 | assigned_value[event_id] = 0; | 88 | assigned_value[event_id] = 0; |
| 80 | } | 89 | } |
| 81 | }; | 90 | }; |
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index ddc224f2c..e1a07d3ee 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp | |||
| @@ -80,6 +80,7 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, | |||
| 80 | 80 | ||
| 81 | std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { | 81 | std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { |
| 82 | auto itr = queue.end(); | 82 | auto itr = queue.end(); |
| 83 | // Iterate to find a queued buffer matching the requested slot. | ||
| 83 | while (itr == queue.end() && !queue_sequence.empty()) { | 84 | while (itr == queue.end() && !queue_sequence.empty()) { |
| 84 | u32 slot = queue_sequence.front(); | 85 | u32 slot = queue_sequence.front(); |
| 85 | itr = std::find_if(queue.begin(), queue.end(), [&slot](const Buffer& buffer) { | 86 | itr = std::find_if(queue.begin(), queue.end(), [&slot](const Buffer& buffer) { |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 894bcdc04..199b30635 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -536,7 +536,7 @@ private: | |||
| 536 | 536 | ||
| 537 | if (result) { | 537 | if (result) { |
| 538 | // Buffer is available | 538 | // Buffer is available |
| 539 | IGBPDequeueBufferResponseParcel response{(*result).first, *(*result).second}; | 539 | IGBPDequeueBufferResponseParcel response{result->first, *result->second}; |
| 540 | ctx.WriteBuffer(response.Serialize()); | 540 | ctx.WriteBuffer(response.Serialize()); |
| 541 | } else { | 541 | } else { |
| 542 | // Wait the current thread until a buffer becomes available | 542 | // Wait the current thread until a buffer becomes available |
| @@ -549,8 +549,7 @@ private: | |||
| 549 | auto result = buffer_queue.DequeueBuffer(width, height); | 549 | auto result = buffer_queue.DequeueBuffer(width, height); |
| 550 | ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); | 550 | ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); |
| 551 | 551 | ||
| 552 | IGBPDequeueBufferResponseParcel response{(*result).first, | 552 | IGBPDequeueBufferResponseParcel response{result->first, *result->second}; |
| 553 | *(*result).second}; | ||
| 554 | ctx.WriteBuffer(response.Serialize()); | 553 | ctx.WriteBuffer(response.Serialize()); |
| 555 | IPC::ResponseBuilder rb{ctx, 2}; | 554 | IPC::ResponseBuilder rb{ctx, 2}; |
| 556 | rb.Push(RESULT_SUCCESS); | 555 | rb.Push(RESULT_SUCCESS); |