From 3476140ba2a1bd0e157eb73425caec6b325227c6 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 13 Jan 2025 16:08:20 +1000 Subject: [PATCH] GPUThread: Add BeginASyncBufferCall() --- src/common/types.h | 1 + src/core/gpu_thread.cpp | 30 ++++++++++++++++++++++++------ src/core/gpu_thread.h | 3 +++ src/core/gpu_thread_commands.h | 10 +--------- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/common/types.h b/src/common/types.h index 85b7d3024..b14915bb6 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -103,6 +103,7 @@ char (&__countof_ArraySizeHelper(T (&array)[N]))[N]; // disable warnings that show up at warning level 4 // TODO: Move to build system instead #ifdef _MSC_VER +#pragma warning(disable : 4200) // warning C4200: nonstandard extension used: zero-sized array in struct/union #pragma warning(disable : 4201) // warning C4201: nonstandard extension used : nameless struct/union #pragma warning(disable : 4100) // warning C4100: 'Platform' : unreferenced formal parameter #pragma warning(disable : 4355) // warning C4355: 'this' : used in base member initializer list diff --git a/src/core/gpu_thread.cpp b/src/core/gpu_thread.cpp index f1e48690d..6834f10a0 100644 --- a/src/core/gpu_thread.cpp +++ b/src/core/gpu_thread.cpp @@ -61,6 +61,8 @@ static bool Reconfigure(std::string serial, std::optional renderer, // NOTE: Use with care! The handler needs to manually run the destructor. template +T* AllocateCommand(u32 size, GPUBackendCommandType type, Args... args); +template T* AllocateCommand(GPUBackendCommandType type, Args... args); static u32 GetPendingCommandSize(); @@ -248,21 +250,27 @@ GPUThreadCommand* GPUThread::AllocateCommand(GPUBackendCommandType command, u32 } template -T* GPUThread::AllocateCommand(GPUBackendCommandType command, Args... args) +T* GPUThread::AllocateCommand(u32 size, GPUBackendCommandType type, Args... args) { - const u32 size = GPUThreadCommand::AlignCommandSize(sizeof(T)); - GPUThreadCommand* cmd = AllocateCommand(command, size); - DebugAssert(cmd->size == size); + const u32 alloc_size = GPUThreadCommand::AlignCommandSize(size); + GPUThreadCommand* cmd = AllocateCommand(type, alloc_size); + DebugAssert(cmd->size == alloc_size); new (cmd) T(std::forward(args)...); // constructor may overwrite the fields, need to reset them - cmd->type = command; - cmd->size = size; + cmd->type = type; + cmd->size = alloc_size; return static_cast(cmd); } +template +T* GPUThread::AllocateCommand(GPUBackendCommandType type, Args... args) +{ + return AllocateCommand(sizeof(T), type, std::forward(args)...); +} + u32 GPUThread::GetPendingCommandSize() { const u32 read_ptr = s_state.command_fifo_read_ptr.load(std::memory_order_acquire); @@ -995,6 +1003,16 @@ void GPUThread::RunOnBackend(AsyncBackendCallType func, bool sync, bool spin_or_ PushCommand(cmd); } +std::pair GPUThread::BeginASyncBufferCall(AsyncBufferCallType func, u32 buffer_size) +{ + // this is less than optimal, but it's only used for input osd updates currently, so whatever + GPUThreadAsyncCallCommand* const cmd = AllocateCommand( + sizeof(GPUThreadAsyncCallCommand) + buffer_size, GPUBackendCommandType::AsyncCall); + void* const buffer = static_cast(cmd + 1); + cmd->func = [func, buffer]() { func(buffer); }; + return std::make_pair(static_cast(cmd), buffer); +} + void GPUThread::UpdateSettings(bool gpu_settings_changed, bool device_settings_changed) { if (device_settings_changed) diff --git a/src/core/gpu_thread.h b/src/core/gpu_thread.h index d8debf55b..1737a5d1c 100644 --- a/src/core/gpu_thread.h +++ b/src/core/gpu_thread.h @@ -7,6 +7,7 @@ #include #include +#include class Error; struct WindowInfo; @@ -28,6 +29,7 @@ struct GPUBackendUpdateDisplayCommand; namespace GPUThread { using AsyncCallType = std::function; using AsyncBackendCallType = std::function; +using AsyncBufferCallType = void(*)(void*); enum class RunIdleReason : u8 { @@ -70,6 +72,7 @@ bool IsOnThread(); bool IsUsingThread(); void RunOnThread(AsyncCallType func); void RunOnBackend(AsyncBackendCallType func, bool sync, bool spin_or_wake); +std::pair BeginASyncBufferCall(AsyncBufferCallType func, u32 buffer_size); void SetVSync(GPUVSyncMode mode, bool allow_present_throttle); // Should only be called on the GPU thread. diff --git a/src/core/gpu_thread_commands.h b/src/core/gpu_thread_commands.h index 9fda31e14..7b289fda5 100644 --- a/src/core/gpu_thread_commands.h +++ b/src/core/gpu_thread_commands.h @@ -23,11 +23,6 @@ namespace System { struct MemorySaveState; } -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4200) // warning C4200: nonstandard extension used: zero-sized array in struct/union -#endif - enum class GPUBackendCommandType : u8 { Wraparound, @@ -87,6 +82,7 @@ struct GPUThreadReconfigureCommand : public GPUThreadCommand struct GPUThreadAsyncCallCommand : public GPUThreadCommand { + GPUThreadAsyncCallCommand() = default; GPUThreadAsyncCallCommand(std::function func_) : func(std::move(func_)) {} std::function func; @@ -329,7 +325,3 @@ struct GPUBackendDrawPreciseLineCommand : public GPUBackendDrawCommand Vertex vertices[0]; }; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif