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/video_core/engines/maxwell_3d.cpp | 5 +++-- src/video_core/gpu.cpp | 24 ++++++++++++++++++++++++ src/video_core/gpu.h | 24 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) (limited to 'src/video_core') diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 8755b8af4..224c27bd2 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -346,8 +346,9 @@ void Maxwell3D::ProcessSyncPoint() { const u32 sync_point = regs.sync_info.sync_point.Value(); const u32 increment = regs.sync_info.increment.Value(); const u32 cache_flush = regs.sync_info.unknown.Value(); - LOG_DEBUG(HW_GPU, "Syncpoint set {}, increment: {}, unk: {}", sync_point, increment, - cache_flush); + if (increment) { + system.GPU().IncrementSyncPoint(sync_point); + } } void Maxwell3D::DrawArrays() { diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 52706505b..1d12f0493 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -66,6 +66,30 @@ const DmaPusher& GPU::DmaPusher() const { return *dma_pusher; } +void GPU::IncrementSyncPoint(const u32 syncpoint_id) { + syncpoints[syncpoint_id]++; + if (!events[syncpoint_id].empty()) { + u32 value = syncpoints[syncpoint_id].load(); + auto it = events[syncpoint_id].begin(); + while (it != events[syncpoint_id].end()) { + if (value >= it->value) { + TriggerCpuInterrupt(it->event_id); + it = events[syncpoint_id].erase(it); + continue; + } + it++; + } + } +} + +u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { + return syncpoints[syncpoint_id].load(); +} + +void GPU::RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 value) { + events[syncpoint_id].emplace_back(event_id, value); +} + u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { ASSERT(format != RenderTargetFormat::NONE); diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index fe6628923..4c97d6c6f 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -5,8 +5,11 @@ #pragma once #include +#include +#include #include #include "common/common_types.h" +#include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/nvflinger/buffer_queue.h" #include "video_core/dma_pusher.h" @@ -164,6 +167,12 @@ public: /// Returns a reference to the GPU DMA pusher. Tegra::DmaPusher& DmaPusher(); + void IncrementSyncPoint(const u32 syncpoint_id); + + u32 GetSyncpointValue(const u32 syncpoint_id) const; + + void RegisterEvent(const u32 event_id, const u32 sync_point_id, const u32 value); + /// Returns a const reference to the GPU DMA pusher. const Tegra::DmaPusher& DmaPusher() const; @@ -228,6 +237,11 @@ public: /// Notify rasterizer that any caches of the specified region should be flushed and invalidated virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0; +protected: + virtual void TriggerCpuInterrupt(const u32 event_id) const { + // Todo implement this + } + private: void ProcessBindMethod(const MethodCall& method_call); void ProcessSemaphoreTriggerMethod(); @@ -262,6 +276,16 @@ private: std::unique_ptr maxwell_dma; /// Inline memory engine std::unique_ptr kepler_memory; + + std::array, Service::Nvidia::MaxSyncPoints> syncpoints{}; + + struct Event { + Event(const u32 event_id, const u32 value) : event_id(event_id), value(value) {} + u32 event_id; + u32 value; + }; + + std::array, Service::Nvidia::MaxSyncPoints> events; }; #define ASSERT_REG_POSITION(field_name, position) \ -- 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/CMakeLists.txt | 2 ++ src/core/core.cpp | 12 +++++++++++- src/core/core.h | 10 ++++++++++ src/core/hardware_interrupt_manager.cpp | 21 +++++++++++++++++++++ src/core/hardware_interrupt_manager.h | 24 ++++++++++++++++++++++++ src/core/hle/service/nvdrv/interface.cpp | 2 -- src/core/hle/service/nvdrv/interface.h | 2 -- src/core/hle/service/nvdrv/nvdrv.h | 5 +---- src/video_core/gpu.cpp | 7 ++++++- src/video_core/gpu.h | 5 ++--- src/video_core/gpu_asynch.cpp | 7 +++++++ src/video_core/gpu_asynch.h | 3 +++ src/video_core/gpu_synch.h | 3 +++ 13 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 src/core/hardware_interrupt_manager.cpp create mode 100644 src/core/hardware_interrupt_manager.h (limited to 'src/video_core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c22585bfb..12f06a189 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -111,6 +111,8 @@ add_library(core STATIC frontend/scope_acquire_window_context.h gdbstub/gdbstub.cpp gdbstub/gdbstub.h + hardware_interrupt_manager.cpp + hardware_interrupt_manager.h hle/ipc.h hle/ipc_helpers.h hle/kernel/address_arbiter.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index 262411db8..d7f43f5ec 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -19,6 +19,7 @@ #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_real.h" #include "core/gdbstub/gdbstub.h" +#include "core/hardware_interrupt_manager.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" @@ -150,7 +151,7 @@ struct System::Impl { if (!renderer->Init()) { return ResultStatus::ErrorVideoCore; } - + interrupt_manager = std::make_unique(system); gpu_core = VideoCore::CreateGPU(system); is_powered_on = true; @@ -297,6 +298,7 @@ struct System::Impl { std::unique_ptr renderer; std::unique_ptr gpu_core; std::shared_ptr debug_context; + std::unique_ptr interrupt_manager; CpuCoreManager cpu_core_manager; bool is_powered_on = false; @@ -440,6 +442,14 @@ const Tegra::GPU& System::GPU() const { return *impl->gpu_core; } +Core::Hardware::InterruptManager& System::InterruptManager() { + return *impl->interrupt_manager; +} + +const Core::Hardware::InterruptManager& System::InterruptManager() const { + return *impl->interrupt_manager; +} + VideoCore::RendererBase& System::Renderer() { return *impl->renderer; } diff --git a/src/core/core.h b/src/core/core.h index 70adb7af9..53e6fdb7b 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -66,6 +66,10 @@ namespace Core::Timing { class CoreTiming; } +namespace Core::Hardware { +class InterruptManager; +} + namespace Core { class ARM_Interface; @@ -230,6 +234,12 @@ public: /// Provides a constant reference to the core timing instance. const Timing::CoreTiming& CoreTiming() const; + /// Provides a reference to the interrupt manager instance. + Core::Hardware::InterruptManager& InterruptManager(); + + /// Provides a constant reference to the interrupt manager instance. + const Core::Hardware::InterruptManager& InterruptManager() const; + /// Provides a reference to the kernel instance. Kernel::KernelCore& Kernel(); diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp new file mode 100644 index 000000000..463d2916c --- /dev/null +++ b/src/core/hardware_interrupt_manager.cpp @@ -0,0 +1,21 @@ + +#include "core/core.h" +#include "core/hardware_interrupt_manager.h" +#include "core/hle/service/nvdrv/interface.h" +#include "core/hle/service/sm/sm.h" + +namespace Core::Hardware { + +InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { + gpu_interrupt_event = + system.CoreTiming().RegisterEvent("GPUInterrupt", [this](u64 event_index, s64) { + auto nvdrv = system.ServiceManager().GetService("nvdrv"); + nvdrv->SignalGPUInterrupt(static_cast(event_index)); + }); +} + +void InterruptManager::InterruptGPU(const u32 event_index) { + system.CoreTiming().ScheduleEvent(10, gpu_interrupt_event, static_cast(event_index)); +} + +} // namespace Core::Hardware diff --git a/src/core/hardware_interrupt_manager.h b/src/core/hardware_interrupt_manager.h new file mode 100644 index 000000000..fc565c88b --- /dev/null +++ b/src/core/hardware_interrupt_manager.h @@ -0,0 +1,24 @@ +#pragma once + +#include "common/common_types.h" +#include "core/core_timing.h" + +namespace Core { +class System; +} + +namespace Core::Hardware { + +class InterruptManager { +public: + InterruptManager(Core::System& system); + ~InterruptManager() = default; + + void InterruptGPU(const u32 event_index); + +private: + Core::System& system; + Core::Timing::EventType* gpu_interrupt_event{}; +}; + +} // namespace Core::Hardware 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 { diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 1d12f0493..06eb570ab 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -29,7 +29,8 @@ u32 FramebufferConfig::BytesPerPixel(PixelFormat format) { UNREACHABLE(); } -GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer) : renderer{renderer} { +GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer) + : system{system}, renderer{renderer} { auto& rasterizer{renderer.Rasterizer()}; memory_manager = std::make_unique(rasterizer); dma_pusher = std::make_unique(*this); @@ -87,6 +88,10 @@ u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { } void GPU::RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 value) { + for (auto& ev : events[syncpoint_id]) { + if (ev.event_id == event_id && ev.value == value) + return; + } events[syncpoint_id].emplace_back(event_id, value); } diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 4c97d6c6f..c3e5311fa 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -238,9 +238,7 @@ public: virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0; protected: - virtual void TriggerCpuInterrupt(const u32 event_id) const { - // Todo implement this - } + virtual void TriggerCpuInterrupt(const u32 event_id) const = 0; private: void ProcessBindMethod(const MethodCall& method_call); @@ -260,6 +258,7 @@ private: protected: std::unique_ptr dma_pusher; VideoCore::RendererBase& renderer; + Core::System& system; private: std::unique_ptr memory_manager; diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp index d4e2553a9..7060f9a89 100644 --- a/src/video_core/gpu_asynch.cpp +++ b/src/video_core/gpu_asynch.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "core/core.h" +#include "core/hardware_interrupt_manager.h" #include "video_core/gpu_asynch.h" #include "video_core/gpu_thread.h" #include "video_core/renderer_base.h" @@ -38,4 +40,9 @@ void GPUAsynch::FlushAndInvalidateRegion(CacheAddr addr, u64 size) { gpu_thread.FlushAndInvalidateRegion(addr, size); } +void GPUAsynch::TriggerCpuInterrupt(const u32 event_id) const { + auto& interrupt_manager = system.InterruptManager(); + interrupt_manager.InterruptGPU(event_id); +} + } // namespace VideoCommon diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h index 30be74cba..d49e9b96e 100644 --- a/src/video_core/gpu_asynch.h +++ b/src/video_core/gpu_asynch.h @@ -27,6 +27,9 @@ public: void InvalidateRegion(CacheAddr addr, u64 size) override; void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override; +protected: + void TriggerCpuInterrupt(const u32 event_id) const override; + private: GPUThread::ThreadManager gpu_thread; }; diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h index 3031fcf72..09bda854a 100644 --- a/src/video_core/gpu_synch.h +++ b/src/video_core/gpu_synch.h @@ -25,6 +25,9 @@ public: void FlushRegion(CacheAddr addr, u64 size) override; void InvalidateRegion(CacheAddr addr, u64 size) override; void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override; + +protected: + void TriggerCpuInterrupt(const u32 event_id) const override {} }; } // namespace VideoCommon -- 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 + src/video_core/gpu.cpp | 11 ++++++ src/video_core/gpu.h | 4 +- 4 files changed, 48 insertions(+), 13 deletions(-) (limited to 'src/video_core') 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; }; diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 06eb570ab..1fa6770ca 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -95,6 +95,17 @@ void GPU::RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 va events[syncpoint_id].emplace_back(event_id, value); } +void GPU::CancelEvent(const u32 event_id, const u32 syncpoint_id, const u32 value) { + auto it = events[syncpoint_id].begin(); + while (it != events[syncpoint_id].end()) { + if (value == it->value) { + it = events[syncpoint_id].erase(it); + return; + } + it++; + } +} + u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { ASSERT(format != RenderTargetFormat::NONE); diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index c3e5311fa..4805a5fbc 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -171,7 +171,9 @@ public: u32 GetSyncpointValue(const u32 syncpoint_id) const; - void RegisterEvent(const u32 event_id, const u32 sync_point_id, const u32 value); + void RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 value); + + void CancelEvent(const u32 event_id, const u32 syncpoint_id, const u32 value); /// Returns a const reference to the GPU DMA pusher. const Tegra::DmaPusher& DmaPusher() const; -- 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 ++++++ src/video_core/gpu.cpp | 2 ++ src/video_core/gpu.h | 11 +++++++++++ 3 files changed, 19 insertions(+) (limited to 'src/video_core') 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; } diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 1fa6770ca..ee976f81f 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -69,6 +69,7 @@ const DmaPusher& GPU::DmaPusher() const { void GPU::IncrementSyncPoint(const u32 syncpoint_id) { syncpoints[syncpoint_id]++; + sync_guard.lock(); if (!events[syncpoint_id].empty()) { u32 value = syncpoints[syncpoint_id].load(); auto it = events[syncpoint_id].begin(); @@ -81,6 +82,7 @@ void GPU::IncrementSyncPoint(const u32 syncpoint_id) { it++; } } + sync_guard.unlock(); } u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 4805a5fbc..bc63920f2 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -12,6 +12,7 @@ #include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/nvflinger/buffer_queue.h" #include "video_core/dma_pusher.h" +#include "common/spin_lock.h" using CacheAddr = std::uintptr_t; inline CacheAddr ToCacheAddr(const void* host_ptr) { @@ -175,6 +176,14 @@ public: void CancelEvent(const u32 event_id, const u32 syncpoint_id, const u32 value); + void Guard(bool guard_set) { + if (guard_set) { + sync_guard.lock(); + } else { + sync_guard.unlock(); + } + } + /// Returns a const reference to the GPU DMA pusher. const Tegra::DmaPusher& DmaPusher() const; @@ -287,6 +296,8 @@ private: }; std::array, Service::Nvidia::MaxSyncPoints> events; + + Common::SpinLock sync_guard{}; }; #define ASSERT_REG_POSITION(field_name, position) \ -- cgit v1.2.3 From c13433aee4032ce654de1db31a93e4aed578596f Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 8 Jun 2019 16:45:25 -0400 Subject: Gpu: use an std mutex instead of a spin_lock to guard syncpoints --- src/video_core/gpu.cpp | 4 ++-- src/video_core/gpu.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/video_core') diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index ee976f81f..c71f0f9bf 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -69,7 +69,7 @@ const DmaPusher& GPU::DmaPusher() const { void GPU::IncrementSyncPoint(const u32 syncpoint_id) { syncpoints[syncpoint_id]++; - sync_guard.lock(); + sync_mutex.lock(); if (!events[syncpoint_id].empty()) { u32 value = syncpoints[syncpoint_id].load(); auto it = events[syncpoint_id].begin(); @@ -82,7 +82,7 @@ void GPU::IncrementSyncPoint(const u32 syncpoint_id) { it++; } } - sync_guard.unlock(); + sync_mutex.unlock(); } u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index bc63920f2..ab1a4bdd4 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -8,11 +8,11 @@ #include #include #include +#include #include "common/common_types.h" #include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/nvflinger/buffer_queue.h" #include "video_core/dma_pusher.h" -#include "common/spin_lock.h" using CacheAddr = std::uintptr_t; inline CacheAddr ToCacheAddr(const void* host_ptr) { @@ -178,9 +178,9 @@ public: void Guard(bool guard_set) { if (guard_set) { - sync_guard.lock(); + sync_mutex.lock(); } else { - sync_guard.unlock(); + sync_mutex.unlock(); } } @@ -297,7 +297,7 @@ private: std::array, Service::Nvidia::MaxSyncPoints> events; - Common::SpinLock sync_guard{}; + std::mutex sync_mutex; }; #define ASSERT_REG_POSITION(field_name, position) \ -- cgit v1.2.3 From 600dddf88db0a786b945c65d27da05105410bfe6 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 8 Jun 2019 17:04:41 -0400 Subject: Async GPU: do invalidate as synced operation Async GPU: Always invalidate synced. --- src/video_core/gpu_thread.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/video_core') diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 3f0939ec9..692655395 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -89,12 +89,7 @@ void ThreadManager::FlushRegion(CacheAddr addr, u64 size) { } void ThreadManager::InvalidateRegion(CacheAddr addr, u64 size) { - if (state.queue.Empty()) { - // It's quicker to invalidate a single region on the CPU if the queue is already empty - system.Renderer().Rasterizer().InvalidateRegion(addr, size); - } else { - PushCommand(InvalidateRegionCommand(addr, size)); - } + system.Renderer().Rasterizer().InvalidateRegion(addr, size); } void ThreadManager::FlushAndInvalidateRegion(CacheAddr addr, u64 size) { -- 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 +++++ src/video_core/gpu.cpp | 4 ++-- src/video_core/gpu.h | 8 +++++++- src/video_core/gpu_asynch.cpp | 2 +- src/video_core/gpu_synch.cpp | 2 +- 5 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src/video_core') 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) { diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index c71f0f9bf..086db0e69 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -29,8 +29,8 @@ u32 FramebufferConfig::BytesPerPixel(PixelFormat format) { UNREACHABLE(); } -GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer) - : system{system}, renderer{renderer} { +GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async) + : system{system}, renderer{renderer}, is_async{is_async} { auto& rasterizer{renderer.Rasterizer()}; memory_manager = std::make_unique(rasterizer); dma_pusher = std::make_unique(*this); diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index ab1a4bdd4..18ac3237e 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -131,7 +131,7 @@ class MemoryManager; class GPU { public: - explicit GPU(Core::System& system, VideoCore::RendererBase& renderer); + explicit GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async); virtual ~GPU(); @@ -184,6 +184,10 @@ public: } } + bool IsAsync() const { + return is_async; + } + /// Returns a const reference to the GPU DMA pusher. const Tegra::DmaPusher& DmaPusher() const; @@ -298,6 +302,8 @@ private: std::array, Service::Nvidia::MaxSyncPoints> events; std::mutex sync_mutex; + + const bool is_async; }; #define ASSERT_REG_POSITION(field_name, position) \ diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp index 7060f9a89..6b6f0f6ec 100644 --- a/src/video_core/gpu_asynch.cpp +++ b/src/video_core/gpu_asynch.cpp @@ -11,7 +11,7 @@ namespace VideoCommon { GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer) - : GPU(system, renderer), gpu_thread{system} {} + : GPU(system, renderer, true), gpu_thread{system} {} GPUAsynch::~GPUAsynch() = default; diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp index 45e43b1dc..d4ead9c47 100644 --- a/src/video_core/gpu_synch.cpp +++ b/src/video_core/gpu_synch.cpp @@ -8,7 +8,7 @@ namespace VideoCommon { GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer) - : GPU(system, renderer) {} + : GPU(system, renderer, false) {} GPUSynch::~GPUSynch() = default; -- cgit v1.2.3 From f2e026a1d8fb2384c1ece24e6dd32062b4f390a2 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 10 Jun 2019 08:36:22 -0400 Subject: gpu_asynch: Simplify synchronization to a simpler consumer->producer scheme. --- src/video_core/gpu_thread.cpp | 18 +++--------------- src/video_core/gpu_thread.h | 32 -------------------------------- 2 files changed, 3 insertions(+), 47 deletions(-) (limited to 'src/video_core') diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 692655395..b87938fdd 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -21,7 +21,7 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p MicroProfileOnThreadCreate("GpuThread"); // Wait for first GPU command before acquiring the window context - state.WaitForCommands(); + while (state.queue.Empty()); // If emulation was stopped during disk shader loading, abort before trying to acquire context if (!state.is_running) { @@ -32,7 +32,6 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p CommandDataContainer next; while (state.is_running) { - state.WaitForCommands(); while (!state.queue.Empty()) { state.queue.Pop(next); if (const auto submit_list = std::get_if(&next.data)) { @@ -49,8 +48,7 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p } else { UNREACHABLE(); } - state.signaled_fence = next.fence; - state.TrySynchronize(); + state.signaled_fence.store(next.fence); } } } @@ -100,22 +98,12 @@ void ThreadManager::FlushAndInvalidateRegion(CacheAddr addr, u64 size) { u64 ThreadManager::PushCommand(CommandData&& command_data) { const u64 fence{++state.last_fence}; state.queue.Push(CommandDataContainer(std::move(command_data), fence)); - state.SignalCommands(); return fence; } MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); void SynchState::WaitForSynchronization(u64 fence) { - if (signaled_fence >= fence) { - return; - } - - // Wait for the GPU to be idle (all commands to be executed) - { - MICROPROFILE_SCOPE(GPU_wait); - std::unique_lock lock{synchronization_mutex}; - synchronization_condition.wait(lock, [this, fence] { return signaled_fence >= fence; }); - } + while (signaled_fence.load() < fence); } } // namespace VideoCommon::GPUThread diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 05a168a72..1d9d0c39e 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -88,41 +88,9 @@ struct CommandDataContainer { /// Struct used to synchronize the GPU thread struct SynchState final { std::atomic_bool is_running{true}; - std::atomic_int queued_frame_count{}; - std::mutex synchronization_mutex; - std::mutex commands_mutex; - std::condition_variable commands_condition; - std::condition_variable synchronization_condition; - - /// Returns true if the gap in GPU commands is small enough that we can consider the CPU and GPU - /// synchronized. This is entirely empirical. - bool IsSynchronized() const { - constexpr std::size_t max_queue_gap{5}; - return queue.Size() <= max_queue_gap; - } - - void TrySynchronize() { - if (IsSynchronized()) { - std::lock_guard lock{synchronization_mutex}; - synchronization_condition.notify_one(); - } - } void WaitForSynchronization(u64 fence); - void SignalCommands() { - if (queue.Empty()) { - return; - } - - commands_condition.notify_one(); - } - - void WaitForCommands() { - std::unique_lock lock{commands_mutex}; - commands_condition.wait(lock, [this] { return !queue.Empty(); }); - } - using CommandQueue = Common::SPSCQueue; CommandQueue queue; u64 last_fence{}; -- 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/hardware_interrupt_manager.cpp | 11 +++++--- src/core/hardware_interrupt_manager.h | 2 +- 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 ++- src/video_core/gpu.cpp | 30 +++++++++++----------- src/video_core/gpu.h | 14 +++------- src/video_core/gpu_asynch.cpp | 4 +-- src/video_core/gpu_asynch.h | 2 +- src/video_core/gpu_synch.h | 2 +- 12 files changed, 45 insertions(+), 48 deletions(-) (limited to 'src/video_core') diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp index 463d2916c..c3fffa894 100644 --- a/src/core/hardware_interrupt_manager.cpp +++ b/src/core/hardware_interrupt_manager.cpp @@ -8,14 +8,17 @@ namespace Core::Hardware { InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { gpu_interrupt_event = - system.CoreTiming().RegisterEvent("GPUInterrupt", [this](u64 event_index, s64) { + system.CoreTiming().RegisterEvent("GPUInterrupt", [this](u64 message, s64) { auto nvdrv = system.ServiceManager().GetService("nvdrv"); - nvdrv->SignalGPUInterrupt(static_cast(event_index)); + const u32 syncpt = static_cast(message >> 32); + const u32 value = static_cast(message & 0x00000000FFFFFFFFULL); + nvdrv->SignalGPUInterruptSyncpt(syncpt, value); }); } -void InterruptManager::InterruptGPU(const u32 event_index) { - system.CoreTiming().ScheduleEvent(10, gpu_interrupt_event, static_cast(event_index)); +void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { + const u64 msg = (static_cast(syncpoint_id) << 32ULL) | value; + system.CoreTiming().ScheduleEvent(10, gpu_interrupt_event, msg); } } // namespace Core::Hardware diff --git a/src/core/hardware_interrupt_manager.h b/src/core/hardware_interrupt_manager.h index fc565c88b..590392f75 100644 --- a/src/core/hardware_interrupt_manager.h +++ b/src/core/hardware_interrupt_manager.h @@ -14,7 +14,7 @@ public: InterruptManager(Core::System& system); ~InterruptManager() = default; - void InterruptGPU(const u32 event_index); + void GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value); private: Core::System& system; 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); diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 086db0e69..efea23bf2 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -70,13 +70,13 @@ const DmaPusher& GPU::DmaPusher() const { void GPU::IncrementSyncPoint(const u32 syncpoint_id) { syncpoints[syncpoint_id]++; sync_mutex.lock(); - if (!events[syncpoint_id].empty()) { + if (!syncpt_interrupts[syncpoint_id].empty()) { u32 value = syncpoints[syncpoint_id].load(); - auto it = events[syncpoint_id].begin(); - while (it != events[syncpoint_id].end()) { - if (value >= it->value) { - TriggerCpuInterrupt(it->event_id); - it = events[syncpoint_id].erase(it); + auto it = syncpt_interrupts[syncpoint_id].begin(); + while (it != syncpt_interrupts[syncpoint_id].end()) { + if (value >= *it) { + TriggerCpuInterrupt(syncpoint_id, *it); + it = syncpt_interrupts[syncpoint_id].erase(it); continue; } it++; @@ -89,19 +89,19 @@ u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { return syncpoints[syncpoint_id].load(); } -void GPU::RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 value) { - for (auto& ev : events[syncpoint_id]) { - if (ev.event_id == event_id && ev.value == value) +void GPU::RegisterSyncptInterrupt(const u32 syncpoint_id, const u32 value) { + for (u32 in_value : syncpt_interrupts[syncpoint_id]) { + if (in_value == value) return; } - events[syncpoint_id].emplace_back(event_id, value); + syncpt_interrupts[syncpoint_id].emplace_back(value); } -void GPU::CancelEvent(const u32 event_id, const u32 syncpoint_id, const u32 value) { - auto it = events[syncpoint_id].begin(); - while (it != events[syncpoint_id].end()) { - if (value == it->value) { - it = events[syncpoint_id].erase(it); +void GPU::CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value) { + auto it = syncpt_interrupts[syncpoint_id].begin(); + while (it != syncpt_interrupts[syncpoint_id].end()) { + if (value == *it) { + it = syncpt_interrupts[syncpoint_id].erase(it); return; } it++; diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 18ac3237e..9bd618941 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -172,9 +172,9 @@ public: u32 GetSyncpointValue(const u32 syncpoint_id) const; - void RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 value); + void RegisterSyncptInterrupt(const u32 syncpoint_id, const u32 value); - void CancelEvent(const u32 event_id, const u32 syncpoint_id, const u32 value); + void CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value); void Guard(bool guard_set) { if (guard_set) { @@ -253,7 +253,7 @@ public: virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0; protected: - virtual void TriggerCpuInterrupt(const u32 event_id) const = 0; + virtual void TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const = 0; private: void ProcessBindMethod(const MethodCall& method_call); @@ -293,13 +293,7 @@ private: std::array, Service::Nvidia::MaxSyncPoints> syncpoints{}; - struct Event { - Event(const u32 event_id, const u32 value) : event_id(event_id), value(value) {} - u32 event_id; - u32 value; - }; - - std::array, Service::Nvidia::MaxSyncPoints> events; + std::array, Service::Nvidia::MaxSyncPoints> syncpt_interrupts; std::mutex sync_mutex; diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp index 6b6f0f6ec..ea67be831 100644 --- a/src/video_core/gpu_asynch.cpp +++ b/src/video_core/gpu_asynch.cpp @@ -40,9 +40,9 @@ void GPUAsynch::FlushAndInvalidateRegion(CacheAddr addr, u64 size) { gpu_thread.FlushAndInvalidateRegion(addr, size); } -void GPUAsynch::TriggerCpuInterrupt(const u32 event_id) const { +void GPUAsynch::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { auto& interrupt_manager = system.InterruptManager(); - interrupt_manager.InterruptGPU(event_id); + interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value); } } // namespace VideoCommon diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h index d49e9b96e..5f1b2fb7d 100644 --- a/src/video_core/gpu_asynch.h +++ b/src/video_core/gpu_asynch.h @@ -28,7 +28,7 @@ public: void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override; protected: - void TriggerCpuInterrupt(const u32 event_id) const override; + void TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const override; private: GPUThread::ThreadManager gpu_thread; diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h index 09bda854a..58d258503 100644 --- a/src/video_core/gpu_synch.h +++ b/src/video_core/gpu_synch.h @@ -27,7 +27,7 @@ public: void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override; protected: - void TriggerCpuInterrupt(const u32 event_id) const override {} + void TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const override {} }; } // namespace VideoCommon -- 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 ++-- src/video_core/gpu.cpp | 7 +++++-- src/video_core/gpu.h | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) (limited to 'src/video_core') 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 ++++++++-------- src/video_core/gpu.cpp | 6 ++---- src/video_core/gpu_thread.cpp | 6 ++++-- 8 files changed, 22 insertions(+), 23 deletions(-) (limited to 'src/video_core') 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); } diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index cdb2f804e..278528618 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -69,7 +69,7 @@ const DmaPusher& GPU::DmaPusher() const { void GPU::IncrementSyncPoint(const u32 syncpoint_id) { syncpoints[syncpoint_id]++; - sync_mutex.lock(); + std::lock_guard lock{sync_mutex}; if (!syncpt_interrupts[syncpoint_id].empty()) { u32 value = syncpoints[syncpoint_id].load(); auto it = syncpt_interrupts[syncpoint_id].begin(); @@ -82,7 +82,6 @@ void GPU::IncrementSyncPoint(const u32 syncpoint_id) { it++; } } - sync_mutex.unlock(); } u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { @@ -98,7 +97,7 @@ void GPU::RegisterSyncptInterrupt(const u32 syncpoint_id, const u32 value) { } bool GPU::CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value) { - sync_mutex.lock(); + std::lock_guard lock{sync_mutex}; auto it = syncpt_interrupts[syncpoint_id].begin(); while (it != syncpt_interrupts[syncpoint_id].end()) { if (value == *it) { @@ -108,7 +107,6 @@ bool GPU::CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value) { it++; } return false; - sync_mutex.unlock(); } u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index b87938fdd..b441e92b0 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -21,7 +21,8 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p MicroProfileOnThreadCreate("GpuThread"); // Wait for first GPU command before acquiring the window context - while (state.queue.Empty()); + while (state.queue.Empty()) + ; // If emulation was stopped during disk shader loading, abort before trying to acquire context if (!state.is_running) { @@ -103,7 +104,8 @@ u64 ThreadManager::PushCommand(CommandData&& command_data) { MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); void SynchState::WaitForSynchronization(u64 fence) { - while (signaled_fence.load() < fence); + while (signaled_fence.load() < fence) + ; } } // namespace VideoCommon::GPUThread -- 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/hardware_interrupt_manager.cpp | 8 ++++++- src/core/hardware_interrupt_manager.h | 15 +++++++++---- 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 ++-- .../hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 2 +- .../hle/service/nvdrv/devices/nvhost_ctrl_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/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 +- src/video_core/gpu.cpp | 25 ++++++++++++---------- src/video_core/gpu.h | 18 ++++++---------- src/video_core/gpu_asynch.h | 2 +- src/video_core/gpu_synch.h | 3 ++- 24 files changed, 73 insertions(+), 65 deletions(-) (limited to 'src/video_core') diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp index c3fffa894..c2115db2d 100644 --- a/src/core/hardware_interrupt_manager.cpp +++ b/src/core/hardware_interrupt_manager.cpp @@ -1,5 +1,9 @@ +// Copyright 2019 Yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. #include "core/core.h" +#include "core/core_timing.h" #include "core/hardware_interrupt_manager.h" #include "core/hle/service/nvdrv/interface.h" #include "core/hle/service/sm/sm.h" @@ -11,11 +15,13 @@ InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) system.CoreTiming().RegisterEvent("GPUInterrupt", [this](u64 message, s64) { auto nvdrv = system.ServiceManager().GetService("nvdrv"); const u32 syncpt = static_cast(message >> 32); - const u32 value = static_cast(message & 0x00000000FFFFFFFFULL); + const u32 value = static_cast(message); nvdrv->SignalGPUInterruptSyncpt(syncpt, value); }); } +InterruptManager::~InterruptManager() = default; + void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { const u64 msg = (static_cast(syncpoint_id) << 32ULL) | value; system.CoreTiming().ScheduleEvent(10, gpu_interrupt_event, msg); diff --git a/src/core/hardware_interrupt_manager.h b/src/core/hardware_interrupt_manager.h index 590392f75..494db883a 100644 --- a/src/core/hardware_interrupt_manager.h +++ b/src/core/hardware_interrupt_manager.h @@ -1,20 +1,27 @@ +// Copyright 2019 Yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + #pragma once #include "common/common_types.h" -#include "core/core_timing.h" namespace Core { class System; } +namespace Core::Timing { +struct EventType; +} + namespace Core::Hardware { class InterruptManager { public: - InterruptManager(Core::System& system); - ~InterruptManager() = default; + explicit InterruptManager(Core::System& system); + ~InterruptManager(); - void GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value); + void GPUInterruptSyncpt(u32 syncpoint_id, u32 value); private: Core::System& system; 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. diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 278528618..da8c715b6 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -89,24 +89,27 @@ u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { } void GPU::RegisterSyncptInterrupt(const u32 syncpoint_id, const u32 value) { - for (u32 in_value : syncpt_interrupts[syncpoint_id]) { - if (in_value == value) - return; + auto& interrupt = syncpt_interrupts[syncpoint_id]; + bool contains = std::any_of(interrupt.begin(), interrupt.end(), + [value](u32 in_value) { return in_value == value; }); + if (contains) { + return; } syncpt_interrupts[syncpoint_id].emplace_back(value); } bool GPU::CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value) { std::lock_guard lock{sync_mutex}; - auto it = syncpt_interrupts[syncpoint_id].begin(); - while (it != syncpt_interrupts[syncpoint_id].end()) { - if (value == *it) { - it = syncpt_interrupts[syncpoint_id].erase(it); - return true; - } - it++; + auto& interrupt = syncpt_interrupts[syncpoint_id]; + const auto iter = + std::find_if(interrupt.begin(), interrupt.end(), + [value](u32 interrupt_value) { return value == interrupt_value; }); + + if (iter == interrupt.end()) { + return false; } - return false; + interrupt.erase(iter); + return true; } u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 94afc91f8..334dec48c 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -168,20 +168,16 @@ public: /// Returns a reference to the GPU DMA pusher. Tegra::DmaPusher& DmaPusher(); - void IncrementSyncPoint(const u32 syncpoint_id); + void IncrementSyncPoint(u32 syncpoint_id); - u32 GetSyncpointValue(const u32 syncpoint_id) const; + u32 GetSyncpointValue(u32 syncpoint_id) const; - void RegisterSyncptInterrupt(const u32 syncpoint_id, const u32 value); + void RegisterSyncptInterrupt(u32 syncpoint_id, u32 value); - bool CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value); + bool CancelSyncptInterrupt(u32 syncpoint_id, u32 value); - void Guard(bool guard_set) { - if (guard_set) { - sync_mutex.lock(); - } else { - sync_mutex.unlock(); - } + std::unique_lock LockSync() { + return std::unique_lock{sync_mutex}; } bool IsAsync() const { @@ -253,7 +249,7 @@ public: virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0; protected: - virtual void TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const = 0; + virtual void TriggerCpuInterrupt(u32 syncpoint_id, u32 value) const = 0; private: void ProcessBindMethod(const MethodCall& method_call); diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h index 5f1b2fb7d..36377d677 100644 --- a/src/video_core/gpu_asynch.h +++ b/src/video_core/gpu_asynch.h @@ -28,7 +28,7 @@ public: void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override; protected: - void TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const override; + void TriggerCpuInterrupt(u32 syncpoint_id, u32 value) const override; private: GPUThread::ThreadManager gpu_thread; diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h index 58d258503..07bcc47f1 100644 --- a/src/video_core/gpu_synch.h +++ b/src/video_core/gpu_synch.h @@ -27,7 +27,8 @@ public: void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override; protected: - void TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const override {} + void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, + [[maybe_unused]] u32 value) const override {} }; } // namespace VideoCommon -- cgit v1.2.3