From b18365ed591066a2fb424244adc2d5d6b1547752 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/gpu_thread.cpp') diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 3f0939ec9e..6926553957 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 78c453696033061c4bd607df573831cbcacd7345 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/gpu_thread.cpp') diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 6926553957..b87938fdd5 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 05a168a726..1d9d0c39e3 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 a156731a9c3c173816835ef6ed4bfdc50b5b1835 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow 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/gpu_thread.cpp') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index ffa6e75c76..a5a4f8c7b8 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 b9e13fae94..241dac8817 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 edc37ff3a6..3ad8e1db10 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 45912153dc..6f7c7502a3 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 be993ee617..356bedb814 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 a7937b4904..70441f6a29 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 cdb2f804ef..278528618a 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 b87938fdd5..b441e92b0a 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