From ceb5f5079c3efd8046ccf35bbc3507a4c190f355 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 4 Jun 2019 16:10:07 -0400 Subject: nvflinger: Implement swap intervals --- src/core/hle/service/nvflinger/buffer_queue.cpp | 3 ++- src/core/hle/service/nvflinger/buffer_queue.h | 3 ++- src/core/hle/service/nvflinger/nvflinger.cpp | 14 ++++++++++---- src/core/hle/service/nvflinger/nvflinger.h | 4 ++++ src/core/hle/service/vi/vi.cpp | 5 +++-- 5 files changed, 21 insertions(+), 8 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 5731e815f..dca75c35e 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -63,7 +63,7 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { } void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, - const Common::Rectangle& crop_rect) { + const Common::Rectangle& crop_rect, u32 swap_interval) { auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { return buffer.slot == slot; }); ASSERT(itr != queue.end()); @@ -71,6 +71,7 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, itr->status = Buffer::Status::Queued; itr->transform = transform; itr->crop_rect = crop_rect; + itr->swap_interval = swap_interval; } std::optional> BufferQueue::AcquireBuffer() { diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index e1ccb6171..139b98b9f 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -68,13 +68,14 @@ public: IGBPBuffer igbp_buffer; BufferTransformFlags transform; Common::Rectangle crop_rect; + u32 swap_interval; }; void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer); std::optional DequeueBuffer(u32 width, u32 height); const IGBPBuffer& RequestBuffer(u32 slot) const; void QueueBuffer(u32 slot, BufferTransformFlags transform, - const Common::Rectangle& crop_rect); + const Common::Rectangle& crop_rect, u32 swap_interval); std::optional> AcquireBuffer(); void ReleaseBuffer(u32 slot); u32 Query(QueryType type); diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 3c5c53e24..6d83535e7 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -37,15 +37,16 @@ NVFlinger::NVFlinger(Core::Timing::CoreTiming& core_timing) : core_timing{core_t displays.emplace_back(4, "Null"); // Schedule the screen composition events - const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : frame_ticks; + //const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : frame_ticks; composition_event = core_timing.RegisterEvent( - "ScreenComposition", [this, ticks](u64 userdata, s64 cycles_late) { + "ScreenComposition", [this](u64 userdata, s64 cycles_late) { Compose(); - this->core_timing.ScheduleEvent(ticks - cycles_late, composition_event); + const auto ticks = GetNextTicks(); + this->core_timing.ScheduleEvent(std::max(0LL,ticks - cycles_late), composition_event); }); - core_timing.ScheduleEvent(ticks, composition_event); + core_timing.ScheduleEvent(frame_ticks, composition_event); } NVFlinger::~NVFlinger() { @@ -206,8 +207,13 @@ void NVFlinger::Compose() { igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->get().transform, buffer->get().crop_rect); + swap_interval = buffer->get().swap_interval; buffer_queue.ReleaseBuffer(buffer->get().slot); } } +s64 NVFlinger::GetNextTicks() { + return (Core::Timing::BASE_CLOCK_RATE * (1LL << swap_interval)) / 120; +} + } // namespace Service::NVFlinger diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index c0a83fffb..86b94302c 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -74,6 +74,8 @@ public: /// finished. void Compose(); + s64 GetNextTicks(); + private: /// Finds the display identified by the specified ID. VI::Display* FindDisplay(u64 display_id); @@ -98,6 +100,8 @@ private: /// layers. u32 next_buffer_queue_id = 1; + u32 swap_interval = 1; + /// Event that handles screen composition. Core::Timing::EventType* composition_event; diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index f1fa6ccd1..55bd252c2 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -418,7 +418,8 @@ public: s32_le scaling_mode; NVFlinger::BufferQueue::BufferTransformFlags transform; u32_le sticky_transform; - INSERT_PADDING_WORDS(2); + INSERT_PADDING_WORDS(1); + u32_le swap_interval; u32_le fence_is_valid; std::array fences; @@ -582,7 +583,7 @@ private: IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()}; buffer_queue.QueueBuffer(request.data.slot, request.data.transform, - request.data.GetCropRect()); + request.data.GetCropRect(), request.data.swap_interval); IGBPQueueBufferResponseParcel response{1280, 720}; ctx.WriteBuffer(response.Serialize()); -- cgit v1.2.3 From 737e978f5b1440a044ef90f346c8616c2de49a81 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 7 Jun 2019 11:34:55 -0400 Subject: nv_services: Correct buffer queue fencing and GPFifo fencing --- src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 8 ++-- src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 22 +++++------ src/core/hle/service/nvdrv/nvdata.h | 25 ++++++++++++ src/core/hle/service/nvdrv/nvdrv.h | 8 +--- src/core/hle/service/nvflinger/buffer_queue.cpp | 9 +++-- src/core/hle/service/nvflinger/buffer_queue.h | 8 +++- src/core/hle/service/vi/vi.cpp | 46 ++++++++--------------- 7 files changed, 69 insertions(+), 57 deletions(-) create mode 100644 src/core/hle/service/nvdrv/nvdata.h (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 8ce7bc7a5..8a53eddb1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -155,8 +155,8 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector& input, std::vector& outp Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); - params.fence_out.id = 0; - params.fence_out.value = 0; + // TODO(Blinkhawk): Figure how thoios fence is set + // params.fence_out.value = 0; std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo)); return 0; } @@ -176,8 +176,8 @@ u32 nvhost_gpu::KickoffPB(const std::vector& input, std::vector& output) Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); - params.fence_out.id = 0; - params.fence_out.value = 0; + // TODO(Blinkhawk): Figure how thoios fence is set + // params.fence_out.value = 0; std::memcpy(output.data(), ¶ms, output.size()); return 0; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 62beb5c0c..d95cedb09 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -113,11 +113,11 @@ private: static_assert(sizeof(IoctlGetErrorNotification) == 16, "IoctlGetErrorNotification is incorrect size"); - struct IoctlFence { + struct Fence { u32_le id; u32_le value; }; - static_assert(sizeof(IoctlFence) == 8, "IoctlFence is incorrect size"); + static_assert(sizeof(Fence) == 8, "Fence is incorrect size"); struct IoctlAllocGpfifoEx { u32_le num_entries; @@ -132,13 +132,13 @@ private: static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx is incorrect size"); struct IoctlAllocGpfifoEx2 { - u32_le num_entries; // in - u32_le flags; // in - u32_le unk0; // in (1 works) - IoctlFence fence_out; // out - u32_le unk1; // in - u32_le unk2; // in - u32_le unk3; // in + u32_le num_entries; // in + u32_le flags; // in + u32_le unk0; // in (1 works) + Fence fence_out; // out + u32_le unk1; // in + u32_le unk2; // in + u32_le unk3; // in }; static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size"); @@ -154,9 +154,9 @@ private: u64_le address; // pointer to gpfifo entry structs u32_le num_entries; // number of fence objects being submitted u32_le flags; - IoctlFence fence_out; // returned new fence object for others to wait on + Fence fence_out; // returned new fence object for others to wait on }; - static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(IoctlFence), + static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence), "IoctlSubmitGpfifo is incorrect size"); struct IoctlGetWaitbase { diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h new file mode 100644 index 000000000..7e1dce232 --- /dev/null +++ b/src/core/hle/service/nvdrv/nvdata.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include "common/common_types.h" + +namespace Service::Nvidia { + +struct Fence { + s32 id; + u32 value; +}; + +static_assert(sizeof(Fence) == 8, "Fence has wrong size"); + +struct MultiFence { + u32 num_fences; + std::array fences; +}; + +enum class NvResult : u32 { + Success = 0, + TryAgain = 11, +}; + +} // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 53564f696..bacd7cdb7 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -8,6 +8,7 @@ #include #include #include "common/common_types.h" +#include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/service.h" namespace Service::NVFlinger { @@ -20,13 +21,6 @@ namespace Devices { class nvdevice; } -struct IoctlFence { - u32 id; - u32 value; -}; - -static_assert(sizeof(IoctlFence) == 8, "IoctlFence has wrong size"); - class Module final { public: Module(); diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index dca75c35e..75e47b8c7 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -34,7 +34,8 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) buffer_wait_event.writable->Signal(); } -std::optional BufferQueue::DequeueBuffer(u32 width, u32 height) { +std::optional> BufferQueue::DequeueBuffer(u32 width, + u32 height) { auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { // Only consider free buffers. Buffers become free once again after they've been Acquired // and Released by the compositor, see the NVFlinger::Compose method. @@ -51,7 +52,7 @@ std::optional BufferQueue::DequeueBuffer(u32 width, u32 height) { } itr->status = Buffer::Status::Dequeued; - return itr->slot; + return {{itr->slot, &itr->multi_fence}}; } const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { @@ -63,7 +64,8 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { } void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, - const Common::Rectangle& crop_rect, u32 swap_interval) { + const Common::Rectangle& crop_rect, u32 swap_interval, + Service::Nvidia::MultiFence& multi_fence) { auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { return buffer.slot == slot; }); ASSERT(itr != queue.end()); @@ -72,6 +74,7 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, itr->transform = transform; itr->crop_rect = crop_rect; itr->swap_interval = swap_interval; + itr->multi_fence = multi_fence; } std::optional> BufferQueue::AcquireBuffer() { diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 139b98b9f..c163e565c 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -12,6 +12,7 @@ #include "common/swap.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/writable_event.h" +#include "core/hle/service/nvdrv/nvdata.h" namespace Service::NVFlinger { @@ -69,13 +70,16 @@ public: BufferTransformFlags transform; Common::Rectangle crop_rect; u32 swap_interval; + Service::Nvidia::MultiFence multi_fence; }; void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer); - std::optional DequeueBuffer(u32 width, u32 height); + std::optional> DequeueBuffer(u32 width, + u32 height); const IGBPBuffer& RequestBuffer(u32 slot) const; void QueueBuffer(u32 slot, BufferTransformFlags transform, - const Common::Rectangle& crop_rect, u32 swap_interval); + const Common::Rectangle& crop_rect, u32 swap_interval, + Service::Nvidia::MultiFence& multi_fence); std::optional> AcquireBuffer(); void ReleaseBuffer(u32 slot); u32 Query(QueryType type); diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 55bd252c2..894bcdc04 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -21,6 +21,7 @@ #include "core/hle/kernel/readable_event.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/writable_event.h" +#include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvflinger/buffer_queue.h" #include "core/hle/service/nvflinger/nvflinger.h" @@ -328,32 +329,22 @@ public: Data data; }; -struct BufferProducerFence { - u32 is_valid; - std::array fences; -}; -static_assert(sizeof(BufferProducerFence) == 36, "BufferProducerFence has wrong size"); - class IGBPDequeueBufferResponseParcel : public Parcel { public: - explicit IGBPDequeueBufferResponseParcel(u32 slot) : slot(slot) {} + explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence) + : slot(slot), multi_fence(multi_fence) {} ~IGBPDequeueBufferResponseParcel() override = default; protected: void SerializeData() override { - // TODO(Subv): Find out how this Fence is used. - BufferProducerFence fence = {}; - fence.is_valid = 1; - for (auto& fence_ : fence.fences) - fence_.id = -1; - Write(slot); Write(1); - WriteObject(fence); + WriteObject(multi_fence); Write(0); } u32_le slot; + Service::Nvidia::MultiFence multi_fence; }; class IGBPRequestBufferRequestParcel : public Parcel { @@ -400,12 +391,6 @@ public: data = Read(); } - struct Fence { - u32_le id; - u32_le value; - }; - static_assert(sizeof(Fence) == 8, "Fence has wrong size"); - struct Data { u32_le slot; INSERT_PADDING_WORDS(3); @@ -420,14 +405,13 @@ public: u32_le sticky_transform; INSERT_PADDING_WORDS(1); u32_le swap_interval; - u32_le fence_is_valid; - std::array fences; + Service::Nvidia::MultiFence multi_fence; Common::Rectangle GetCropRect() const { return {crop_left, crop_top, crop_right, crop_bottom}; } }; - static_assert(sizeof(Data) == 80, "ParcelData has wrong size"); + static_assert(sizeof(Data) == 96, "ParcelData has wrong size"); Data data; }; @@ -548,11 +532,11 @@ private: IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()}; const u32 width{request.data.width}; const u32 height{request.data.height}; - std::optional slot = buffer_queue.DequeueBuffer(width, height); + auto result = buffer_queue.DequeueBuffer(width, height); - if (slot) { + if (result) { // Buffer is available - IGBPDequeueBufferResponseParcel response{*slot}; + IGBPDequeueBufferResponseParcel response{(*result).first, *(*result).second}; ctx.WriteBuffer(response.Serialize()); } else { // Wait the current thread until a buffer becomes available @@ -562,10 +546,11 @@ private: Kernel::ThreadWakeupReason reason) { // Repeat TransactParcel DequeueBuffer when a buffer is available auto& buffer_queue = nv_flinger->FindBufferQueue(id); - std::optional slot = buffer_queue.DequeueBuffer(width, height); - ASSERT_MSG(slot != std::nullopt, "Could not dequeue buffer."); + auto result = buffer_queue.DequeueBuffer(width, height); + ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); - IGBPDequeueBufferResponseParcel response{*slot}; + IGBPDequeueBufferResponseParcel response{(*result).first, + *(*result).second}; ctx.WriteBuffer(response.Serialize()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -583,7 +568,8 @@ private: IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()}; buffer_queue.QueueBuffer(request.data.slot, request.data.transform, - request.data.GetCropRect(), request.data.swap_interval); + request.data.GetCropRect(), request.data.swap_interval, + request.data.multi_fence); IGBPQueueBufferResponseParcel response{1280, 720}; ctx.WriteBuffer(response.Serialize()); -- cgit v1.2.3 From 82b829625b89a706dd0d867c529f533fe928710c Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 7 Jun 2019 12:56:30 -0400 Subject: video_core: Implement GPU side Syncpoints --- src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 30 ++++++++++++++++++----- src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 8 +++++- src/core/hle/service/nvdrv/nvdata.h | 2 ++ 3 files changed, 33 insertions(+), 7 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 8a53eddb1..9d1107594 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -143,7 +143,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector& input, std::vector& outp IoctlSubmitGpfifo params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", - params.address, params.num_entries, params.flags); + params.address, params.num_entries, params.flags.raw); ASSERT_MSG(input.size() == sizeof(IoctlSubmitGpfifo) + params.num_entries * sizeof(Tegra::CommandListHeader), @@ -153,7 +153,17 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector& input, std::vector& outp std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)], params.num_entries * sizeof(Tegra::CommandListHeader)); - Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); + UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0); + UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0); + + auto& gpu = Core::System::GetInstance().GPU(); + u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id); + if (params.flags.increment.Value()) { + params.fence_out.value += current_syncpoint_value; + } else { + params.fence_out.value = current_syncpoint_value; + } + gpu.PushGPUEntries(std::move(entries)); // TODO(Blinkhawk): Figure how thoios fence is set // params.fence_out.value = 0; @@ -168,16 +178,24 @@ u32 nvhost_gpu::KickoffPB(const std::vector& input, std::vector& output) IoctlSubmitGpfifo params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", - params.address, params.num_entries, params.flags); + params.address, params.num_entries, params.flags.raw); Tegra::CommandList entries(params.num_entries); Memory::ReadBlock(params.address, entries.data(), params.num_entries * sizeof(Tegra::CommandListHeader)); - Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); + UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0); + UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0); + + auto& gpu = Core::System::GetInstance().GPU(); + u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id); + if (params.flags.increment.Value()) { + params.fence_out.value += current_syncpoint_value; + } else { + params.fence_out.value = current_syncpoint_value; + } + gpu.PushGPUEntries(std::move(entries)); - // TODO(Blinkhawk): Figure how thoios fence is set - // params.fence_out.value = 0; std::memcpy(output.data(), ¶ms, output.size()); return 0; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index d95cedb09..0729eeb8d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -153,7 +153,13 @@ private: struct IoctlSubmitGpfifo { u64_le address; // pointer to gpfifo entry structs u32_le num_entries; // number of fence objects being submitted - u32_le flags; + union { + u32_le raw; + BitField<0, 1, u32_le> add_wait; // append a wait sync_point to the list + BitField<1, 1, u32_le> add_increment; // append an increment to the list + BitField<2, 1, u32_le> new_hw_format; // Mostly ignored + BitField<8, 1, u32_le> increment; // increment the returned fence + } flags; Fence fence_out; // returned new fence object for others to wait on }; static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence), diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h index 7e1dce232..fd5f79f36 100644 --- a/src/core/hle/service/nvdrv/nvdata.h +++ b/src/core/hle/service/nvdrv/nvdata.h @@ -5,6 +5,8 @@ namespace Service::Nvidia { +constexpr u32 MaxSyncPoints = 192; + struct Fence { s32 id; u32 value; -- cgit v1.2.3 From 7039ece0a0effbb62c18fba3ac57bdb3d89b27c8 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 7 Jun 2019 15:16:54 -0400 Subject: nv_services: Create GPU channels correctly --- src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 6 ++++-- src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 9d1107594..8083f5a87 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -119,8 +119,10 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector& input, std::vector& ou params.num_entries, params.flags, params.unk0, params.unk1, params.unk2, params.unk3); - params.fence_out.id = 0; - params.fence_out.value = 0; + auto& gpu = Core::System::GetInstance().GPU(); + params.fence_out.id = channels; + params.fence_out.value = gpu.GetSyncpointValue(channels); + channels++; std::memcpy(output.data(), ¶ms, output.size()); return 0; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 0729eeb8d..54378cb5d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -190,6 +190,7 @@ private: u32 ChannelSetTimeout(const std::vector& input, std::vector& output); std::shared_ptr nvmap_dev; + u32 channels{}; }; } // namespace Service::Nvidia::Devices -- cgit v1.2.3 From e0027eba854b9cf097360e898457e164e6ae0b4d Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 7 Jun 2019 18:41:55 -0400 Subject: nv_services: Implement NvQueryEvent, NvCtrlEventWait, NvEventRegister, NvEventUnregister --- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 91 +++++++++++++++++++--- src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 7 +- src/core/hle/service/nvdrv/interface.cpp | 17 +++- src/core/hle/service/nvdrv/interface.h | 2 + src/core/hle/service/nvdrv/nvdata.h | 14 +++- src/core/hle/service/nvdrv/nvdrv.cpp | 26 ++++++- src/core/hle/service/nvdrv/nvdrv.h | 52 +++++++++++++ 7 files changed, 192 insertions(+), 17 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index b39fb9ef9..ef6731a8f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -7,11 +7,15 @@ #include "common/assert.h" #include "common/logging/log.h" +#include "core/core.h" +#include "core/hle/kernel/readable_event.h" +#include "core/hle/kernel/writable_event.h" #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" +#include "video_core/gpu.h" namespace Service::Nvidia::Devices { -nvhost_ctrl::nvhost_ctrl() = default; +nvhost_ctrl::nvhost_ctrl(EventsInterface& events_interface) : events_interface{events_interface} {} nvhost_ctrl::~nvhost_ctrl() = default; u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector& input, std::vector& output) { @@ -27,6 +31,8 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector& input, std::vector< return IocCtrlEventWait(input, output, true); case IoctlCommand::IocCtrlEventRegisterCommand: return IocCtrlEventRegister(input, output); + case IoctlCommand::IocCtrlEventUnregisterCommand: + return IocCtrlEventUnregister(input, output); } UNIMPLEMENTED_MSG("Unimplemented ioctl"); return 0; @@ -44,20 +50,85 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& bool is_async) { IocCtrlEventWaitParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); - LOG_WARNING(Service_NVDRV, - "(STUBBED) called, syncpt_id={}, threshold={}, timeout={}, is_async={}", - params.syncpt_id, params.threshold, params.timeout, is_async); + LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_async={}", + params.syncpt_id, params.threshold, params.timeout, is_async); - // TODO(Subv): Implement actual syncpt waiting. - params.value = 0; + if (params.syncpt_id >= MaxSyncPoints) { + return NvResult::BadParameter; + } + + auto& gpu = Core::System::GetInstance().GPU(); + u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); + if (current_syncpoint_value >= params.threshold) { + params.value = current_syncpoint_value; + std::memcpy(output.data(), ¶ms, sizeof(params)); + return NvResult::Success; + } + + if (!is_async) { + params.value = 0; + } + + if (params.timeout == 0) { + std::memcpy(output.data(), ¶ms, sizeof(params)); + return NvResult::Timeout; + } + + u32 event_index; + if (is_async) { + event_index = params.value; + if (event_index >= 64) { + std::memcpy(output.data(), ¶ms, sizeof(params)); + return NvResult::BadParameter; + } + } else { + event_index = 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; + 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); + std::memcpy(output.data(), ¶ms, sizeof(params)); + return NvResult::Timeout; + } std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; + return NvResult::BadParameter; } u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector& input, std::vector& output) { - LOG_WARNING(Service_NVDRV, "(STUBBED) called"); - // TODO(bunnei): Implement this. - return 0; + IocCtrlEventRegisterParams params{}; + std::memcpy(¶ms, input.data(), sizeof(params)); + if (params.user_event_id >= MaxNvEvents) { + return NvResult::BadParameter; + } + if (events_interface.registered[params.user_event_id]) { + return NvResult::BadParameter; + } + events_interface.RegisterEvent(params.user_event_id); + return NvResult::Success; +} + +u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector& input, std::vector& output) { + IocCtrlEventUnregisterParams params{}; + std::memcpy(¶ms, input.data(), sizeof(params)); + if (params.user_event_id >= MaxNvEvents) { + return NvResult::BadParameter; + } + if (!events_interface.registered[params.user_event_id]) { + return NvResult::BadParameter; + } + events_interface.UnregisterEvent(params.user_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 6d0de2212..2985e7f75 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -8,12 +8,13 @@ #include #include "common/common_types.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" +#include "core/hle/service/nvdrv/nvdrv.h" namespace Service::Nvidia::Devices { class nvhost_ctrl final : public nvdevice { public: - nvhost_ctrl(); + nvhost_ctrl(EventsInterface& events_interface); ~nvhost_ctrl() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; @@ -135,6 +136,10 @@ private: u32 IocCtrlEventWait(const std::vector& input, std::vector& output, bool is_async); u32 IocCtrlEventRegister(const std::vector& input, std::vector& output); + + u32 IocCtrlEventUnregister(const std::vector& input, std::vector& output); + + EventsInterface& events_interface; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index b60fc748b..76482d16e 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -10,10 +10,15 @@ #include "core/hle/kernel/readable_event.h" #include "core/hle/kernel/writable_event.h" #include "core/hle/service/nvdrv/interface.h" +#include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/nvdrv/nvdrv.h" namespace Service::Nvidia { +void NVDRV::SignalGPUInterrupt(const u32 event_id) { + nvdrv->SignalEvent(event_id); +} + void NVDRV::Open(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NVDRV, "called"); @@ -66,13 +71,19 @@ void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; u32 fd = rp.Pop(); - u32 event_id = rp.Pop(); + // TODO(Blinkhawk): Figure the meaning of the flag at bit 16 + u32 event_id = rp.Pop() & 0x000000FF; LOG_WARNING(Service_NVDRV, "(STUBBED) called, fd={:X}, event_id={:X}", fd, event_id); IPC::ResponseBuilder rb{ctx, 3, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(query_event.readable); - rb.Push(0); + if (event_id < 64) { + rb.PushCopyObjects(nvdrv->GetEvent(event_id)); + rb.Push(NvResult::Success); + } else { + rb.Push(0); + rb.Push(NvResult::BadParameter); + } } void NVDRV::SetClientPID(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h index 5b4889910..421b01017 100644 --- a/src/core/hle/service/nvdrv/interface.h +++ b/src/core/hle/service/nvdrv/interface.h @@ -19,6 +19,8 @@ public: NVDRV(std::shared_ptr nvdrv, const char* name); ~NVDRV() override; + void SignalGPUInterrupt(const u32 event_id); + private: void Open(Kernel::HLERequestContext& ctx); void Ioctl(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h index fd5f79f36..6dbc90e4c 100644 --- a/src/core/hle/service/nvdrv/nvdata.h +++ b/src/core/hle/service/nvdrv/nvdata.h @@ -6,6 +6,7 @@ namespace Service::Nvidia { constexpr u32 MaxSyncPoints = 192; +constexpr u32 MaxNvEvents = 64; struct Fence { s32 id; @@ -19,9 +20,18 @@ struct MultiFence { std::array fences; }; -enum class NvResult : u32 { +enum NvResult : u32 { Success = 0, - TryAgain = 11, + BadParameter = 4, + Timeout = 5, + ResourceError = 15, +}; + +enum class EventState { + Free = 0, + Registered = 1, + Waiting = 2, + Busy = 3, }; } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 6e4b8f2c6..618bcbc7c 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -4,7 +4,10 @@ #include +#include #include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/readable_event.h" +#include "core/hle/kernel/writable_event.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" @@ -33,13 +36,21 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger } Module::Module() { + auto& kernel = Core::System::GetInstance().Kernel(); + for (u32 i = 0; i < MaxNvEvents; i++) { + std::string event_label = fmt::format("NVDRV::NvEvent_{}", i); + events_interface.events[i] = Kernel::WritableEvent::CreateEventPair( + kernel, Kernel::ResetType::Automatic, event_label); + events_interface.status[i] = EventState::Free; + events_interface.registered[i] = false; + } auto nvmap_dev = std::make_shared(); devices["/dev/nvhost-as-gpu"] = std::make_shared(nvmap_dev); devices["/dev/nvhost-gpu"] = std::make_shared(nvmap_dev); devices["/dev/nvhost-ctrl-gpu"] = std::make_shared(); devices["/dev/nvmap"] = nvmap_dev; devices["/dev/nvdisp_disp0"] = std::make_shared(nvmap_dev); - devices["/dev/nvhost-ctrl"] = std::make_shared(); + devices["/dev/nvhost-ctrl"] = std::make_shared(events_interface); devices["/dev/nvhost-nvdec"] = std::make_shared(); devices["/dev/nvhost-nvjpg"] = std::make_shared(); devices["/dev/nvhost-vic"] = std::make_shared(); @@ -77,4 +88,17 @@ ResultCode Module::Close(u32 fd) { return RESULT_SUCCESS; } +void Module::SignalEvent(const u32 event_id) { + if (event_id >= 64) { + LOG_ERROR(Service_NVDRV, "Unexpected Event signalled!"); + return; + } + events_interface.LiberateEvent(event_id); + events_interface.events[event_id].writable->Signal(); +} + +Kernel::SharedPtr Module::GetEvent(const u32 event_id) { + return events_interface.events[event_id].readable; +} + } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index bacd7cdb7..9a4cdc60f 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -15,12 +15,58 @@ namespace Service::NVFlinger { class NVFlinger; } +namespace Kernel { +class WritableEvent; +} + namespace Service::Nvidia { namespace Devices { class nvdevice; } +struct EventsInterface { + u64 events_mask; + std::array events; + std::array status; + std::array registered; + std::array assigned_syncpt; + std::array assigned_value; + u32 GetFreeEvent() { + u64 mask = events_mask; + for (u32 i = 0; i < MaxNvEvents; i++) { + if (mask & 0x1) { + if (status[i] == EventState::Registered || status[i] == EventState::Free) { + return i; + } + } + mask = mask >> 1; + } + return 0xFFFFFFFF; + } + void SetEventStatus(const u32 event_id, EventState new_status) { + status[event_id] = new_status; + if (new_status == EventState::Registered) { + registered[event_id] = true; + } + } + void RegisterEvent(const u32 event_id) { + registered[event_id] = true; + if (status[event_id] == EventState::Free) { + status[event_id] = EventState::Registered; + } + } + void UnregisterEvent(const u32 event_id) { + registered[event_id] = false; + if (status[event_id] == EventState::Registered) { + status[event_id] = EventState::Free; + } + } + void LiberateEvent(const u32 event_id) { + status[event_id] = registered[event_id] ? EventState::Registered : EventState::Free; + } +}; + class Module final { public: Module(); @@ -42,6 +88,10 @@ public: /// Closes a device file descriptor and returns operation success. ResultCode Close(u32 fd); + void SignalEvent(const u32 event_id); + + Kernel::SharedPtr GetEvent(const u32 event_id); + private: /// Id to use for the next open file descriptor. u32 next_fd = 1; @@ -51,6 +101,8 @@ private: /// Mapping of device node names to their implementation. std::unordered_map> devices; + + EventsInterface events_interface; }; /// Registers all NVDRV services with the specified service manager. -- cgit v1.2.3 From 8942047d419f6d2d0c56adad689fbf3bcd4d2961 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 7 Jun 2019 20:41:06 -0400 Subject: Gpu: Implement Hardware Interrupt Manager and manage GPU interrupts --- src/core/hle/service/nvdrv/interface.cpp | 2 -- src/core/hle/service/nvdrv/interface.h | 2 -- src/core/hle/service/nvdrv/nvdrv.h | 5 +---- 3 files changed, 1 insertion(+), 8 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 76482d16e..d95ba18cb 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -140,8 +140,6 @@ NVDRV::NVDRV(std::shared_ptr nvdrv, const char* name) RegisterHandlers(functions); auto& kernel = Core::System::GetInstance().Kernel(); - query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, - "NVDRV::query_event"); } NVDRV::~NVDRV() = default; diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h index 421b01017..09cf4bb12 100644 --- a/src/core/hle/service/nvdrv/interface.h +++ b/src/core/hle/service/nvdrv/interface.h @@ -35,8 +35,6 @@ private: std::shared_ptr nvdrv; u64 pid{}; - - Kernel::EventPair query_event; }; } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 9a4cdc60f..d299f2877 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -8,6 +8,7 @@ #include #include #include "common/common_types.h" +#include "core/hle/kernel/writable_event.h" #include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/service.h" @@ -15,10 +16,6 @@ namespace Service::NVFlinger { class NVFlinger; } -namespace Kernel { -class WritableEvent; -} - namespace Service::Nvidia { namespace Devices { -- cgit v1.2.3 From a45643cb3b07e76e73814baf1d472d636dd2cd91 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 7 Jun 2019 21:13:20 -0400 Subject: nv_services: Stub CtrlEventSignal --- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 44 ++++++++++++++++------ src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 2 + 2 files changed, 34 insertions(+), 12 deletions(-) (limited to 'src/core/hle/service') 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& 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& input, std::vector& 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& input, std::vecto return NvResult::Success; } +u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector& input, std::vector& 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& input, std::vector& output); + u32 IocCtrlEventSignal(const std::vector& input, std::vector& output); + EventsInterface& events_interface; }; -- cgit v1.2.3 From eef55f493b636bfc57389e9c541ddf2c39f6f826 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 7 Jun 2019 22:13:40 -0400 Subject: Gpu: Mark areas as protected. --- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 8f47d63e3..8e28c2fa4 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -60,10 +60,12 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& } auto& gpu = Core::System::GetInstance().GPU(); + gpu.Guard(true); u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); if (current_syncpoint_value >= params.threshold) { params.value = current_syncpoint_value; std::memcpy(output.data(), ¶ms, sizeof(params)); + gpu.Guard(false); return NvResult::Success; } @@ -73,6 +75,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& if (params.timeout == 0) { std::memcpy(output.data(), ¶ms, sizeof(params)); + gpu.Guard(false); return NvResult::Timeout; } @@ -81,6 +84,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& event_id = params.value & 0x00FF; if (event_id >= 64) { std::memcpy(output.data(), ¶ms, sizeof(params)); + gpu.Guard(false); return NvResult::BadParameter; } } else { @@ -100,9 +104,11 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& params.value |= event_id; gpu.RegisterEvent(event_id, params.syncpt_id, params.threshold); std::memcpy(output.data(), ¶ms, sizeof(params)); + gpu.Guard(false); return NvResult::Timeout; } std::memcpy(output.data(), ¶ms, sizeof(params)); + gpu.Guard(false); return NvResult::BadParameter; } -- cgit v1.2.3 From 78add28aabf0d9835336e5b4369b11308ab362e3 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 8 Jun 2019 15:13:26 -0400 Subject: nvhost_ctrl: Corrections to event handling --- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 18 +++++++++++------- src/core/hle/service/nvdrv/nvdrv.cpp | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 8e28c2fa4..5b1253f6b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -102,6 +102,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; } params.value |= event_id; + events_interface.events[event_id].writable->Clear(); gpu.RegisterEvent(event_id, params.syncpt_id, params.threshold); std::memcpy(output.data(), ¶ms, sizeof(params)); gpu.Guard(false); @@ -115,26 +116,29 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector& input, std::vector& output) { IocCtrlEventRegisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); - if (params.user_event_id >= MaxNvEvents) { + const u32 event_id = params.user_event_id & 0x00FF; + if (event_id >= MaxNvEvents) { return NvResult::BadParameter; } - if (events_interface.registered[params.user_event_id]) { + if (events_interface.registered[event_id]) { return NvResult::BadParameter; } - events_interface.RegisterEvent(params.user_event_id); + events_interface.RegisterEvent(event_id); + events_interface.events[event_id].writable->Signal(); return NvResult::Success; } u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector& input, std::vector& output) { IocCtrlEventUnregisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); - if (params.user_event_id >= MaxNvEvents) { + const u32 event_id = params.user_event_id & 0x00FF; + if (event_id >= MaxNvEvents) { return NvResult::BadParameter; } - if (!events_interface.registered[params.user_event_id]) { + if (!events_interface.registered[event_id]) { return NvResult::BadParameter; } - events_interface.UnregisterEvent(params.user_event_id); + events_interface.UnregisterEvent(event_id); return NvResult::Success; } @@ -142,7 +146,7 @@ u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector& input, std::vector= MaxNvEvents) { diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 618bcbc7c..3a716e734 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -40,7 +40,7 @@ Module::Module() { for (u32 i = 0; i < MaxNvEvents; i++) { std::string event_label = fmt::format("NVDRV::NvEvent_{}", i); events_interface.events[i] = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Automatic, event_label); + kernel, Kernel::ResetType::Manual, event_label); events_interface.status[i] = EventState::Free; events_interface.registered[i] = false; } -- cgit v1.2.3 From 0706d633bf7764455082cfdfdc35c14507cb6897 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 10 Jun 2019 08:19:27 -0400 Subject: nv_host_ctrl: Make Sync GPU variant always return synced result. --- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 5b1253f6b..96310ed83 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -60,6 +60,11 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& } auto& gpu = Core::System::GetInstance().GPU(); + // This is mostly to take into account unimplemented features. As synced + // gpu is always synced. + if (!gpu.IsAsync()) { + return NvResult::Success; + } gpu.Guard(true); u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); if (current_syncpoint_value >= params.threshold) { -- cgit v1.2.3 From 24408cce9bd899a6709c03b25e318123f4de7371 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 10 Jun 2019 12:03:30 -0400 Subject: nv_services: Deglobalize NvServices --- src/core/hle/service/nvdrv/devices/nvdevice.h | 9 ++++++- .../hle/service/nvdrv/devices/nvdisp_disp0.cpp | 5 ++-- src/core/hle/service/nvdrv/devices/nvdisp_disp0.h | 2 +- .../hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 12 ++++----- src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | 2 +- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 7 ++--- src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 2 +- .../hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 4 +-- .../hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | 2 +- src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 9 ++++--- src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 2 +- .../hle/service/nvdrv/devices/nvhost_nvdec.cpp | 2 +- src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | 2 +- .../hle/service/nvdrv/devices/nvhost_nvjpg.cpp | 2 +- src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h | 2 +- src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | 2 +- src/core/hle/service/nvdrv/devices/nvhost_vic.h | 2 +- src/core/hle/service/nvdrv/devices/nvmap.cpp | 2 +- src/core/hle/service/nvdrv/devices/nvmap.h | 2 +- src/core/hle/service/nvdrv/interface.cpp | 2 -- src/core/hle/service/nvdrv/nvdrv.cpp | 31 +++++++++++----------- src/core/hle/service/nvdrv/nvdrv.h | 9 +++++-- src/core/hle/service/service.cpp | 2 +- 23 files changed, 65 insertions(+), 51 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 4f6042b00..ed606cd15 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h @@ -9,13 +9,17 @@ #include "common/common_types.h" #include "common/swap.h" +namespace Core { +class System; +} + namespace Service::Nvidia::Devices { /// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to /// implement the ioctl interface. class nvdevice { public: - nvdevice() = default; + nvdevice(Core::System& system) : system{system} {}; virtual ~nvdevice() = default; union Ioctl { u32_le raw; @@ -34,6 +38,9 @@ public: * @returns The result code of the ioctl. */ virtual u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) = 0; + +protected: + Core::System& system; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 20c7c39aa..3336b2080 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -13,7 +13,8 @@ namespace Service::Nvidia::Devices { -nvdisp_disp0::nvdisp_disp0(std::shared_ptr nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {} +nvdisp_disp0::nvdisp_disp0(Core::System& system, std::shared_ptr nvmap_dev) + : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} nvdisp_disp0 ::~nvdisp_disp0() = default; u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector& input, std::vector& output) { @@ -34,7 +35,7 @@ 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 = Core::System::GetInstance(); + auto& instance = system; instance.GetPerfStats().EndGameFrame(); instance.GPU().SwapBuffers(framebuffer); } diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 12f3ef825..812967bdf 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -17,7 +17,7 @@ class nvmap; class nvdisp_disp0 final : public nvdevice { public: - explicit nvdisp_disp0(std::shared_ptr nvmap_dev); + explicit nvdisp_disp0(Core::System& system, std::shared_ptr nvmap_dev); ~nvdisp_disp0() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index af62d33d2..eccc3f1d9 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -22,7 +22,8 @@ enum { }; } -nvhost_as_gpu::nvhost_as_gpu(std::shared_ptr nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {} +nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr nvmap_dev) + : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} nvhost_as_gpu::~nvhost_as_gpu() = default; u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output) { @@ -65,7 +66,7 @@ u32 nvhost_as_gpu::AllocateSpace(const std::vector& input, std::vector& LOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages, params.page_size, params.flags); - auto& gpu = Core::System::GetInstance().GPU(); + auto& gpu = system.GPU(); const u64 size{static_cast(params.pages) * static_cast(params.page_size)}; if (params.flags & 1) { params.offset = gpu.MemoryManager().AllocateSpace(params.offset, size, 1); @@ -85,7 +86,7 @@ u32 nvhost_as_gpu::Remap(const std::vector& input, std::vector& output) std::vector entries(num_entries); std::memcpy(entries.data(), input.data(), input.size()); - auto& gpu = Core::System::GetInstance().GPU(); + auto& gpu = system.GPU(); for (const auto& entry : entries) { LOG_WARNING(Service_NVDRV, "remap entry, offset=0x{:X} handle=0x{:X} pages=0x{:X}", entry.offset, entry.nvmap_handle, entry.pages); @@ -136,7 +137,7 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector& input, std::vector& ou // case to prevent unexpected behavior. ASSERT(object->id == params.nvmap_handle); - auto& gpu = Core::System::GetInstance().GPU(); + auto& gpu = system.GPU(); if (params.flags & 1) { params.offset = gpu.MemoryManager().MapBufferEx(object->addr, params.offset, object->size); @@ -173,8 +174,7 @@ u32 nvhost_as_gpu::UnmapBuffer(const std::vector& input, std::vector& ou return 0; } - params.offset = Core::System::GetInstance().GPU().MemoryManager().UnmapBuffer(params.offset, - itr->second.size); + params.offset = system.GPU().MemoryManager().UnmapBuffer(params.offset, itr->second.size); buffer_mappings.erase(itr->second.offset); std::memcpy(output.data(), ¶ms, output.size()); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index eb14b1da8..e45d4f1ff 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -17,7 +17,7 @@ class nvmap; class nvhost_as_gpu final : public nvdevice { public: - explicit nvhost_as_gpu(std::shared_ptr nvmap_dev); + explicit nvhost_as_gpu(Core::System& system, std::shared_ptr nvmap_dev); ~nvhost_as_gpu() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 96310ed83..02b078c2f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -15,7 +15,8 @@ namespace Service::Nvidia::Devices { -nvhost_ctrl::nvhost_ctrl(EventsInterface& events_interface) : events_interface{events_interface} {} +nvhost_ctrl::nvhost_ctrl(Core::System& system, EventsInterface& events_interface) + : nvdevice(system), events_interface{events_interface} {} nvhost_ctrl::~nvhost_ctrl() = default; u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector& input, std::vector& output) { @@ -59,7 +60,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& return NvResult::BadParameter; } - auto& gpu = Core::System::GetInstance().GPU(); + auto& gpu = system.GPU(); // This is mostly to take into account unimplemented features. As synced // gpu is always synced. if (!gpu.IsAsync()) { @@ -158,7 +159,7 @@ u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector& input, std::vector& input, std::vector& output) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 0e28755bd..c139f2ceb 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -12,7 +12,7 @@ namespace Service::Nvidia::Devices { -nvhost_ctrl_gpu::nvhost_ctrl_gpu() = default; +nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system){}; nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default; u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output) { @@ -185,7 +185,7 @@ u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector& input, std::vector& o IoctlGetGpuTime params{}; std::memcpy(¶ms, input.data(), input.size()); - const auto ns = Core::Timing::CyclesToNs(Core::System::GetInstance().CoreTiming().GetTicks()); + const auto ns = Core::Timing::CyclesToNs(system.CoreTiming().GetTicks()); params.gpu_time = static_cast(ns.count()); std::memcpy(output.data(), ¶ms, output.size()); return 0; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index 240435eea..65eac47d1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { class nvhost_ctrl_gpu final : public nvdevice { public: - nvhost_ctrl_gpu(); + nvhost_ctrl_gpu(Core::System& system); ~nvhost_ctrl_gpu() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 8083f5a87..13e80bfad 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -13,7 +13,8 @@ namespace Service::Nvidia::Devices { -nvhost_gpu::nvhost_gpu(std::shared_ptr nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {} +nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr nvmap_dev) + : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} nvhost_gpu::~nvhost_gpu() = default; u32 nvhost_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output) { @@ -119,7 +120,7 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector& input, std::vector& ou params.num_entries, params.flags, params.unk0, params.unk1, params.unk2, params.unk3); - auto& gpu = Core::System::GetInstance().GPU(); + auto& gpu = system.GPU(); params.fence_out.id = channels; params.fence_out.value = gpu.GetSyncpointValue(channels); channels++; @@ -158,7 +159,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector& input, std::vector& outp UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0); UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0); - auto& gpu = Core::System::GetInstance().GPU(); + auto& gpu = system.GPU(); u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id); if (params.flags.increment.Value()) { params.fence_out.value += current_syncpoint_value; @@ -189,7 +190,7 @@ u32 nvhost_gpu::KickoffPB(const std::vector& input, std::vector& output) UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0); UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0); - auto& gpu = Core::System::GetInstance().GPU(); + auto& gpu = system.GPU(); u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id); if (params.flags.increment.Value()) { params.fence_out.value += current_syncpoint_value; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 54378cb5d..106359f87 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -20,7 +20,7 @@ constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b); class nvhost_gpu final : public nvdevice { public: - explicit nvhost_gpu(std::shared_ptr nvmap_dev); + explicit nvhost_gpu(Core::System& system, std::shared_ptr nvmap_dev); ~nvhost_gpu() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index f5e8ea7c3..3bfcb8423 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -10,7 +10,7 @@ namespace Service::Nvidia::Devices { -nvhost_nvdec::nvhost_nvdec() = default; +nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system){}; nvhost_nvdec::~nvhost_nvdec() = default; u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector& input, std::vector& output) { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index 0e7b284f8..febfd4cc4 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { class nvhost_nvdec final : public nvdevice { public: - nvhost_nvdec(); + nvhost_nvdec(Core::System& system); ~nvhost_nvdec() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index 3e0951ab0..16c683b47 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp @@ -10,7 +10,7 @@ namespace Service::Nvidia::Devices { -nvhost_nvjpg::nvhost_nvjpg() = default; +nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system){}; nvhost_nvjpg::~nvhost_nvjpg() = default; u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector& input, std::vector& output) { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 89fd5e95e..33b149bb7 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { class nvhost_nvjpg final : public nvdevice { public: - nvhost_nvjpg(); + nvhost_nvjpg(Core::System& system); ~nvhost_nvjpg() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index d544f0f31..853136dea 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -10,7 +10,7 @@ namespace Service::Nvidia::Devices { -nvhost_vic::nvhost_vic() = default; +nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system){}; nvhost_vic::~nvhost_vic() = default; u32 nvhost_vic::ioctl(Ioctl command, const std::vector& input, std::vector& output) { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index fc24c3f9c..b71816ba1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { class nvhost_vic final : public nvdevice { public: - nvhost_vic(); + nvhost_vic(Core::System& system); ~nvhost_vic() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 1ec796fc6..a75ff334b 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -18,7 +18,7 @@ enum { }; } -nvmap::nvmap() = default; +nvmap::nvmap(Core::System& system) : nvdevice(system){}; nvmap::~nvmap() = default; VAddr nvmap::GetObjectAddress(u32 handle) const { diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 396230c19..623c9b232 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h @@ -16,7 +16,7 @@ namespace Service::Nvidia::Devices { class nvmap final : public nvdevice { public: - nvmap(); + nvmap(Core::System& system); ~nvmap() override; /// Returns the allocated address of an nvmap object given its handle. diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index d95ba18cb..c548f1223 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -138,8 +138,6 @@ NVDRV::NVDRV(std::shared_ptr nvdrv, const char* name) {13, &NVDRV::FinishInitialize, "FinishInitialize"}, }; RegisterHandlers(functions); - - auto& kernel = Core::System::GetInstance().Kernel(); } NVDRV::~NVDRV() = default; diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 3a716e734..c68d29177 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -25,8 +25,9 @@ namespace Service::Nvidia { -void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger) { - auto module_ = std::make_shared(); +void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, + Core::System& system) { + auto module_ = std::make_shared(system); std::make_shared(module_, "nvdrv")->InstallAsService(service_manager); std::make_shared(module_, "nvdrv:a")->InstallAsService(service_manager); std::make_shared(module_, "nvdrv:s")->InstallAsService(service_manager); @@ -35,25 +36,25 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger nvflinger.SetNVDrvInstance(module_); } -Module::Module() { - auto& kernel = Core::System::GetInstance().Kernel(); +Module::Module(Core::System& system) { + auto& kernel = system.Kernel(); for (u32 i = 0; i < MaxNvEvents; i++) { std::string event_label = fmt::format("NVDRV::NvEvent_{}", i); - events_interface.events[i] = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Manual, event_label); + events_interface.events[i] = + Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, event_label); events_interface.status[i] = EventState::Free; events_interface.registered[i] = false; } - auto nvmap_dev = std::make_shared(); - devices["/dev/nvhost-as-gpu"] = std::make_shared(nvmap_dev); - devices["/dev/nvhost-gpu"] = std::make_shared(nvmap_dev); - devices["/dev/nvhost-ctrl-gpu"] = std::make_shared(); + auto nvmap_dev = std::make_shared(system); + devices["/dev/nvhost-as-gpu"] = std::make_shared(system, nvmap_dev); + devices["/dev/nvhost-gpu"] = std::make_shared(system, nvmap_dev); + devices["/dev/nvhost-ctrl-gpu"] = std::make_shared(system); devices["/dev/nvmap"] = nvmap_dev; - devices["/dev/nvdisp_disp0"] = std::make_shared(nvmap_dev); - devices["/dev/nvhost-ctrl"] = std::make_shared(events_interface); - devices["/dev/nvhost-nvdec"] = std::make_shared(); - devices["/dev/nvhost-nvjpg"] = std::make_shared(); - devices["/dev/nvhost-vic"] = std::make_shared(); + devices["/dev/nvdisp_disp0"] = std::make_shared(system, nvmap_dev); + devices["/dev/nvhost-ctrl"] = std::make_shared(system, events_interface); + devices["/dev/nvhost-nvdec"] = std::make_shared(system); + devices["/dev/nvhost-nvjpg"] = std::make_shared(system); + devices["/dev/nvhost-vic"] = std::make_shared(system); } Module::~Module() = default; diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index d299f2877..0e8eed113 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -12,6 +12,10 @@ #include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::NVFlinger { class NVFlinger; } @@ -66,7 +70,7 @@ struct EventsInterface { class Module final { public: - Module(); + Module(Core::System& system); ~Module(); /// Returns a pointer to one of the available devices, identified by its name. @@ -103,6 +107,7 @@ private: }; /// Registers all NVDRV services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger); +void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, + Core::System& system); } // namespace Service::Nvidia diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 5fc7d3cab..07b1f4d43 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -237,7 +237,7 @@ void Init(std::shared_ptr& sm, Core::System& system, NIM::InstallInterfaces(*sm); NPNS::InstallInterfaces(*sm); NS::InstallInterfaces(*sm); - Nvidia::InstallInterfaces(*sm, *nv_flinger); + Nvidia::InstallInterfaces(*sm, *nv_flinger, system); PCIe::InstallInterfaces(*sm); PCTL::InstallInterfaces(*sm); PCV::InstallInterfaces(*sm); -- cgit v1.2.3 From ea975896242fba4a92d68c8fb45751e60ed826cc Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 10 Jun 2019 22:58:20 -0400 Subject: nvflinger: Acquire buffers in the same order as they were queued. --- src/core/hle/service/nvflinger/buffer_queue.cpp | 12 +++++++++--- src/core/hle/service/nvflinger/buffer_queue.h | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 75e47b8c7..d8aa3f1c0 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -75,12 +75,18 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, itr->crop_rect = crop_rect; itr->swap_interval = swap_interval; itr->multi_fence = multi_fence; + queue_sequence.push_back(slot); } std::optional> BufferQueue::AcquireBuffer() { - auto itr = std::find_if(queue.begin(), queue.end(), [](const Buffer& buffer) { - return buffer.status == Buffer::Status::Queued; - }); + std::vector::iterator itr = queue.end(); + while (itr == queue.end() && !queue_sequence.empty()) { + u32 slot = queue_sequence.front(); + itr = std::find_if(queue.begin(), queue.end(), [&slot](const Buffer& buffer) { + return buffer.status == Buffer::Status::Queued && buffer.slot == slot; + }); + queue_sequence.pop_front(); + } if (itr == queue.end()) return {}; itr->status = Buffer::Status::Acquired; diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index c163e565c..be993ee61 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -6,6 +6,7 @@ #include #include +#include #include "common/common_funcs.h" #include "common/math_util.h" @@ -97,6 +98,7 @@ private: u64 layer_id; std::vector queue; + std::list queue_sequence; Kernel::EventPair buffer_wait_event; }; -- cgit v1.2.3 From efdeab3a1d5735a8b000241f09ba57e9b981204b Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 11 Jun 2019 17:04:24 -0400 Subject: nv_services: Fixes to event liberation. --- src/core/hle/service/nvdrv/nvdrv.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 0e8eed113..597acc9c6 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -27,16 +27,17 @@ class nvdevice; } struct EventsInterface { - u64 events_mask; + u64 events_mask{}; std::array events; - std::array status; - std::array registered; - std::array assigned_syncpt; - std::array assigned_value; + std::array status{}; + std::array registered{}; + std::array assigned_syncpt{}; + std::array assigned_value{}; u32 GetFreeEvent() { u64 mask = events_mask; for (u32 i = 0; i < MaxNvEvents; i++) { - if (mask & 0x1) { + const bool is_free = (mask & 0x1) == 0; + if (is_free) { if (status[i] == EventState::Registered || status[i] == EventState::Free) { return i; } @@ -46,10 +47,16 @@ struct EventsInterface { return 0xFFFFFFFF; } void SetEventStatus(const u32 event_id, EventState new_status) { + EventState old_status = status[event_id]; + if (old_status == new_status) + return; status[event_id] = new_status; if (new_status == EventState::Registered) { registered[event_id] = true; } + if (new_status == EventState::Waiting || new_status == EventState::Busy) { + events_mask |= (1 << event_id); + } } void RegisterEvent(const u32 event_id) { registered[event_id] = true; @@ -65,6 +72,7 @@ struct EventsInterface { } void LiberateEvent(const u32 event_id) { status[event_id] = registered[event_id] ? EventState::Registered : EventState::Free; + events_mask &= ~(1 << event_id); } }; -- cgit v1.2.3 From 61697864c3c8abc35ce957f5f0a0dacd7a8e96f9 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 11 Jun 2019 17:56:36 -0400 Subject: nvflinger: Make the force 30 fps still force 30 fps --- src/core/hle/service/nvflinger/nvflinger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 6d83535e7..a7937b490 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -42,7 +42,7 @@ NVFlinger::NVFlinger(Core::Timing::CoreTiming& core_timing) : core_timing{core_t composition_event = core_timing.RegisterEvent( "ScreenComposition", [this](u64 userdata, s64 cycles_late) { Compose(); - const auto ticks = GetNextTicks(); + const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : GetNextTicks(); this->core_timing.ScheduleEvent(std::max(0LL,ticks - cycles_late), composition_event); }); -- cgit v1.2.3 From 7d1b974bcaf72c32910dcf4ff2d435f91cf40609 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 12 Jun 2019 07:52:49 -0400 Subject: GPU: Correct Interrupts to interrupt on syncpt/value instead of event, mirroring hardware --- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 5 +---- src/core/hle/service/nvdrv/interface.cpp | 4 ++-- src/core/hle/service/nvdrv/interface.h | 2 +- src/core/hle/service/nvdrv/nvdrv.cpp | 13 +++++++------ src/core/hle/service/nvdrv/nvdrv.h | 4 +++- 5 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 02b078c2f..d41274616 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -109,7 +109,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& } params.value |= event_id; events_interface.events[event_id].writable->Clear(); - gpu.RegisterEvent(event_id, params.syncpt_id, params.threshold); + gpu.RegisterSyncptInterrupt(params.syncpt_id, params.threshold); std::memcpy(output.data(), ¶ms, sizeof(params)); gpu.Guard(false); return NvResult::Timeout; @@ -159,9 +159,6 @@ u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector& input, std::vectorSignalEvent(event_id); +void NVDRV::SignalGPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { + nvdrv->SignalSyncpt(syncpoint_id, value); } void NVDRV::Open(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h index 09cf4bb12..10a0ecd52 100644 --- a/src/core/hle/service/nvdrv/interface.h +++ b/src/core/hle/service/nvdrv/interface.h @@ -19,7 +19,7 @@ public: NVDRV(std::shared_ptr nvdrv, const char* name); ~NVDRV() override; - void SignalGPUInterrupt(const u32 event_id); + void SignalGPUInterruptSyncpt(const u32 syncpoint_id, const u32 value); private: void Open(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index c68d29177..b87c228bd 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -89,13 +89,14 @@ ResultCode Module::Close(u32 fd) { return RESULT_SUCCESS; } -void Module::SignalEvent(const u32 event_id) { - if (event_id >= 64) { - LOG_ERROR(Service_NVDRV, "Unexpected Event signalled!"); - return; +void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) { + for (u32 i = 0; i < MaxNvEvents; i++) { + if (events_interface.assigned_syncpt[i] == syncpoint_id && + events_interface.assigned_value[i] == value) { + events_interface.LiberateEvent(i); + events_interface.events[i].writable->Signal(); + } } - events_interface.LiberateEvent(event_id); - events_interface.events[event_id].writable->Signal(); } Kernel::SharedPtr Module::GetEvent(const u32 event_id) { diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 597acc9c6..97b48d150 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -73,6 +73,8 @@ struct EventsInterface { 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; + assigned_value[event_id] = 0; } }; @@ -97,7 +99,7 @@ public: /// Closes a device file descriptor and returns operation success. ResultCode Close(u32 fd); - void SignalEvent(const u32 event_id); + void SignalSyncpt(const u32 syncpoint_id, const u32 value); Kernel::SharedPtr GetEvent(const u32 event_id); -- cgit v1.2.3 From b6844bec608ed82511738e9f3911e72aeb05243a Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 16 Jun 2019 11:43:41 -0400 Subject: NVServices: Correct CtrlEventWaitSync to block the ipc until timeout. --- src/core/hle/service/nvdrv/devices/nvdevice.h | 4 ++- .../hle/service/nvdrv/devices/nvdisp_disp0.cpp | 3 +- src/core/hle/service/nvdrv/devices/nvdisp_disp0.h | 3 +- .../hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 3 +- src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | 3 +- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 22 ++++++++++---- src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 6 ++-- .../hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 3 +- .../hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | 3 +- src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 3 +- src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 3 +- .../hle/service/nvdrv/devices/nvhost_nvdec.cpp | 3 +- src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | 3 +- .../hle/service/nvdrv/devices/nvhost_nvjpg.cpp | 3 +- src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h | 3 +- src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | 3 +- src/core/hle/service/nvdrv/devices/nvhost_vic.h | 3 +- src/core/hle/service/nvdrv/devices/nvmap.cpp | 3 +- src/core/hle/service/nvdrv/devices/nvmap.h | 3 +- src/core/hle/service/nvdrv/interface.cpp | 34 +++++++++++++++++++--- src/core/hle/service/nvdrv/nvdata.h | 7 +++++ src/core/hle/service/nvdrv/nvdrv.cpp | 9 ++++-- src/core/hle/service/nvdrv/nvdrv.h | 5 +++- 23 files changed, 104 insertions(+), 31 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index ed606cd15..fae69eb19 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h @@ -8,6 +8,7 @@ #include "common/bit_field.h" #include "common/common_types.h" #include "common/swap.h" +#include "core/hle/service/nvdrv/nvdata.h" namespace Core { class System; @@ -37,7 +38,8 @@ public: * @param output A buffer where the output data will be written to. * @returns The result code of the ioctl. */ - virtual u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) = 0; + virtual u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) = 0; protected: Core::System& system; diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 3336b2080..c918b4225 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -17,7 +17,8 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system, std::shared_ptr nvmap_de : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} nvdisp_disp0 ::~nvdisp_disp0() = default; -u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector& input, std::vector& output) { +u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { UNIMPLEMENTED_MSG("Unimplemented ioctl"); return 0; } diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 812967bdf..e79e490ff 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -20,7 +20,8 @@ public: explicit nvdisp_disp0(Core::System& system, std::shared_ptr nvmap_dev); ~nvdisp_disp0() override; - u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) override; /// Performs a screen flip, drawing the buffer pointed to by the handle. void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index eccc3f1d9..24ab3f2e9 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -26,7 +26,8 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr nvmap_ : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} nvhost_as_gpu::~nvhost_as_gpu() = default; -u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output) { +u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", command.raw, input.size(), output.size()); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index e45d4f1ff..30ca5f4c3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -20,7 +20,8 @@ public: explicit nvhost_as_gpu(Core::System& system, std::shared_ptr nvmap_dev); ~nvhost_as_gpu() override; - u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) override; private: enum class IoctlCommand : u32_le { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index d41274616..e46e6b94c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -19,7 +19,8 @@ nvhost_ctrl::nvhost_ctrl(Core::System& system, EventsInterface& events_interface : nvdevice(system), events_interface{events_interface} {} nvhost_ctrl::~nvhost_ctrl() = default; -u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector& input, std::vector& output) { +u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", command.raw, input.size(), output.size()); @@ -27,9 +28,9 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector& input, std::vector< case IoctlCommand::IocGetConfigCommand: return NvOsGetConfigU32(input, output); case IoctlCommand::IocCtrlEventWaitCommand: - return IocCtrlEventWait(input, output, false); + return IocCtrlEventWait(input, output, false, ctrl); case IoctlCommand::IocCtrlEventWaitAsyncCommand: - return IocCtrlEventWait(input, output, true); + return IocCtrlEventWait(input, output, true, ctrl); case IoctlCommand::IocCtrlEventRegisterCommand: return IocCtrlEventRegister(input, output); case IoctlCommand::IocCtrlEventUnregisterCommand: @@ -50,7 +51,7 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector& input, std::vector& } u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& output, - bool is_async) { + bool is_async, IoctlCtrl& ctrl) { IocCtrlEventWaitParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_async={}", @@ -94,7 +95,11 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& return NvResult::BadParameter; } } else { - event_id = events_interface.GetFreeEvent(); + if (ctrl.fresh_call) { + event_id = events_interface.GetFreeEvent(); + } else { + event_id = ctrl.event_id; + } } EventState status = events_interface.status[event_id]; @@ -110,6 +115,13 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& params.value |= event_id; events_interface.events[event_id].writable->Clear(); gpu.RegisterSyncptInterrupt(params.syncpt_id, params.threshold); + if (!is_async && ctrl.fresh_call) { + ctrl.must_delay = true; + ctrl.timeout = params.timeout; + ctrl.event_id = event_id; + gpu.Guard(false); + return NvResult::Timeout; + } std::memcpy(output.data(), ¶ms, sizeof(params)); gpu.Guard(false); return NvResult::Timeout; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 6cbf75f89..7cb41aa54 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -17,7 +17,8 @@ public: nvhost_ctrl(Core::System& system, EventsInterface& events_interface); ~nvhost_ctrl() override; - u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) override; private: enum class IoctlCommand : u32_le { @@ -133,7 +134,8 @@ private: u32 NvOsGetConfigU32(const std::vector& input, std::vector& output); - u32 IocCtrlEventWait(const std::vector& input, std::vector& output, bool is_async); + u32 IocCtrlEventWait(const std::vector& input, std::vector& output, bool is_async, + IoctlCtrl& ctrl); u32 IocCtrlEventRegister(const std::vector& input, std::vector& output); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index c139f2ceb..e3d2b4470 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -15,7 +15,8 @@ namespace Service::Nvidia::Devices { nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system){}; nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default; -u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output) { +u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", command.raw, input.size(), output.size()); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index 65eac47d1..de36cb014 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -16,7 +16,8 @@ public: nvhost_ctrl_gpu(Core::System& system); ~nvhost_ctrl_gpu() override; - u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) override; private: enum class IoctlCommand : u32_le { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 13e80bfad..b9e13fae9 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -17,7 +17,8 @@ nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr nvmap_dev) : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} nvhost_gpu::~nvhost_gpu() = default; -u32 nvhost_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output) { +u32 nvhost_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", command.raw, input.size(), output.size()); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 106359f87..edc37ff3a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -23,7 +23,8 @@ public: explicit nvhost_gpu(Core::System& system, std::shared_ptr nvmap_dev); ~nvhost_gpu() override; - u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) override; private: enum class IoctlCommand : u32_le { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 3bfcb8423..f464328f3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -13,7 +13,8 @@ namespace Service::Nvidia::Devices { nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system){}; nvhost_nvdec::~nvhost_nvdec() = default; -u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector& input, std::vector& output) { +u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", command.raw, input.size(), output.size()); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index febfd4cc4..c2b7a22f6 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h @@ -16,7 +16,8 @@ public: nvhost_nvdec(Core::System& system); ~nvhost_nvdec() override; - u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) override; private: enum class IoctlCommand : u32_le { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index 16c683b47..d4d67fc72 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp @@ -13,7 +13,8 @@ namespace Service::Nvidia::Devices { nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system){}; nvhost_nvjpg::~nvhost_nvjpg() = default; -u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector& input, std::vector& output) { +u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", command.raw, input.size(), output.size()); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 33b149bb7..4bf280d67 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h @@ -16,7 +16,8 @@ public: nvhost_nvjpg(Core::System& system); ~nvhost_nvjpg() override; - u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) override; private: enum class IoctlCommand : u32_le { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 853136dea..24e38d31a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -13,7 +13,8 @@ namespace Service::Nvidia::Devices { nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system){}; nvhost_vic::~nvhost_vic() = default; -u32 nvhost_vic::ioctl(Ioctl command, const std::vector& input, std::vector& output) { +u32 nvhost_vic::ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", command.raw, input.size(), output.size()); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index b71816ba1..3d0934a78 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h @@ -16,7 +16,8 @@ public: nvhost_vic(Core::System& system); ~nvhost_vic() override; - u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) override; private: enum class IoctlCommand : u32_le { diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index a75ff334b..349454685 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -28,7 +28,8 @@ VAddr nvmap::GetObjectAddress(u32 handle) const { return object->addr; } -u32 nvmap::ioctl(Ioctl command, const std::vector& input, std::vector& output) { +u32 nvmap::ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { switch (static_cast(command.raw)) { case IoctlCommand::Create: return IocCreate(input, output); diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 623c9b232..b79ed736c 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h @@ -22,7 +22,8 @@ public: /// Returns the allocated address of an nvmap object given its handle. VAddr GetObjectAddress(u32 handle) const; - u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) override; /// Represents an nvmap object. struct Object { diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index a4cb8cb81..45912153d 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -8,6 +8,7 @@ #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/readable_event.h" +#include "core/hle/kernel/thread.h" #include "core/hle/kernel/writable_event.h" #include "core/hle/service/nvdrv/interface.h" #include "core/hle/service/nvdrv/nvdata.h" @@ -41,11 +42,36 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { std::vector output(ctx.GetWriteBufferSize()); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output)); + IoctlCtrl ctrl{}; + + u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output, ctrl); - ctx.WriteBuffer(output); + if (!ctrl.must_delay) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(result); + + ctx.WriteBuffer(output); + return; + } + ctrl.fresh_call = false; + ctx.SleepClientThread( + "NVServices::DelayedResponse", ctrl.timeout, + [this, ctrl = ctrl](Kernel::SharedPtr thread, Kernel::HLERequestContext& ctx, + Kernel::ThreadWakeupReason reason) { + IPC::RequestParser rp{ctx}; + u32 fd = rp.Pop(); + u32 command = rp.Pop(); + std::vector output(ctx.GetWriteBufferSize()); + IoctlCtrl ctrl2{ctrl}; + u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output, ctrl2); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(result); + + ctx.WriteBuffer(output); + }, + nvdrv->GetEventWriteable(ctrl.event_id)); } void NVDRV::Close(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h index 6dbc90e4c..22b1dc79b 100644 --- a/src/core/hle/service/nvdrv/nvdata.h +++ b/src/core/hle/service/nvdrv/nvdata.h @@ -34,4 +34,11 @@ enum class EventState { Busy = 3, }; +struct IoctlCtrl { + bool fresh_call{true}; + bool must_delay{}; + s64 timeout{}; + s32 event_id{-1}; +}; + } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index b87c228bd..598a1123b 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -71,12 +71,13 @@ u32 Module::Open(const std::string& device_name) { return fd; } -u32 Module::Ioctl(u32 fd, u32 command, const std::vector& input, std::vector& output) { +u32 Module::Ioctl(u32 fd, u32 command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl) { auto itr = open_files.find(fd); ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); auto& device = itr->second; - return device->ioctl({command}, input, output); + return device->ioctl({command}, input, output, ctrl); } ResultCode Module::Close(u32 fd) { @@ -103,4 +104,8 @@ Kernel::SharedPtr Module::GetEvent(const u32 event_id) { return events_interface.events[event_id].readable; } +Kernel::SharedPtr Module::GetEventWriteable(const u32 event_id) { + return events_interface.events[event_id].writable; +} + } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 97b48d150..b7f692962 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -95,7 +95,8 @@ public: /// Opens a device node and returns a file descriptor to it. u32 Open(const std::string& device_name); /// Sends an ioctl command to the specified file descriptor. - u32 Ioctl(u32 fd, u32 command, const std::vector& input, std::vector& output); + u32 Ioctl(u32 fd, u32 command, const std::vector& input, std::vector& output, + IoctlCtrl& ctrl); /// Closes a device file descriptor and returns operation success. ResultCode Close(u32 fd); @@ -103,6 +104,8 @@ public: Kernel::SharedPtr GetEvent(const u32 event_id); + Kernel::SharedPtr GetEventWriteable(const u32 event_id); + private: /// Id to use for the next open file descriptor. u32 next_fd = 1; -- cgit v1.2.3 From 0335a25d1fcca5328ef79b3c62edb679df63ffba Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 17 Jun 2019 15:27:42 -0400 Subject: NVServices: Make NVEvents Automatic according to documentation. --- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 7 +++++-- src/core/hle/service/nvdrv/nvdrv.cpp | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index e46e6b94c..ffa6e75c7 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -142,7 +142,6 @@ u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector& input, std::vector< return NvResult::BadParameter; } events_interface.RegisterEvent(event_id); - events_interface.events[event_id].writable->Signal(); return NvResult::Success; } @@ -171,7 +170,11 @@ u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector& input, std::vector Date: Tue, 18 Jun 2019 16:58:29 -0400 Subject: NVFlinger: Correct GCC compile error --- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 1 + src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 8 +++----- src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 2 +- src/core/hle/service/nvdrv/interface.cpp | 4 ++-- src/core/hle/service/nvflinger/buffer_queue.h | 2 +- src/core/hle/service/nvflinger/nvflinger.cpp | 16 ++++++++-------- 6 files changed, 16 insertions(+), 17 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index ffa6e75c7..a5a4f8c7b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -174,6 +174,7 @@ u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector& input, std::vectorSignal(); } } return NvResult::Success; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index b9e13fae9..241dac881 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -122,9 +122,9 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector& input, std::vector& ou params.unk3); auto& gpu = system.GPU(); - params.fence_out.id = channels; - params.fence_out.value = gpu.GetSyncpointValue(channels); - channels++; + params.fence_out.id = assigned_syncpoints; + params.fence_out.value = gpu.GetSyncpointValue(assigned_syncpoints); + assigned_syncpoints++; std::memcpy(output.data(), ¶ms, output.size()); return 0; } @@ -169,8 +169,6 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector& input, std::vector& outp } gpu.PushGPUEntries(std::move(entries)); - // TODO(Blinkhawk): Figure how thoios fence is set - // params.fence_out.value = 0; std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo)); return 0; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index edc37ff3a..3ad8e1db1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -191,7 +191,7 @@ private: u32 ChannelSetTimeout(const std::vector& input, std::vector& output); std::shared_ptr nvmap_dev; - u32 channels{}; + u32 assigned_syncpoints{}; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 45912153d..6f7c7502a 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -57,8 +57,8 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { ctrl.fresh_call = false; ctx.SleepClientThread( "NVServices::DelayedResponse", ctrl.timeout, - [this, ctrl = ctrl](Kernel::SharedPtr thread, Kernel::HLERequestContext& ctx, - Kernel::ThreadWakeupReason reason) { + [this, ctrl = ctrl](Kernel::SharedPtr thread, + Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { IPC::RequestParser rp{ctx}; u32 fd = rp.Pop(); u32 command = rp.Pop(); diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index be993ee61..356bedb81 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -4,9 +4,9 @@ #pragma once +#include #include #include -#include #include "common/common_funcs.h" #include "common/math_util.h" diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index a7937b490..70441f6a2 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -37,14 +37,14 @@ NVFlinger::NVFlinger(Core::Timing::CoreTiming& core_timing) : core_timing{core_t displays.emplace_back(4, "Null"); // Schedule the screen composition events - //const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : frame_ticks; - - composition_event = core_timing.RegisterEvent( - "ScreenComposition", [this](u64 userdata, s64 cycles_late) { - Compose(); - const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : GetNextTicks(); - this->core_timing.ScheduleEvent(std::max(0LL,ticks - cycles_late), composition_event); - }); + // const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : frame_ticks; + + composition_event = core_timing.RegisterEvent("ScreenComposition", [this](u64 userdata, + s64 cycles_late) { + Compose(); + const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : GetNextTicks(); + this->core_timing.ScheduleEvent(std::max(0LL, ticks - cycles_late), composition_event); + }); core_timing.ScheduleEvent(frame_ticks, composition_event); } -- cgit v1.2.3 From d20ede40b1e9cd0539982fb1feb3b13af3501ea2 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 18 Jun 2019 20:53:21 -0400 Subject: NVServices: Styling, define constructors as explicit and corrections --- src/core/hle/service/nvdrv/devices/nvdevice.h | 2 +- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 10 ++-------- src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 4 ++-- src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 2 +- src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | 2 +- src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | 2 +- src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | 2 +- src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp | 2 +- src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h | 2 +- src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | 2 +- src/core/hle/service/nvdrv/devices/nvhost_vic.h | 2 +- src/core/hle/service/nvdrv/devices/nvmap.cpp | 2 +- src/core/hle/service/nvdrv/devices/nvmap.h | 2 +- src/core/hle/service/nvdrv/nvdrv.cpp | 4 ++-- src/core/hle/service/nvdrv/nvdrv.h | 16 +++++++++------- src/core/hle/service/nvflinger/buffer_queue.cpp | 2 +- src/core/hle/service/nvflinger/nvflinger.cpp | 7 +++---- src/core/hle/service/nvflinger/nvflinger.h | 2 +- 18 files changed, 31 insertions(+), 36 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index fae69eb19..5b8248433 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h @@ -20,7 +20,7 @@ namespace Service::Nvidia::Devices { /// implement the ioctl interface. class nvdevice { public: - nvdevice(Core::System& system) : system{system} {}; + explicit nvdevice(Core::System& system) : system{system} {}; virtual ~nvdevice() = default; union Ioctl { u32_le raw; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index a5a4f8c7b..749aa71d4 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -15,7 +15,7 @@ namespace Service::Nvidia::Devices { -nvhost_ctrl::nvhost_ctrl(Core::System& system, EventsInterface& events_interface) +nvhost_ctrl::nvhost_ctrl(Core::System& system, EventInterface& events_interface) : nvdevice(system), events_interface{events_interface} {} nvhost_ctrl::~nvhost_ctrl() = default; @@ -67,12 +67,11 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& if (!gpu.IsAsync()) { return NvResult::Success; } - gpu.Guard(true); + auto lock = gpu.LockSync(); u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); if (current_syncpoint_value >= params.threshold) { params.value = current_syncpoint_value; std::memcpy(output.data(), ¶ms, sizeof(params)); - gpu.Guard(false); return NvResult::Success; } @@ -82,7 +81,6 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& if (params.timeout == 0) { std::memcpy(output.data(), ¶ms, sizeof(params)); - gpu.Guard(false); return NvResult::Timeout; } @@ -91,7 +89,6 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& event_id = params.value & 0x00FF; if (event_id >= 64) { std::memcpy(output.data(), ¶ms, sizeof(params)); - gpu.Guard(false); return NvResult::BadParameter; } } else { @@ -119,15 +116,12 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& ctrl.must_delay = true; ctrl.timeout = params.timeout; ctrl.event_id = event_id; - gpu.Guard(false); return NvResult::Timeout; } std::memcpy(output.data(), ¶ms, sizeof(params)); - gpu.Guard(false); return NvResult::Timeout; } std::memcpy(output.data(), ¶ms, sizeof(params)); - gpu.Guard(false); return NvResult::BadParameter; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 7cb41aa54..14e6e7e57 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -14,7 +14,7 @@ namespace Service::Nvidia::Devices { class nvhost_ctrl final : public nvdevice { public: - nvhost_ctrl(Core::System& system, EventsInterface& events_interface); + explicit nvhost_ctrl(Core::System& system, EventInterface& events_interface); ~nvhost_ctrl() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, @@ -143,7 +143,7 @@ private: u32 IocCtrlEventSignal(const std::vector& input, std::vector& output); - EventsInterface& events_interface; + EventInterface& events_interface; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index e3d2b4470..988effd90 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -12,7 +12,7 @@ namespace Service::Nvidia::Devices { -nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system){}; +nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system) {} nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default; u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& output, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index de36cb014..2b035ae3f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { class nvhost_ctrl_gpu final : public nvdevice { public: - nvhost_ctrl_gpu(Core::System& system); + explicit nvhost_ctrl_gpu(Core::System& system); ~nvhost_ctrl_gpu() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index f464328f3..f572ad30f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -10,7 +10,7 @@ namespace Service::Nvidia::Devices { -nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system){}; +nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system) {} nvhost_nvdec::~nvhost_nvdec() = default; u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector& input, std::vector& output, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index c2b7a22f6..2710f0511 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { class nvhost_nvdec final : public nvdevice { public: - nvhost_nvdec(Core::System& system); + explicit nvhost_nvdec(Core::System& system); ~nvhost_nvdec() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index d4d67fc72..38282956f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp @@ -10,7 +10,7 @@ namespace Service::Nvidia::Devices { -nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system){}; +nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system) {} nvhost_nvjpg::~nvhost_nvjpg() = default; u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector& input, std::vector& output, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 4bf280d67..379766693 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { class nvhost_nvjpg final : public nvdevice { public: - nvhost_nvjpg(Core::System& system); + explicit nvhost_nvjpg(Core::System& system); ~nvhost_nvjpg() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 24e38d31a..70e8091db 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -10,7 +10,7 @@ namespace Service::Nvidia::Devices { -nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system){}; +nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system) {} nvhost_vic::~nvhost_vic() = default; u32 nvhost_vic::ioctl(Ioctl command, const std::vector& input, std::vector& output, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index 3d0934a78..7d111977e 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { class nvhost_vic final : public nvdevice { public: - nvhost_vic(Core::System& system); + explicit nvhost_vic(Core::System& system); ~nvhost_vic() override; u32 ioctl(Ioctl command, const std::vector& input, std::vector& output, diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 349454685..223b496b7 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -18,7 +18,7 @@ enum { }; } -nvmap::nvmap(Core::System& system) : nvdevice(system){}; +nvmap::nvmap(Core::System& system) : nvdevice(system) {} nvmap::~nvmap() = default; VAddr nvmap::GetObjectAddress(u32 handle) const { diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index b79ed736c..bf4a101c2 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h @@ -16,7 +16,7 @@ namespace Service::Nvidia::Devices { class nvmap final : public nvdevice { public: - nvmap(Core::System& system); + explicit nvmap(Core::System& system); ~nvmap() override; /// Returns the allocated address of an nvmap object given its handle. diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 8958e21e3..2011a226a 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -100,11 +100,11 @@ void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) { } } -Kernel::SharedPtr Module::GetEvent(const u32 event_id) { +Kernel::SharedPtr Module::GetEvent(const u32 event_id) const { return events_interface.events[event_id].readable; } -Kernel::SharedPtr Module::GetEventWriteable(const u32 event_id) { +Kernel::SharedPtr Module::GetEventWriteable(const u32 event_id) const { return events_interface.events[event_id].writable; } diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index b7f692962..8f7c59a21 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -26,14 +26,15 @@ namespace Devices { class nvdevice; } -struct EventsInterface { +struct EventInterface { u64 events_mask{}; std::array events; std::array status{}; std::array registered{}; std::array assigned_syncpt{}; std::array assigned_value{}; - u32 GetFreeEvent() { + static constexpr u32 null_event = 0xFFFFFFFF; + u32 GetFreeEvent() const { u64 mask = events_mask; for (u32 i = 0; i < MaxNvEvents; i++) { const bool is_free = (mask & 0x1) == 0; @@ -44,12 +45,13 @@ struct EventsInterface { } mask = mask >> 1; } - return 0xFFFFFFFF; + return null_event; } void SetEventStatus(const u32 event_id, EventState new_status) { EventState old_status = status[event_id]; - if (old_status == new_status) + if (old_status == new_status) { return; + } status[event_id] = new_status; if (new_status == EventState::Registered) { registered[event_id] = true; @@ -102,9 +104,9 @@ public: void SignalSyncpt(const u32 syncpoint_id, const u32 value); - Kernel::SharedPtr GetEvent(const u32 event_id); + Kernel::SharedPtr GetEvent(u32 event_id) const; - Kernel::SharedPtr GetEventWriteable(const u32 event_id); + Kernel::SharedPtr GetEventWriteable(u32 event_id) const; private: /// Id to use for the next open file descriptor. @@ -116,7 +118,7 @@ private: /// Mapping of device node names to their implementation. std::unordered_map> devices; - EventsInterface events_interface; + EventInterface events_interface; }; /// Registers all NVDRV services with the specified service manager. diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index d8aa3f1c0..ddc224f2c 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -79,7 +79,7 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, } std::optional> BufferQueue::AcquireBuffer() { - std::vector::iterator itr = queue.end(); + auto itr = queue.end(); 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/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 70441f6a2..f9db79370 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -37,8 +37,6 @@ NVFlinger::NVFlinger(Core::Timing::CoreTiming& core_timing) : core_timing{core_t displays.emplace_back(4, "Null"); // Schedule the screen composition events - // const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : frame_ticks; - composition_event = core_timing.RegisterEvent("ScreenComposition", [this](u64 userdata, s64 cycles_late) { Compose(); @@ -212,8 +210,9 @@ void NVFlinger::Compose() { } } -s64 NVFlinger::GetNextTicks() { - return (Core::Timing::BASE_CLOCK_RATE * (1LL << swap_interval)) / 120; +s64 NVFlinger::GetNextTicks() const { + constexpr s64 max_hertz = 120LL; + return (Core::Timing::BASE_CLOCK_RATE * (1LL << swap_interval)) / max_hertz; } } // namespace Service::NVFlinger diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 86b94302c..988be8726 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -74,7 +74,7 @@ public: /// finished. void Compose(); - s64 GetNextTicks(); + s64 GetNextTicks() const; private: /// Finds the display identified by the specified ID. -- cgit v1.2.3 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(-) (limited to 'src/core/hle/service') 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 From 8c91d5c16614ac42efee7c1858cb338d65861154 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 4 Jul 2019 09:55:50 -0400 Subject: Nv_Host_Ctrl: Correct difference calculation --- src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 1f178d17d..9a66a5f88 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -68,12 +68,14 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& return NvResult::Success; } auto lock = gpu.LockSync(); - u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); - if (current_syncpoint_value >= params.threshold) { + const u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); + const s32 diff = current_syncpoint_value - params.threshold; + if (diff >= 0) { params.value = current_syncpoint_value; std::memcpy(output.data(), ¶ms, sizeof(params)); return NvResult::Success; } + const u32 target_value = current_syncpoint_value - diff; if (!is_async) { params.value = 0; @@ -109,7 +111,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& 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; + events_interface.assigned_value[event_id] = target_value; if (is_async) { params.value = params.syncpt_id << 4; } else { @@ -117,7 +119,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& } params.value |= event_id; events_interface.events[event_id].writable->Clear(); - gpu.RegisterSyncptInterrupt(params.syncpt_id, params.threshold); + gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); if (!is_async && ctrl.fresh_call) { ctrl.must_delay = true; ctrl.timeout = params.timeout; @@ -167,7 +169,7 @@ u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector& input, std::vector= MaxNvEvents) { return NvResult::BadParameter; } -- cgit v1.2.3 From 0fc98958a3efdc30e2d6ece5a2654df0987ce7ac Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 4 Jul 2019 10:19:25 -0400 Subject: NVServices: Correct delayed responses. --- src/core/hle/service/nvdrv/interface.cpp | 43 ++++++++++++++------------------ 1 file changed, 19 insertions(+), 24 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index b8877b6cb..d5be64ed2 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -46,32 +46,27 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output, ctrl); - if (!ctrl.must_delay) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(result); - + if (ctrl.must_delay) { + ctrl.fresh_call = false; + ctx.SleepClientThread( + "NVServices::DelayedResponse", ctrl.timeout, + [=](Kernel::SharedPtr thread, Kernel::HLERequestContext& ctx, + Kernel::ThreadWakeupReason reason) { + IoctlCtrl ctrl2{ctrl}; + std::vector output2 = output; + u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output2, ctrl2); + ctx.WriteBuffer(output2); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(result); + }, + nvdrv->GetEventWriteable(ctrl.event_id)); + } else { ctx.WriteBuffer(output); - return; } - ctrl.fresh_call = false; - ctx.SleepClientThread( - "NVServices::DelayedResponse", ctrl.timeout, - [this, ctrl = ctrl](Kernel::SharedPtr thread, - Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { - IPC::RequestParser rp{ctx}; - u32 fd = rp.Pop(); - u32 command = rp.Pop(); - std::vector output(ctx.GetWriteBufferSize()); - IoctlCtrl ctrl2{ctrl}; - u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output, ctrl2); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(result); - - ctx.WriteBuffer(output); - }, - nvdrv->GetEventWriteable(ctrl.event_id)); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(result); } void NVDRV::Close(Kernel::HLERequestContext& ctx) { -- cgit v1.2.3