From f3a39e0c9ce8468859da12e35a52fa088e264d28 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 1 Jul 2019 11:10:27 -0400 Subject: NVServices: Address Feedback --- .../hle/service/nvdrv/devices/nvdisp_disp0.cpp | 5 ++--- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 14 ++++++++++--- src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 5 +---- src/core/hle/service/nvdrv/interface.cpp | 2 +- src/core/hle/service/nvdrv/nvdata.h | 4 ++++ src/core/hle/service/nvdrv/nvdrv.h | 23 +++++++++++++++------- src/core/hle/service/nvflinger/buffer_queue.cpp | 1 + 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 addr, offset, width, height, stride, static_cast(format), transform, crop_rect}; - auto& instance = system; - instance.GetPerfStats().EndGameFrame(); - instance.GPU().SwapBuffers(framebuffer); + system.GetPerfStats().EndGameFrame(); + system.GPU().SwapBuffers(framebuffer); } } // 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& input, std::vector& u32 event_id; if (is_async) { event_id = params.value & 0x00FF; - if (event_id >= 64) { + if (event_id >= MaxNvEvents) { std::memcpy(output.data(), ¶ms, sizeof(params)); return NvResult::BadParameter; } } else { if (ctrl.fresh_call) { - event_id = events_interface.GetFreeEvent(); + const auto result = events_interface.GetFreeEvent(); + if (result) { + event_id = *result; + } else { + LOG_CRITICAL(Service_NVDRV, "No Free Events available!"); + event_id = params.value & 0x00FF; + } } else { event_id = ctrl.event_id; } @@ -129,6 +135,7 @@ u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector& input, std::vector< IocCtrlEventRegisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); const u32 event_id = params.user_event_id & 0x00FF; + LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); if (event_id >= MaxNvEvents) { return NvResult::BadParameter; } @@ -143,6 +150,7 @@ u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector& input, std::vecto IocCtrlEventUnregisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); const u32 event_id = params.user_event_id & 0x00FF; + LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); if (event_id >= MaxNvEvents) { return NvResult::BadParameter; } @@ -159,7 +167,7 @@ u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector& input, std::vector= MaxNvEvents) { return NvResult::BadParameter; } 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 @@ #include "common/common_types.h" #include "common/swap.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" +#include "core/hle/service/nvdrv/nvdata.h" namespace Service::Nvidia::Devices { @@ -114,10 +115,6 @@ private: static_assert(sizeof(IoctlGetErrorNotification) == 16, "IoctlGetErrorNotification is incorrect size"); - struct Fence { - u32_le id; - u32_le value; - }; static_assert(sizeof(Fence) == 8, "Fence is incorrect size"); 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) { IPC::ResponseBuilder rb{ctx, 3, 1}; rb.Push(RESULT_SUCCESS); - if (event_id < 64) { + if (event_id < MaxNvEvents) { rb.PushCopyObjects(nvdrv->GetEvent(event_id)); rb.Push(NvResult::Success); } 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 { }; struct IoctlCtrl { + // First call done to the servioce for services that call itself again after a call. bool fresh_call{true}; + // Tells the Ioctl Wrapper that it must delay the IPC response and send the thread to sleep bool must_delay{}; + // Timeout for the delay s64 timeout{}; + // NV Event Id s32 event_id{-1}; }; 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; } struct EventInterface { + // Mask representing currently busy events u64 events_mask{}; + // Each kernel event associated to an NV event std::array events; + // The status of the current NVEvent std::array status{}; + // Tells if an NVEvent is registered or not std::array registered{}; + // When an NVEvent is waiting on GPU interrupt, this is the sync_point + // associated with it. std::array assigned_syncpt{}; + // This is the value of the GPU interrupt for which the NVEvent is waiting + // for. std::array assigned_value{}; - static constexpr u32 null_event = 0xFFFFFFFF; - u32 GetFreeEvent() const { + // Constant to denote an unasigned syncpoint. + static constexpr u32 unassigned_syncpt = 0xFFFFFFFF; + std::optional GetFreeEvent() const { u64 mask = events_mask; for (u32 i = 0; i < MaxNvEvents; i++) { const bool is_free = (mask & 0x1) == 0; if (is_free) { if (status[i] == EventState::Registered || status[i] == EventState::Free) { - return i; + return {i}; } } mask = mask >> 1; } - return null_event; + return {}; } void SetEventStatus(const u32 event_id, EventState new_status) { EventState old_status = status[event_id]; @@ -57,7 +66,7 @@ struct EventInterface { registered[event_id] = true; } if (new_status == EventState::Waiting || new_status == EventState::Busy) { - events_mask |= (1 << event_id); + events_mask |= (1ULL << event_id); } } void RegisterEvent(const u32 event_id) { @@ -74,8 +83,8 @@ struct EventInterface { } void LiberateEvent(const u32 event_id) { status[event_id] = registered[event_id] ? EventState::Registered : EventState::Free; - events_mask &= ~(1 << event_id); - assigned_syncpt[event_id] = 0xFFFFFFFF; + events_mask &= ~(1ULL << event_id); + assigned_syncpt[event_id] = unassigned_syncpt; assigned_value[event_id] = 0; } }; 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, std::optional> BufferQueue::AcquireBuffer() { auto itr = queue.end(); + // Iterate to find a queued buffer matching the requested slot. while (itr == queue.end() && !queue_sequence.empty()) { u32 slot = queue_sequence.front(); 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: if (result) { // Buffer is available - IGBPDequeueBufferResponseParcel response{(*result).first, *(*result).second}; + IGBPDequeueBufferResponseParcel response{result->first, *result->second}; ctx.WriteBuffer(response.Serialize()); } else { // Wait the current thread until a buffer becomes available @@ -549,8 +549,7 @@ private: auto result = buffer_queue.DequeueBuffer(width, height); ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); - IGBPDequeueBufferResponseParcel response{(*result).first, - *(*result).second}; + IGBPDequeueBufferResponseParcel response{result->first, *result->second}; ctx.WriteBuffer(response.Serialize()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); -- cgit v1.2.3