mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-24 12:56:53 +02:00
refactor(gpu): use a single ordered PM4 scheduler
This commit is contained in:
@@ -2,12 +2,10 @@
|
||||
#define GRAPHICS_GUEST_GPU_COMMAND_PROCESSOR_COMMAND_PROCESSOR_H
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/threads.h"
|
||||
#include "graphics/guest_gpu/hardwareContext.h"
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
#include "graphics/host_gpu/renderer/renderContext.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
@@ -17,94 +15,25 @@ inline constexpr uint32_t AcquireGcrGl2Writeback = 1u << 15u;
|
||||
|
||||
bool TestWaitRegMemValue(uint64_t value, uint64_t ref, uint64_t mask, uint32_t func);
|
||||
|
||||
class CommandScheduler {
|
||||
enum class Pm4ProcessResult { Complete, Blocked };
|
||||
|
||||
class Pm4Execution {
|
||||
public:
|
||||
static constexpr int BuffersNum = 8;
|
||||
|
||||
CommandScheduler(HW::Context& registers, HW::UserConfig& user_config, HW::Shader& shaders)
|
||||
: m_registers(registers), m_user_config(user_config), m_shaders(shaders) {}
|
||||
|
||||
bool Active() const { return m_current >= 0 && m_current < BuffersNum; }
|
||||
void CheckActive() const { EXIT_IF(!Active()); }
|
||||
|
||||
RenderCommandBuffer& Current() const {
|
||||
CheckActive();
|
||||
EXIT_IF(m_buffers[m_current] == nullptr);
|
||||
return *m_buffers[m_current];
|
||||
}
|
||||
|
||||
void Init() {
|
||||
if (m_current >= 0) {
|
||||
return;
|
||||
}
|
||||
for (auto& buf: m_buffers) {
|
||||
EXIT_IF(buf != nullptr);
|
||||
buf = new RenderCommandBuffer(m_registers, m_user_config, m_shaders);
|
||||
}
|
||||
m_current = 0;
|
||||
Current().Begin();
|
||||
}
|
||||
|
||||
void Flush() {
|
||||
SubmitCurrent();
|
||||
BeginNext();
|
||||
}
|
||||
|
||||
CommandBuffer& FlushAndGetSubmitted() {
|
||||
auto& submitted = SubmitCurrent();
|
||||
BeginNext();
|
||||
return submitted;
|
||||
}
|
||||
|
||||
void CopyBuffers(std::array<CommandBuffer*, BuffersNum>& out) const {
|
||||
for (int i = 0; i < BuffersNum; i++) {
|
||||
auto* buf = m_buffers[i];
|
||||
EXIT_IF(buf == nullptr);
|
||||
out[i] = buf;
|
||||
}
|
||||
}
|
||||
|
||||
void WaitAll() {
|
||||
for (auto* buf: m_buffers) {
|
||||
EXIT_IF(buf == nullptr);
|
||||
buf->WaitForFenceAndReset();
|
||||
}
|
||||
}
|
||||
|
||||
void SubmitForReadback() {
|
||||
if (!Active()) {
|
||||
return;
|
||||
}
|
||||
SubmitCurrent();
|
||||
}
|
||||
|
||||
void ResumeAfterReadback() {
|
||||
if (!Active()) {
|
||||
return;
|
||||
}
|
||||
Current().WaitForFenceAndReset();
|
||||
Current().Begin();
|
||||
}
|
||||
[[nodiscard]] bool MadeProgress() const noexcept { return m_made_progress; }
|
||||
|
||||
private:
|
||||
CommandBuffer& SubmitCurrent() {
|
||||
auto& submitted = Current();
|
||||
submitted.End();
|
||||
submitted.Execute();
|
||||
return submitted;
|
||||
}
|
||||
friend class CommandProcessor;
|
||||
|
||||
void BeginNext() {
|
||||
m_current = (m_current + 1) % BuffersNum;
|
||||
Current().WaitForFenceAndReset();
|
||||
Current().Begin();
|
||||
}
|
||||
struct BufferCursor {
|
||||
uint32_t* next_packet = nullptr;
|
||||
uint32_t remaining_dw = 0;
|
||||
uint32_t total_dw = 0;
|
||||
uint32_t deferred_advance_dw = 0;
|
||||
};
|
||||
|
||||
RenderCommandBuffer* m_buffers[BuffersNum] = {};
|
||||
int m_current = -1;
|
||||
HW::Context& m_registers;
|
||||
HW::UserConfig& m_user_config;
|
||||
HW::Shader& m_shaders;
|
||||
std::vector<BufferCursor> m_buffer_stack;
|
||||
bool m_suspended = false;
|
||||
bool m_made_progress = false;
|
||||
};
|
||||
|
||||
class CommandProcessor {
|
||||
@@ -116,8 +45,8 @@ public:
|
||||
int64_t flip_arg = 0;
|
||||
};
|
||||
|
||||
CommandProcessor();
|
||||
~CommandProcessor() { KYTY_NOT_IMPLEMENTED; }
|
||||
CommandProcessor() = default;
|
||||
~CommandProcessor() = default;
|
||||
|
||||
KYTY_CLASS_NO_COPY(CommandProcessor);
|
||||
|
||||
@@ -128,7 +57,6 @@ public:
|
||||
void BufferFlushAndWait();
|
||||
void BufferWait();
|
||||
void BeginReadbackTransaction() {
|
||||
m_mutex.Lock();
|
||||
if (m_readback_active) {
|
||||
EXIT("nested command-processor readback transaction\n");
|
||||
}
|
||||
@@ -142,12 +70,8 @@ public:
|
||||
}
|
||||
m_readback_active = false;
|
||||
m_readback_finished = false;
|
||||
m_mutex.Unlock();
|
||||
}
|
||||
|
||||
void RunLock() { m_run_mutex.Lock(); }
|
||||
void RunUnlock() { m_run_mutex.Unlock(); }
|
||||
|
||||
HW::Context& GetCtx() { return m_ctx; }
|
||||
HW::UserConfig& GetUcfg() { return m_ucfg; }
|
||||
HW::Shader& GetShCtx() { return m_sh_ctx; }
|
||||
@@ -202,10 +126,11 @@ public:
|
||||
|
||||
void PrefetchL2(void* addr, uint32_t size) {}
|
||||
void ResetDeCe();
|
||||
void SetCeComplete(bool complete) { m_ce_complete = complete; }
|
||||
void WaitCe();
|
||||
void WaitDeDiff(uint32_t diff);
|
||||
void IncremenetDe();
|
||||
void IncremenetCe();
|
||||
void IncrementDe();
|
||||
void IncrementCe();
|
||||
|
||||
void WriteConstRam(uint32_t offset, const uint32_t* src, uint32_t dw_num);
|
||||
void DumpConstRam(uint32_t* dst, uint32_t offset, uint32_t dw_num);
|
||||
@@ -222,30 +147,26 @@ public:
|
||||
const volatile void* address, uint32_t count_in_dwords);
|
||||
[[nodiscard]] bool ShouldSkipPredicatedPackets() const { return m_predicate_skip; }
|
||||
|
||||
void Run(uint32_t* data, uint32_t num_dw);
|
||||
Pm4ProcessResult Process(Pm4Execution& execution, uint32_t* buffer, uint32_t size_dw);
|
||||
void ProcessIndirectBuffer(uint32_t* buffer, uint32_t size_dw);
|
||||
|
||||
[[nodiscard]] const FlipInfo& GetFlip() const { return m_flip; }
|
||||
void SetFlip(const FlipInfo& flip) { m_flip = flip; }
|
||||
void SetFlip(const FlipInfo& flip) { m_flip = flip; }
|
||||
|
||||
[[nodiscard]] uint64_t GetSubmitId() const { return m_submit_id; }
|
||||
void SetSubmitId(uint64_t submit_id) { m_submit_id = submit_id; }
|
||||
|
||||
private:
|
||||
struct Counter {
|
||||
Common::Mutex mutex;
|
||||
Common::CondVar cond_var;
|
||||
uint32_t value = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void WriteAtEndOfPipe(uint32_t cache_policy, uint32_t event_write_dest, uint32_t eop_event_type,
|
||||
uint32_t cache_action, uint32_t event_index, uint32_t event_write_source,
|
||||
void* dst_gpu_addr, T value, uint32_t interrupt_selector,
|
||||
uint32_t interrupt_context_id);
|
||||
void FinishCommandProcessors();
|
||||
void ProcessPm4(Pm4Execution& execution, size_t stop_depth);
|
||||
void SuspendPm4();
|
||||
|
||||
RenderCommandBuffer& CurrentBuffer() { return m_scheduler.Current(); }
|
||||
void CheckBuffer() const { m_scheduler.CheckActive(); }
|
||||
CommandScheduler& GetScheduler() const { return GetRenderContext().GetCommandScheduler(); }
|
||||
RenderCommandBuffer& CurrentBuffer() { return GetScheduler().Current(); }
|
||||
void CheckBuffer() const { GetScheduler().CheckActive(); }
|
||||
GpuResourceManager& GetGpuResources() const { return GetRenderContext().GetGpuResources(); }
|
||||
|
||||
HW::Context m_ctx;
|
||||
@@ -259,16 +180,11 @@ private:
|
||||
uint64_t m_dispatch_indirect_args_base_addr = 0;
|
||||
uint32_t m_num_instances = 1;
|
||||
|
||||
inline static Common::Mutex m_mutex;
|
||||
inline static std::vector<CommandProcessor*> m_processors;
|
||||
inline static bool m_readback_active = false;
|
||||
inline static bool m_readback_finished = false;
|
||||
Common::Mutex m_run_mutex;
|
||||
|
||||
CommandScheduler m_scheduler;
|
||||
|
||||
Counter m_de_counter;
|
||||
Counter m_ce_counter;
|
||||
uint32_t m_de_count = 0;
|
||||
uint32_t m_ce_count = 0;
|
||||
bool m_ce_complete = false;
|
||||
bool m_readback_active = false;
|
||||
bool m_readback_finished = false;
|
||||
|
||||
uint32_t m_const_ram[0x3000] = {0};
|
||||
|
||||
|
||||
@@ -1984,7 +1984,6 @@ KYTY_CP_OP_PARSER(CpOpAcquireMem) {
|
||||
}
|
||||
|
||||
if (stall_mode == 0) {
|
||||
cp.BufferFlush();
|
||||
cp.BufferWait();
|
||||
}
|
||||
|
||||
@@ -2166,10 +2165,10 @@ KYTY_CP_OP_PARSER(CpOpBranch) {
|
||||
reinterpret_cast<uint64_t>(else_buffer), else_num_dw);
|
||||
|
||||
if (take_then) {
|
||||
cp.Run(then_buffer, then_num_dw);
|
||||
cp.ProcessIndirectBuffer(then_buffer, then_num_dw);
|
||||
} else if (mode == 2 && else_num_dw != 0) {
|
||||
EXIT_NOT_IMPLEMENTED(else_buffer == nullptr);
|
||||
cp.Run(else_buffer, else_num_dw);
|
||||
cp.ProcessIndirectBuffer(else_buffer, else_num_dw);
|
||||
}
|
||||
|
||||
return payload_dw;
|
||||
@@ -2496,7 +2495,7 @@ KYTY_CP_OP_PARSER(CpOpIncrementCeCounter) {
|
||||
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0008400);
|
||||
EXIT_NOT_IMPLEMENTED(buffer[0] != 1);
|
||||
|
||||
cp.IncremenetCe();
|
||||
cp.IncrementCe();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2507,7 +2506,7 @@ KYTY_CP_OP_PARSER(CpOpIncrementDeCounter) {
|
||||
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0008500);
|
||||
EXIT_NOT_IMPLEMENTED(buffer[0] != 0);
|
||||
|
||||
cp.IncremenetDe();
|
||||
cp.IncrementDe();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2607,7 +2606,7 @@ KYTY_CP_OP_PARSER(CpOpIndirectBuffer) {
|
||||
|
||||
GraphicsDbgDumpDcb("ci", indirect_num_dw, indirect_buffer);
|
||||
|
||||
cp.Run(indirect_buffer, indirect_num_dw);
|
||||
cp.ProcessIndirectBuffer(indirect_buffer, indirect_num_dw);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@ void GraphicsRunDone();
|
||||
int GraphicsRunGetFrameNum();
|
||||
[[nodiscard]] bool GraphicsRunIsCommandProcessorThread() noexcept;
|
||||
[[nodiscard]] CommandProcessor* GraphicsRunCurrentCommandProcessor() noexcept;
|
||||
void GraphicsRunFinishCommandProcessors();
|
||||
void GraphicsRunFinishScheduler();
|
||||
[[nodiscard]] bool GraphicsRunSubmissionLockHeld() noexcept;
|
||||
[[nodiscard]] bool GraphicsRunGpuLockHeld() noexcept;
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
Reference in New Issue
Block a user