From 146253afb6532c1e5cc04d2dbf258a655a91ff8c Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 17 Aug 2026 11:27:49 +0200 Subject: [PATCH] renderer&guest_gpu: minor cleanup --- src/graphics/guest_gpu/graphicsRun.cpp | 204 ++++-------------- src/graphics/guest_gpu/graphicsRun.h | 89 +++++++- .../host_gpu/renderer/cache/bufferCache.cpp | 6 +- .../renderer/cache/gpuResourceManager.h | 6 +- .../host_gpu/renderer/renderContext.cpp | 4 +- .../host_gpu/renderer/renderContext.h | 6 +- src/kernel/memory.cpp | 2 +- tests/ShaderRecompilerComputeTests.cpp | 2 +- 8 files changed, 130 insertions(+), 189 deletions(-) diff --git a/src/graphics/guest_gpu/graphicsRun.cpp b/src/graphics/guest_gpu/graphicsRun.cpp index 74057a4b0..bcf2631ac 100644 --- a/src/graphics/guest_gpu/graphicsRun.cpp +++ b/src/graphics/guest_gpu/graphicsRun.cpp @@ -37,7 +37,7 @@ static thread_local CommandProcessor* g_current_processor = nullptr; static thread_local Pm4Execution* g_current_execution = nullptr; static thread_local bool g_gpu_mutex_owned = false; static thread_local bool g_gpu_thread = false; -static thread_local GpuState* g_gpu_state = nullptr; +static thread_local GuestGpu* g_gpu_state = nullptr; class GpuMutexLock final { public: @@ -60,115 +60,30 @@ private: Common::Mutex& m_mutex; }; -struct OwnedCmdBuffer { - OwnedCmdBuffer() = default; - explicit OwnedCmdBuffer(const uint32_t* data, uint32_t count) { - EXIT_IF(data == nullptr && count != 0); - if (count != 0) { - m_words.assign(data, data + count); - } - } - - [[nodiscard]] bool Empty() const noexcept { return m_words.empty(); } - [[nodiscard]] uint32_t Size() const noexcept { return static_cast(m_words.size()); } - [[nodiscard]] uint32_t* Data() noexcept { return m_words.data(); } - -private: - std::vector m_words; -}; - -class GpuState { -public: - static constexpr uint32_t ComputePipeCount = 7; - static constexpr uint32_t QueuesPerComputePipe = 8; - static constexpr uint32_t ComputeQueueCount = ComputePipeCount * QueuesPerComputePipe; - static constexpr uint32_t QueueCount = 1 + ComputeQueueCount; - - explicit GpuState(RenderContext& renderer): m_renderer(renderer) { - EXIT_NOT_IMPLEMENTED(!Common::Thread::IsMainThread()); - m_gfx_cp = std::make_unique(renderer); - m_thread = std::jthread(ThreadRun, this); - } - ~GpuState(); - - KYTY_CLASS_NO_COPY(GpuState); - - void Submit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* cmd_const_buffer, - uint32_t num_const_dw, bool trigger_agc_interrupt_on_done); - void SubmitCompute(uint32_t queue, uint32_t* cmd_buffer, uint32_t num_dw, - bool trigger_agc_interrupt_on_done); - void SubmitFlipPreparation(uint64_t request_id); - void Done(); - void Shutdown(); - [[nodiscard]] bool IsStopping(); - void SendCommand(Common::UniqueFunction&& command); - void SendCommandSync(Common::UniqueFunction&& command); - int GetFrameNum(); - [[nodiscard]] static bool IsGpuThread() noexcept { return g_gpu_thread; } - -private: - enum class SubmissionType { Graphics, Compute, FlipPreparation }; - - struct Submission { - SubmissionType type = SubmissionType::Graphics; - uint32_t queue_id = 0; - OwnedCmdBuffer commands; - OwnedCmdBuffer constant_commands; - Pm4Execution command_execution; - Pm4Execution constant_execution; - bool trigger_agc_interrupt_on_done = false; - bool reset_processor = false; - bool started = false; - bool command_complete = false; - bool constant_complete = false; - bool blocked = false; - uint64_t flip_request_id = 0; - }; - - void Enqueue(Submission submission); - void WaitForIdle(); - void ProcessCommands(); - bool Process(Submission& submission); - static void ThreadRun(void* data); - CommandProcessor& GetProcessor(uint32_t queue_id); - - RenderContext& m_renderer; - Common::Mutex m_submission_mutex; - Common::Mutex m_queue_mutex; - std::mutex m_shutdown_mutex; - Common::CondVar m_work_available; - Common::CondVar m_idle; - std::array, QueueCount> m_queues; - std::deque> m_commands; - std::atomic_uint32_t m_pending_commands {0}; - uint32_t m_next_queue = 0; - uint32_t m_submission_count = 0; - bool m_processing = false; - bool m_graphics_done = true; - bool m_accepting = true; - bool m_stopping = false; - bool m_shutdown_complete = false; - - std::unique_ptr m_gfx_cp; - std::array, ComputeQueueCount> m_compute_cp; - - uint64_t m_submit_id = 0; - std::atomic_int m_done_num = 0; - std::jthread m_thread; - - friend class CommandProcessor; -}; - static bool GraphicsRunDebugDumpEnabled() { return Config::GraphicsDebugDumpEnabled() && Config::GetPrintfDirection() != Config::OutputDirection::Silent; } -GpuState::~GpuState() { +GuestGpu::OwnedCmdBuffer::OwnedCmdBuffer(const uint32_t* data, uint32_t count) { + EXIT_IF(data == nullptr && count != 0); + if (count != 0) { + m_words.assign(data, data + count); + } +} + +GuestGpu::GuestGpu(RenderContext& renderer): m_renderer(renderer) { + EXIT_NOT_IMPLEMENTED(!Common::Thread::IsMainThread()); + GraphicsInitJmpTables(); + m_gfx_cp = std::make_unique(renderer); + m_thread = std::jthread(ThreadRun, this); +} + +GuestGpu::~GuestGpu() { Shutdown(); } -void GpuState::Shutdown() { +void GuestGpu::Shutdown() { std::lock_guard shutdown_lock(m_shutdown_mutex); if (m_shutdown_complete) { return; @@ -185,12 +100,12 @@ void GpuState::Shutdown() { m_shutdown_complete = true; } -bool GpuState::IsStopping() { +bool GuestGpu::IsStopping() { Common::LockGuard lock(m_queue_mutex); return m_stopping; } -void GpuState::SendCommand(Common::UniqueFunction&& command) { +void GuestGpu::SendCommand(Common::UniqueFunction&& command) { EXIT_IF(!command); if (IsGpuThread()) { command(); @@ -203,7 +118,7 @@ void GpuState::SendCommand(Common::UniqueFunction&& command) { m_work_available.Signal(); } -void GpuState::ProcessCommands() { +void GuestGpu::ProcessCommands() { EXIT_IF(!IsGpuThread()); while (m_pending_commands.load(std::memory_order_acquire) != 0) { Common::UniqueFunction command; @@ -218,7 +133,7 @@ void GpuState::ProcessCommands() { } } -void GpuState::SendCommandSync(Common::UniqueFunction&& command) { +void GuestGpu::SendCommandSync(Common::UniqueFunction&& command) { EXIT_IF(!command); if (IsGpuThread()) { command(); @@ -232,8 +147,9 @@ void GpuState::SendCommandSync(Common::UniqueFunction&& command) { done.acquire(); } -void GpuState::Submit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* cmd_const_buffer, +void GuestGpu::Submit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* cmd_const_buffer, uint32_t num_const_dw, bool trigger_agc_interrupt_on_done) { + EXIT_IF(cmd_draw_buffer == nullptr || num_draw_dw == 0); GpuMutexLock lock(m_submission_mutex); Submission submission; submission.type = SubmissionType::Graphics; @@ -246,8 +162,9 @@ void GpuState::Submit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* Enqueue(std::move(submission)); } -void GpuState::SubmitCompute(uint32_t queue, uint32_t* cmd_buffer, uint32_t num_dw, +void GuestGpu::SubmitCompute(uint32_t queue, uint32_t* cmd_buffer, uint32_t num_dw, bool trigger_agc_interrupt_on_done) { + EXIT_IF(cmd_buffer == nullptr || num_dw == 0); GpuMutexLock lock(m_submission_mutex); constexpr uint32_t compute_queue_base = 0x20u; @@ -263,7 +180,7 @@ void GpuState::SubmitCompute(uint32_t queue, uint32_t* cmd_buffer, uint32_t num_ Enqueue(std::move(submission)); } -void GpuState::SubmitFlipPreparation(uint64_t request_id) { +void GuestGpu::SubmitFlipPreparation(uint64_t request_id) { GpuMutexLock lock(m_submission_mutex); Submission submission; submission.type = SubmissionType::FlipPreparation; @@ -274,7 +191,7 @@ void GpuState::SubmitFlipPreparation(uint64_t request_id) { Enqueue(std::move(submission)); } -void GpuState::Done() { +void GuestGpu::Done() { GpuMutexLock lock(m_submission_mutex); if (!IsGpuThread()) { WaitForIdle(); @@ -289,11 +206,11 @@ void GpuState::Done() { m_done_num++; } -int GpuState::GetFrameNum() { +int GuestGpu::GetFrameNum() const { return m_done_num; } -CommandProcessor& GpuState::GetProcessor(uint32_t queue_id) { +CommandProcessor& GuestGpu::GetProcessor(uint32_t queue_id) { EXIT_IF(queue_id >= QueueCount); if (queue_id == 0) { return *m_gfx_cp; @@ -531,7 +448,7 @@ void CommandProcessor::DmaData(uint8_t engine, uint8_t dst_sel, uint8_t dst_cach dst_gds, src_gds); } -void GpuState::Enqueue(Submission submission) { +void GuestGpu::Enqueue(Submission submission) { EXIT_IF(submission.queue_id >= QueueCount); Common::LockGuard lock(m_queue_mutex); EXIT_IF(!m_accepting); @@ -540,15 +457,15 @@ void GpuState::Enqueue(Submission submission) { m_work_available.Signal(); } -void GpuState::WaitForIdle() { +void GuestGpu::WaitForIdle() { Common::LockGuard lock(m_queue_mutex); while (m_processing || !m_commands.empty() || m_submission_count != 0) { m_idle.Wait(&m_queue_mutex); } } -void GpuState::ThreadRun(void* data) { - auto* gpu = static_cast(data); +void GuestGpu::ThreadRun(void* data) { + auto* gpu = static_cast(data); EXIT_IF(gpu == nullptr); KYTY_PROFILER_THREAD("Thread_Gpu"); g_gpu_thread = true; @@ -644,7 +561,7 @@ void GpuState::ThreadRun(void* data) { } } -bool GpuState::Process(Submission& submission) { +bool GuestGpu::Process(Submission& submission) { const bool first_slice = !submission.started; if (first_slice && RenderDocCaptureRequested()) { Common::LockGuard render_lock(m_renderer.GetMutex()); @@ -1686,57 +1603,8 @@ void CommandProcessor::SynchronizeGpu() { GetScheduler().FinishCurrent(); } -Gpu::Gpu(RenderContext& renderer) { - EXIT_NOT_IMPLEMENTED(!Common::Thread::IsMainThread()); - GraphicsInitJmpTables(); - m_state = std::make_unique(renderer); -} - -Gpu::~Gpu() = default; - -void Gpu::Shutdown() { - m_state->Shutdown(); -} - -bool Gpu::IsStopping() { - return m_state->IsStopping(); -} - -void Gpu::SendCommand(Common::UniqueFunction&& command) { - m_state->SendCommand(std::move(command)); -} - -void Gpu::SendCommandSync(Common::UniqueFunction&& command) { - m_state->SendCommandSync(std::move(command)); -} - -void Gpu::Submit(uint32_t* draw_commands, uint32_t draw_size_dw, uint32_t* constant_commands, - uint32_t constant_size_dw, bool trigger_agc_interrupt_on_done) { - EXIT_IF(draw_commands == nullptr || draw_size_dw == 0); - m_state->Submit(draw_commands, draw_size_dw, constant_commands, constant_size_dw, - trigger_agc_interrupt_on_done); -} - -void Gpu::SubmitCompute(uint32_t queue, uint32_t* commands, uint32_t size_dw, - bool trigger_agc_interrupt_on_done) { - EXIT_IF(commands == nullptr || size_dw == 0); - m_state->SubmitCompute(queue, commands, size_dw, trigger_agc_interrupt_on_done); -} - -void Gpu::SubmitFlipPreparation(uint64_t request_id) { - m_state->SubmitFlipPreparation(request_id); -} - -void Gpu::Done() { - m_state->Done(); -} - -int Gpu::GetFrameNum() const { - return m_state->GetFrameNum(); -} - -bool Gpu::IsGpuThread() noexcept { - return GpuState::IsGpuThread(); +bool GuestGpu::IsGpuThread() noexcept { + return g_gpu_thread; } } // namespace Libs::Graphics diff --git a/src/graphics/guest_gpu/graphicsRun.h b/src/graphics/guest_gpu/graphicsRun.h index dc9c2cf69..836cd6606 100644 --- a/src/graphics/guest_gpu/graphicsRun.h +++ b/src/graphics/guest_gpu/graphicsRun.h @@ -3,20 +3,28 @@ #include "common/abi.h" #include "common/common.h" +#include "common/threads.h" #include "common/uniqueFunction.h" +#include "graphics/guest_gpu/command_processor/commandProcessor.h" +#include +#include +#include +#include #include +#include +#include +#include namespace Libs::Graphics { -class GpuState; class RenderContext; -class Gpu final { +class GuestGpu final { public: - explicit Gpu(RenderContext& renderer); - ~Gpu(); - KYTY_CLASS_NO_COPY(Gpu); + explicit GuestGpu(RenderContext& renderer); + ~GuestGpu(); + KYTY_CLASS_NO_COPY(GuestGpu); void Shutdown(); [[nodiscard]] bool IsStopping(); @@ -34,7 +42,76 @@ public: [[nodiscard]] static bool IsGpuThread() noexcept; private: - std::unique_ptr m_state; + static constexpr uint32_t ComputePipeCount = 7; + static constexpr uint32_t QueuesPerComputePipe = 8; + static constexpr uint32_t ComputeQueueCount = ComputePipeCount * QueuesPerComputePipe; + static constexpr uint32_t QueueCount = 1 + ComputeQueueCount; + + class OwnedCmdBuffer { + public: + OwnedCmdBuffer() = default; + explicit OwnedCmdBuffer(const uint32_t* data, uint32_t count); + + [[nodiscard]] bool Empty() const noexcept { return m_words.empty(); } + [[nodiscard]] uint32_t Size() const noexcept { + return static_cast(m_words.size()); + } + [[nodiscard]] uint32_t* Data() noexcept { return m_words.data(); } + + private: + std::vector m_words; + }; + + enum class SubmissionType { Graphics, Compute, FlipPreparation }; + + struct Submission { + SubmissionType type = SubmissionType::Graphics; + uint32_t queue_id = 0; + OwnedCmdBuffer commands; + OwnedCmdBuffer constant_commands; + Pm4Execution command_execution; + Pm4Execution constant_execution; + bool trigger_agc_interrupt_on_done = false; + bool reset_processor = false; + bool started = false; + bool command_complete = false; + bool constant_complete = false; + bool blocked = false; + uint64_t flip_request_id = 0; + }; + + void Enqueue(Submission submission); + void WaitForIdle(); + void ProcessCommands(); + bool Process(Submission& submission); + static void ThreadRun(void* data); + CommandProcessor& GetProcessor(uint32_t queue_id); + + RenderContext& m_renderer; + Common::Mutex m_submission_mutex; + Common::Mutex m_queue_mutex; + std::mutex m_shutdown_mutex; + Common::CondVar m_work_available; + Common::CondVar m_idle; + std::array, QueueCount> m_queues; + std::deque> m_commands; + std::atomic_uint32_t m_pending_commands {0}; + uint32_t m_next_queue = 0; + uint32_t m_submission_count = 0; + bool m_processing = false; + bool m_graphics_done = true; + bool m_accepting = true; + bool m_stopping = false; + bool m_shutdown_complete = false; + + std::unique_ptr m_gfx_cp; + std::array, ComputeQueueCount> m_compute_cp; + + uint64_t m_submit_id = 0; + std::atomic_int m_done_num = 0; + std::jthread m_thread; + + friend class CommandProcessor; }; } // namespace Libs::Graphics diff --git a/src/graphics/host_gpu/renderer/cache/bufferCache.cpp b/src/graphics/host_gpu/renderer/cache/bufferCache.cpp index ffed0366c..2fe48bb2b 100644 --- a/src/graphics/host_gpu/renderer/cache/bufferCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/bufferCache.cpp @@ -257,11 +257,7 @@ void BufferCache::InvalidateMemory(uint64_t vaddr, uint64_t size) { } void BufferCache::ReadMemory(uint64_t vaddr, uint64_t size, bool is_write) { - if (Gpu::IsGpuThread()) { - ReadMemoryOnGpu(vaddr, size, is_write); - return; - } - if (CommandScheduler::InDeferredOperation()) { + if (!GuestGpu::IsGpuThread() && CommandScheduler::InDeferredOperation()) { EXIT("unsupported buffer readback from an asynchronous GPU completion, " "addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n", vaddr, size); diff --git a/src/graphics/host_gpu/renderer/cache/gpuResourceManager.h b/src/graphics/host_gpu/renderer/cache/gpuResourceManager.h index 501b62253..1c3f4ce45 100644 --- a/src/graphics/host_gpu/renderer/cache/gpuResourceManager.h +++ b/src/graphics/host_gpu/renderer/cache/gpuResourceManager.h @@ -13,7 +13,7 @@ namespace Libs::Graphics { class CommandScheduler; -class Gpu; +class GuestGpu; class GpuResourceManager { public: @@ -23,7 +23,7 @@ public: [[nodiscard]] BufferCache& GetBufferCache() { return m_buffer_cache; } [[nodiscard]] TextureCache& GetTextureCache() { return m_texture_cache; } - void SetGpu(Gpu* gpu) noexcept { m_gpu = gpu; } + void SetGpu(GuestGpu* gpu) noexcept { m_gpu = gpu; } [[nodiscard]] bool HandleFault(PageFaultAccess access, uint64_t fault_vaddr) noexcept; [[nodiscard]] bool InvalidateMemory(uint64_t vaddr, uint64_t size); @@ -39,7 +39,7 @@ private: TextureCache m_texture_cache; mutable std::shared_mutex m_mapped_ranges_mutex; RangeSet m_mapped_ranges; - Gpu* m_gpu = nullptr; + GuestGpu* m_gpu = nullptr; }; } // namespace Libs::Graphics diff --git a/src/graphics/host_gpu/renderer/renderContext.cpp b/src/graphics/host_gpu/renderer/renderContext.cpp index 041443dce..be6d4f8cd 100644 --- a/src/graphics/host_gpu/renderer/renderContext.cpp +++ b/src/graphics/host_gpu/renderer/renderContext.cpp @@ -26,7 +26,7 @@ RenderContext::~RenderContext() { void RenderContext::InitializeGpu(VideoOut::VideoOutDriver* video_out) { EXIT_IF(m_gpu != nullptr); m_video_out = video_out; - m_gpu = std::make_unique(*this); + m_gpu = std::make_unique(*this); m_gpu_resources.SetGpu(m_gpu.get()); } @@ -45,7 +45,7 @@ void RenderContext::ShutdownGpu() { } } -Gpu& RenderContext::GetGpu() const { +GuestGpu& RenderContext::GetGpu() const { EXIT_IF(m_gpu == nullptr); return *m_gpu; } diff --git a/src/graphics/host_gpu/renderer/renderContext.h b/src/graphics/host_gpu/renderer/renderContext.h index b9f70430a..11848f285 100644 --- a/src/graphics/host_gpu/renderer/renderContext.h +++ b/src/graphics/host_gpu/renderer/renderContext.h @@ -24,7 +24,7 @@ class VideoOutDriver; namespace Libs::Graphics { constexpr int AGC_USER_INTERRUPT_EVENT = 0x1800; -class Gpu; +class GuestGpu; class RenderContext { public: @@ -35,7 +35,7 @@ public: [[nodiscard]] GraphicContext& GetGraphics() const noexcept { return m_graphics; } void InitializeGpu(VideoOut::VideoOutDriver* video_out); void ShutdownGpu(); - [[nodiscard]] Gpu& GetGpu() const; + [[nodiscard]] GuestGpu& GetGpu() const; [[nodiscard]] VideoOut::VideoOutDriver& GetVideoOut() const; Common::Mutex& GetMutex() { return m_mutex; } @@ -67,7 +67,7 @@ private: PipelineCache m_pipeline_cache; SamplerCache m_sampler_cache; GpuResourceManager m_gpu_resources; - std::unique_ptr m_gpu; + std::unique_ptr m_gpu; VideoOut::VideoOutDriver* m_video_out = nullptr; Common::Mutex m_eop_mutex; diff --git a/src/kernel/memory.cpp b/src/kernel/memory.cpp index ac0e00cb7..5922cddd7 100644 --- a/src/kernel/memory.cpp +++ b/src/kernel/memory.cpp @@ -869,7 +869,7 @@ bool TryReadBacking(uint64_t vaddr, void* data, uint64_t size) { bool TryReadGpuCleanBacking(uint64_t vaddr, void* data, uint64_t size) { if (g_gpu_resources != nullptr && IsGpuAddressRange(vaddr, size)) { - if (!Graphics::Gpu::IsGpuThread() || + if (!Graphics::GuestGpu::IsGpuThread() || GetGpuResources().GetBufferCache().HasGpuDirtyBytes(vaddr, size) || GetGpuResources().GetTextureCache().QueryRegion(vaddr, size).gpu_image_bytes) { return false; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 4ab356110..c8761ce3d 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -1794,7 +1794,7 @@ public: gpu_thread = std::this_thread::get_id(); Require("GpuCommandLane", "FIFO", order == 1, "synchronous command overtook an older host command"); - Require("GpuCommandLane", "GPU context", Gpu::IsGpuThread(), + Require("GpuCommandLane", "GPU context", GuestGpu::IsGpuThread(), "host command did not run on the GPU thread"); gpu.SendCommandSync( [&nested_thread] { nested_thread = std::this_thread::get_id(); });