GPU/SW: Spin for 1ms rather than immediately sleeping

This commit is contained in:
Connor McLaughlin 2021-04-17 22:16:59 +10:00
parent 90e0ff33db
commit e4d5d9f049
4 changed files with 19 additions and 6 deletions

View file

@ -2,6 +2,7 @@
#include "common/align.h" #include "common/align.h"
#include "common/log.h" #include "common/log.h"
#include "common/state_wrapper.h" #include "common/state_wrapper.h"
#include "common/timer.h"
#include "settings.h" #include "settings.h"
Log_SetChannel(GPUBackend); Log_SetChannel(GPUBackend);
@ -21,13 +22,13 @@ bool GPUBackend::Initialize()
void GPUBackend::Reset(bool clear_vram) void GPUBackend::Reset(bool clear_vram)
{ {
Sync(); Sync(true);
m_drawing_area = {}; m_drawing_area = {};
} }
void GPUBackend::UpdateSettings() void GPUBackend::UpdateSettings()
{ {
Sync(); Sync(true);
if (m_use_gpu_thread != g_settings.gpu_use_thread) if (m_use_gpu_thread != g_settings.gpu_use_thread)
{ {
@ -188,13 +189,14 @@ void GPUBackend::StopGPUThread()
Log_InfoPrint("GPU thread stopped."); Log_InfoPrint("GPU thread stopped.");
} }
void GPUBackend::Sync() void GPUBackend::Sync(bool allow_sleep)
{ {
if (!m_use_gpu_thread) if (!m_use_gpu_thread)
return; return;
GPUBackendSyncCommand* cmd = GPUBackendSyncCommand* cmd =
static_cast<GPUBackendSyncCommand*>(AllocateCommand(GPUBackendCommandType::Sync, sizeof(GPUBackendSyncCommand))); static_cast<GPUBackendSyncCommand*>(AllocateCommand(GPUBackendCommandType::Sync, sizeof(GPUBackendSyncCommand)));
cmd->allow_sleep = allow_sleep;
PushCommand(cmd); PushCommand(cmd);
WakeGPUThread(); WakeGPUThread();
@ -204,12 +206,19 @@ void GPUBackend::Sync()
void GPUBackend::RunGPULoop() void GPUBackend::RunGPULoop()
{ {
static constexpr double SPIN_TIME_NS = 1 * 1000000;
Common::Timer::Value last_command_time = 0;
for (;;) for (;;)
{ {
u32 write_ptr = m_command_fifo_write_ptr.load(); u32 write_ptr = m_command_fifo_write_ptr.load();
u32 read_ptr = m_command_fifo_read_ptr.load(); u32 read_ptr = m_command_fifo_read_ptr.load();
if (read_ptr == write_ptr) 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<std::mutex> lock(m_sync_mutex); std::unique_lock<std::mutex> lock(m_sync_mutex);
m_gpu_thread_sleeping.store(true); m_gpu_thread_sleeping.store(true);
m_wake_gpu_thread_cv.wait(lock, [this]() { return m_gpu_loop_done.load() || GetPendingCommandSize() > 0; }); 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) if (write_ptr < read_ptr)
write_ptr = COMMAND_QUEUE_SIZE; write_ptr = COMMAND_QUEUE_SIZE;
bool allow_sleep = false;
while (read_ptr < write_ptr) while (read_ptr < write_ptr)
{ {
const GPUBackendCommand* cmd = reinterpret_cast<const GPUBackendCommand*>(&m_command_fifo_data[read_ptr]); const GPUBackendCommand* cmd = reinterpret_cast<const GPUBackendCommand*>(&m_command_fifo_data[read_ptr]);
@ -243,6 +253,7 @@ void GPUBackend::RunGPULoop()
{ {
DebugAssert(read_ptr == write_ptr); DebugAssert(read_ptr == write_ptr);
m_sync_event.Signal(); m_sync_event.Signal();
allow_sleep = static_cast<const GPUBackendSyncCommand*>(cmd)->allow_sleep;
} }
break; 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); m_command_fifo_read_ptr.store(read_ptr);
} }
} }

View file

@ -35,7 +35,7 @@ public:
GPUBackendDrawLineCommand* NewDrawLineCommand(u32 num_vertices); GPUBackendDrawLineCommand* NewDrawLineCommand(u32 num_vertices);
void PushCommand(GPUBackendCommand* cmd); void PushCommand(GPUBackendCommand* cmd);
void Sync(); void Sync(bool allow_sleep);
/// Processes all pending GPU commands. /// Processes all pending GPU commands.
void RunGPULoop(); void RunGPULoop();

View file

@ -482,7 +482,7 @@ void GPU_SW::ClearDisplay()
void GPU_SW::UpdateDisplay() void GPU_SW::UpdateDisplay()
{ {
// fill display texture // fill display texture
m_backend.Sync(); m_backend.Sync(true);
if (!g_settings.debugging.show_vram) 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) 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) void GPU_SW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)

View file

@ -277,6 +277,7 @@ struct GPUBackendCommand
struct GPUBackendSyncCommand : public GPUBackendCommand struct GPUBackendSyncCommand : public GPUBackendCommand
{ {
bool allow_sleep;
}; };
struct GPUBackendFillVRAMCommand : public GPUBackendCommand struct GPUBackendFillVRAMCommand : public GPUBackendCommand