From e4d5d9f0497750e8708186ec9bb9fd95ba9473bc Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 17 Apr 2021 22:16:59 +1000 Subject: [PATCH] GPU/SW: Spin for 1ms rather than immediately sleeping --- src/core/gpu_backend.cpp | 18 +++++++++++++++--- src/core/gpu_backend.h | 2 +- src/core/gpu_sw.cpp | 4 ++-- src/core/gpu_types.h | 1 + 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/core/gpu_backend.cpp b/src/core/gpu_backend.cpp index 6d628715c..8d85dafe7 100644 --- a/src/core/gpu_backend.cpp +++ b/src/core/gpu_backend.cpp @@ -2,6 +2,7 @@ #include "common/align.h" #include "common/log.h" #include "common/state_wrapper.h" +#include "common/timer.h" #include "settings.h" Log_SetChannel(GPUBackend); @@ -21,13 +22,13 @@ bool GPUBackend::Initialize() void GPUBackend::Reset(bool clear_vram) { - Sync(); + Sync(true); m_drawing_area = {}; } void GPUBackend::UpdateSettings() { - Sync(); + Sync(true); if (m_use_gpu_thread != g_settings.gpu_use_thread) { @@ -188,13 +189,14 @@ void GPUBackend::StopGPUThread() Log_InfoPrint("GPU thread stopped."); } -void GPUBackend::Sync() +void GPUBackend::Sync(bool allow_sleep) { if (!m_use_gpu_thread) return; GPUBackendSyncCommand* cmd = static_cast(AllocateCommand(GPUBackendCommandType::Sync, sizeof(GPUBackendSyncCommand))); + cmd->allow_sleep = allow_sleep; PushCommand(cmd); WakeGPUThread(); @@ -204,12 +206,19 @@ void GPUBackend::Sync() void GPUBackend::RunGPULoop() { + static constexpr double SPIN_TIME_NS = 1 * 1000000; + Common::Timer::Value last_command_time = 0; + for (;;) { u32 write_ptr = m_command_fifo_write_ptr.load(); u32 read_ptr = m_command_fifo_read_ptr.load(); if (read_ptr == write_ptr) { + const Common::Timer::Value current_time = Common::Timer::GetValue(); + if (Common::Timer::ConvertValueToNanoseconds(current_time - last_command_time) < SPIN_TIME_NS) + continue; + std::unique_lock lock(m_sync_mutex); m_gpu_thread_sleeping.store(true); m_wake_gpu_thread_cv.wait(lock, [this]() { return m_gpu_loop_done.load() || GetPendingCommandSize() > 0; }); @@ -224,6 +233,7 @@ void GPUBackend::RunGPULoop() if (write_ptr < read_ptr) write_ptr = COMMAND_QUEUE_SIZE; + bool allow_sleep = false; while (read_ptr < write_ptr) { const GPUBackendCommand* cmd = reinterpret_cast(&m_command_fifo_data[read_ptr]); @@ -243,6 +253,7 @@ void GPUBackend::RunGPULoop() { DebugAssert(read_ptr == write_ptr); m_sync_event.Signal(); + allow_sleep = static_cast(cmd)->allow_sleep; } break; @@ -252,6 +263,7 @@ void GPUBackend::RunGPULoop() } } + last_command_time = allow_sleep ? 0 : Common::Timer::GetValue(); m_command_fifo_read_ptr.store(read_ptr); } } diff --git a/src/core/gpu_backend.h b/src/core/gpu_backend.h index 3302f76a4..dfa924768 100644 --- a/src/core/gpu_backend.h +++ b/src/core/gpu_backend.h @@ -35,7 +35,7 @@ public: GPUBackendDrawLineCommand* NewDrawLineCommand(u32 num_vertices); void PushCommand(GPUBackendCommand* cmd); - void Sync(); + void Sync(bool allow_sleep); /// Processes all pending GPU commands. void RunGPULoop(); diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index d3cead497..48dbf3e6b 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -482,7 +482,7 @@ void GPU_SW::ClearDisplay() void GPU_SW::UpdateDisplay() { // fill display texture - m_backend.Sync(); + m_backend.Sync(true); if (!g_settings.debugging.show_vram) { @@ -824,7 +824,7 @@ void GPU_SW::DispatchRenderCommand() void GPU_SW::ReadVRAM(u32 x, u32 y, u32 width, u32 height) { - m_backend.Sync(); + m_backend.Sync(false); } void GPU_SW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) diff --git a/src/core/gpu_types.h b/src/core/gpu_types.h index e3e66c420..c0da5c63a 100644 --- a/src/core/gpu_types.h +++ b/src/core/gpu_types.h @@ -277,6 +277,7 @@ struct GPUBackendCommand struct GPUBackendSyncCommand : public GPUBackendCommand { + bool allow_sleep; }; struct GPUBackendFillVRAMCommand : public GPUBackendCommand