refactor(gpu): use a single ordered PM4 scheduler

This commit is contained in:
nmzik
2026-07-22 23:15:03 +02:00
parent dbcb444c05
commit f60007e923
12 changed files with 680 additions and 918 deletions
@@ -554,7 +554,7 @@ bool BufferCache::InvalidateMemory(PageFaultAccess access, uint64_t vaddr, uint6
return action == CpuFaultAction::Continue;
}
if (GraphicsRunIsCommandProcessorThread()) {
GraphicsRunFinishCommandProcessors();
GraphicsRunFinishScheduler();
}
m_readback->Request(access, vaddr, size);
return true;
@@ -0,0 +1,92 @@
#include "graphics/host_gpu/renderer/commandScheduler.h"
#include "common/assert.h"
namespace Libs::Graphics {
void CommandScheduler::Begin(HW::Context& registers, HW::UserConfig& user_config,
HW::Shader& shaders) {
m_registers = &registers;
m_user_config = &user_config;
m_shaders = &shaders;
if (!Active()) {
for (auto& buffer: m_buffers) {
buffer = std::make_unique<RenderCommandBuffer>();
}
m_current = 0;
}
BindCurrent();
if (!m_recording) {
Current().Begin();
m_recording = true;
}
}
void CommandScheduler::Flush() {
SubmitCurrent();
BeginNext();
}
CommandBuffer& CommandScheduler::FlushAndGetSubmitted() {
auto& submitted = SubmitCurrent();
BeginNext();
return submitted;
}
void CommandScheduler::Finish() {
CheckActive();
if (m_recording) {
SubmitCurrent();
}
for (auto& buffer: m_buffers) {
buffer->WaitForFenceAndReset();
}
BindCurrent();
Current().Begin();
m_recording = true;
}
void CommandScheduler::FinishCurrent() {
auto& submitted = SubmitCurrent();
submitted.WaitForFenceAndReset();
submitted.Begin();
m_recording = true;
}
void CommandScheduler::CheckActive() const {
EXIT_IF(!Active() || m_current >= BufferCount);
}
RenderCommandBuffer& CommandScheduler::Current() const {
CheckActive();
EXIT_IF(m_buffers[m_current] == nullptr);
return *m_buffers[m_current];
}
void CommandScheduler::BindCurrent() const {
EXIT_IF(m_registers == nullptr || m_user_config == nullptr || m_shaders == nullptr);
Current().Bind(*m_registers, *m_user_config, *m_shaders);
}
CommandBuffer& CommandScheduler::SubmitCurrent() {
CheckActive();
EXIT_IF(!m_recording);
auto& submitted = Current();
submitted.End();
submitted.Execute();
m_recording = false;
return submitted;
}
void CommandScheduler::BeginNext() {
EXIT_IF(m_recording);
m_current = (m_current + 1) % BufferCount;
Current().WaitForFenceAndReset();
BindCurrent();
Current().Begin();
m_recording = true;
}
} // namespace Libs::Graphics
@@ -0,0 +1,45 @@
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_COMMANDSCHEDULER_H_
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_COMMANDSCHEDULER_H_
#include "common/common.h"
#include "graphics/host_gpu/renderer/render.h"
#include <array>
#include <memory>
namespace Libs::Graphics {
class CommandScheduler {
public:
static constexpr int BufferCount = 8;
CommandScheduler() = default;
~CommandScheduler() = default;
KYTY_CLASS_NO_COPY(CommandScheduler);
void Begin(HW::Context& registers, HW::UserConfig& user_config, HW::Shader& shaders);
void Flush();
CommandBuffer& FlushAndGetSubmitted();
void Finish();
void FinishCurrent();
[[nodiscard]] bool Active() const noexcept { return m_current >= 0; }
void CheckActive() const;
RenderCommandBuffer& Current() const;
private:
void BindCurrent() const;
CommandBuffer& SubmitCurrent();
void BeginNext();
std::array<std::unique_ptr<RenderCommandBuffer>, BufferCount> m_buffers;
int m_current = -1;
bool m_recording = false;
HW::Context* m_registers = nullptr;
HW::UserConfig* m_user_config = nullptr;
HW::Shader* m_shaders = nullptr;
};
} // namespace Libs::Graphics
#endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_COMMANDSCHEDULER_H_
+13 -8
View File
@@ -129,17 +129,22 @@ private:
class RenderCommandBuffer final: public CommandBuffer {
public:
RenderCommandBuffer(HW::Context& registers, HW::UserConfig& user_config, HW::Shader& shaders)
: m_registers(registers), m_user_config(user_config), m_shaders(shaders) {}
RenderCommandBuffer() = default;
[[nodiscard]] HW::Context& GetRegisters() const noexcept { return m_registers; }
[[nodiscard]] HW::UserConfig& GetUserConfig() const noexcept { return m_user_config; }
[[nodiscard]] HW::Shader& GetShaders() const noexcept { return m_shaders; }
void Bind(HW::Context& registers, HW::UserConfig& user_config, HW::Shader& shaders) noexcept {
m_registers = &registers;
m_user_config = &user_config;
m_shaders = &shaders;
}
[[nodiscard]] HW::Context& GetRegisters() const noexcept { return *m_registers; }
[[nodiscard]] HW::UserConfig& GetUserConfig() const noexcept { return *m_user_config; }
[[nodiscard]] HW::Shader& GetShaders() const noexcept { return *m_shaders; }
private:
HW::Context& m_registers;
HW::UserConfig& m_user_config;
HW::Shader& m_shaders;
HW::Context* m_registers = nullptr;
HW::UserConfig* m_user_config = nullptr;
HW::Shader* m_shaders = nullptr;
};
void RenderDrawIndex(uint64_t submit_id, RenderCommandBuffer& buffer, uint32_t index_type_and_size,
@@ -6,6 +6,7 @@
#include "common/common.h"
#include "common/threads.h"
#include "graphics/host_gpu/renderer/bufferCache.h"
#include "graphics/host_gpu/renderer/commandScheduler.h"
#include "graphics/host_gpu/renderer/descriptorCache.h"
#include "graphics/host_gpu/renderer/framebufferCache.h"
#include "graphics/host_gpu/renderer/gdsBuffer.h"
@@ -30,6 +31,7 @@ public:
[[nodiscard]] GraphicContext& GetGraphics() const noexcept { return m_graphics; }
Common::Mutex& GetMutex() { return m_mutex; }
CommandScheduler& GetCommandScheduler() { return m_command_scheduler; }
PipelineCache& GetPipelineCache() { return m_pipeline_cache; }
DescriptorCache& GetDescriptorCache() { return m_descriptor_cache; }
FramebufferCache& GetFramebufferCache() { return m_framebuffer_cache; }
@@ -52,6 +54,7 @@ private:
GraphicContext& m_graphics;
Common::Mutex m_mutex;
CommandScheduler m_command_scheduler;
PipelineCache m_pipeline_cache;
DescriptorCache m_descriptor_cache;
FramebufferCache m_framebuffer_cache;
@@ -3653,7 +3653,7 @@ bool TextureCache::InvalidateMemory(PageFaultAccess access, uint64_t vaddr, uint
if (needs_readback) {
if (GraphicsRunIsCommandProcessorThread()) {
GraphicsRunFinishCommandProcessors();
GraphicsRunFinishScheduler();
}
m_readback->Request(access, vaddr, size);
action = m_memory_tracker.BeginCpuFault(vaddr, size, access);