remove readback hacks, allows to read/write guest memory directly

This commit is contained in:
nmzik committed 2026-07-17 05:16:00 +02:00
1 parent 013e9a4485
commit e903c93848
27 files changed
+522 -1228

No files matched your search

@@ -12,8 +12,6 @@
namespace Libs::Graphics {
class CommandProcessorGuestAccessScope;
inline constexpr uint32_t AcquireGcrGl2Writeback = 1u << 15u;
bool TestWaitRegMemValue(uint64_t value, uint64_t ref, uint64_t mask, uint32_t func);
@@ -72,6 +70,21 @@ public:
}
}
void SubmitForReadback() {
if (!Active()) {
return;
}
SubmitCurrent();
}
void ResumeAfterReadback() {
if (!Active()) {
return;
}
Current()->WaitForFenceAndReset();
Current()->Begin();
}
private:
CommandBuffer* SubmitCurrent() {
auto* submitted = Current();
@@ -107,22 +120,26 @@ public:
void Reset();
void BufferInit();
void BufferFlush();
void BufferFlushAndWait();
void BufferWait();
[[nodiscard]] int BeginReadbackTransaction(bool mutex_preowned) {
if (!mutex_preowned) {
m_mutex.Lock();
void BufferInit();
void BufferFlush();
void BufferFlushAndWait();
void BufferWait();
void BeginReadbackTransaction() {
m_mutex.Lock();
if (m_readback_active) {
EXIT("nested command-processor readback transaction\n");
}
m_scheduler.Flush();
m_scheduler.WaitAll();
return m_scheduler.Queue();
m_readback_active = true;
m_readback_finished = false;
}
void EndReadbackTransaction(bool mutex_preowned) {
if (!mutex_preowned) {
m_mutex.Unlock();
void FinishReadbackTransaction();
void EndReadbackTransaction() {
if (!m_readback_active) {
EXIT("command-processor readback transaction is not active\n");
}
m_readback_active = false;
m_readback_finished = false;
m_mutex.Unlock();
}
void RunLock() { m_run_mutex.Lock(); }
@@ -164,7 +181,6 @@ public:
uint32_t value);
void PrepareCpuFlip();
void SynchronizeGpu();
void SynchronizeGpuRange(uint64_t vaddr, uint64_t size);
void MemoryBarrier();
void TriggerEopEventAtEndOfPipe(uint32_t interrupt_context_id);
void RenderTextureBarrier(uint64_t vaddr, uint64_t size);
@@ -182,9 +198,6 @@ public:
void PopMarker() {}
void PrefetchL2(void* addr, uint32_t size) {}
void ClearGds(uint64_t dw_offset, uint32_t dw_num, uint32_t clear_value);
void ReadGds(uint32_t* dst, uint32_t dw_offset, uint32_t dw_size);
void ResetDeCe();
void WaitCe();
void WaitDeDiff(uint32_t diff);
@@ -208,7 +221,7 @@ public:
void Run(uint32_t* data, uint32_t num_dw);
void SetQueue(int queue) { m_scheduler.SetQueue(queue); }
void SetQueue(int queue);
[[nodiscard]] int GetQueue() const { return m_scheduler.Queue(); }
[[nodiscard]] const FlipInfo& GetFlip() const { return m_flip; }
@@ -218,8 +231,6 @@ public:
void SetSubmitId(uint64_t submit_id) { m_submit_id = submit_id; }
private:
friend class CommandProcessorGuestAccessScope;
struct Counter {
Common::Mutex mutex;
Common::CondVar cond_var;
@@ -231,6 +242,7 @@ private:
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();
CommandBuffer* CurrentBuffer() { return m_scheduler.Current(); }
void CheckBuffer() const { m_scheduler.CheckActive(); }
@@ -250,8 +262,11 @@ private:
uint64_t m_dispatch_indirect_args_base_addr = 0;
uint32_t m_num_instances = 1;
Common::Mutex m_mutex;
Common::Mutex m_run_mutex;
inline static Common::Mutex m_mutex;
inline static std::array<CommandProcessor*, GraphicContext::QUEUES_NUM> m_processors {};
inline static bool m_readback_active = false;
inline static bool m_readback_finished = false;
Common::Mutex m_run_mutex;
CommandScheduler m_scheduler;
@@ -2233,7 +2233,7 @@ KYTY_CP_OP_PARSER(CpOpCopyData) {
cp->WriteReferenceClock(dst, num_bytes);
return 5;
}
const auto dma_src = CopyDataSrcToDma(src_sel);
const auto dma_src = CopyDataSrcToDma(src_sel);
if (dma_src == 2 && num_bytes == 8) {
EXIT("unsupported 64-bit immediate copyData\n");
}
@@ -2636,7 +2636,6 @@ KYTY_CP_OP_PARSER(CpOpIndirectCxRegs) {
if (indirect_buffer == nullptr) {
EXIT("indirect CX registers have null address, num_regs = %" PRIu32 "\n", indirect_num_dw);
}
for (uint32_t i = 0; i < indirect_num_dw; i++, indirect_buffer += 2) {
auto cmd_offset = indirect_buffer[0];
auto value = indirect_buffer[1];
@@ -2695,13 +2694,14 @@ KYTY_CP_OP_PARSER(CpOpIndirectShRegs) {
if (indirect_buffer == nullptr) {
EXIT("indirect SH registers have null address, num_regs = %" PRIu32 "\n", indirect_num_dw);
}
const auto indirect_address = reinterpret_cast<uint64_t>(indirect_buffer);
for (uint32_t i = 0; i < indirect_num_dw; i++, indirect_buffer += 2) {
auto raw_cmd_offset = indirect_buffer[0];
auto cmd_offset = NormalizeRegisterOffset(raw_cmd_offset);
auto value = indirect_buffer[1];
//Not sure if this is correct
// Not sure if this is correct
if (raw_cmd_offset != cmd_offset) {
LOGF_COLOR(Log::Color::Red,
"\t temporary: normalized indirect SH register offset 0x%08" PRIx32
@@ -2709,7 +2709,7 @@ KYTY_CP_OP_PARSER(CpOpIndirectShRegs) {
raw_cmd_offset, cmd_offset);
}
//Not sure if this is correct
// Not sure if this is correct
if (cmd_offset == Pm4::SH_NOP || raw_cmd_offset == 0xffffffffu) {
continue;
}
@@ -2725,8 +2725,7 @@ KYTY_CP_OP_PARSER(CpOpIndirectShRegs) {
if (pfunc == nullptr) {
LOGF("unknown indirect SH register: index=%" PRIu32 "/%" PRIu32 ", regs=0x%016" PRIx64
", offset=0x%08" PRIx32 ", value=0x%08" PRIx32 "\n",
i, indirect_num_dw, reinterpret_cast<uint64_t>(indirect_buffer - i * 2),
cmd_offset, value);
i, indirect_num_dw, indirect_address, cmd_offset, value);
auto* dump_regs = indirect_buffer - i * 2;
for (uint32_t j = 0; j < indirect_num_dw && j < 16; j++) {
LOGF("\t sh_indirect[%" PRIu32 "] offset=0x%08" PRIx32 ", value=0x%08" PRIx32 "\n",
@@ -2758,13 +2757,12 @@ KYTY_CP_OP_PARSER(CpOpIndirectUcRegs) {
if (indirect_buffer == nullptr) {
EXIT("indirect UC registers have null address, num_regs = %" PRIu32 "\n", indirect_num_dw);
}
for (uint32_t i = 0; i < indirect_num_dw; i++, indirect_buffer += 2) {
auto raw_cmd_offset = indirect_buffer[0];
auto cmd_offset = NormalizeRegisterOffset(raw_cmd_offset);
auto value = indirect_buffer[1];
//Not sure if this is correct
// Not sure if this is correct
if (raw_cmd_offset != cmd_offset) {
LOGF_COLOR(Log::Color::Red,
"\t temporary: normalized indirect UC register offset 0x%08" PRIx32