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

This commit is contained in:
nmzik
2026-07-17 05:16:00 +02:00
parent 013e9a4485
commit e903c93848
27 changed files with 522 additions and 1228 deletions
+12 -98
View File
@@ -1,14 +1,11 @@
#include "graphics/host_gpu/objects/label.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "kernel/memory.h"
#include "common/threads.h"
#include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/renderer/render.h"
#include <algorithm>
#include <atomic>
#include <memory>
#include <vector>
@@ -22,10 +19,6 @@ enum LabelStatus {
};
struct LabelCallbacks {
uint64_t* dst_gpu_addr64 = nullptr;
uint64_t value64 = 0;
uint32_t* dst_gpu_addr32 = nullptr;
uint32_t value32 = 0;
LabelCallback callback_1 = nullptr;
LabelCallback callback_2 = nullptr;
uint64_t args[LABEL_ARGS_MAX] = {};
@@ -64,10 +57,8 @@ public:
~LabelManager() { KYTY_NOT_IMPLEMENTED; }
KYTY_CLASS_NO_COPY(LabelManager);
Label* Create64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value,
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args);
Label* Create32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value,
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args);
Label* Create(GraphicContext* ctx, LabelCallback callback_1, LabelCallback callback_2,
const uint64_t* args);
void Delete(Label* label);
void Set(CommandBuffer* buffer, Label* label);
void Drain();
@@ -75,9 +66,6 @@ public:
private:
static void ThreadRun(void* data);
template <typename T>
Label* Create(GraphicContext* ctx, T* dst_gpu_addr, T value, LabelCallback callback_1,
LabelCallback callback_2, const uint64_t* args);
bool Remove(Label* label);
static void Destroy(Label* label);
@@ -90,11 +78,6 @@ private:
static LabelManager* g_label_manager = nullptr;
static thread_local bool g_in_label_callback = false;
template <typename T>
void WriteGuestLabel(T* address, T value) {
LabelWriteGuestMemory(address, &value, sizeof(value));
}
class LabelCallbackScope final {
public:
LabelCallbackScope() {
@@ -132,8 +115,7 @@ void LabelManager::ThreadRun(void* data) {
it->completion->event == nullptr) {
EXIT("GPU label submission has no completion event\n");
}
const auto status =
vkGetEventStatus(it->completion->device, it->completion->event);
const auto status = vkGetEventStatus(it->completion->device, it->completion->event);
switch (status) {
case VK_EVENT_SET:
fired_labels.push_back(it->callbacks);
@@ -180,35 +162,9 @@ void LabelManager::ThreadRun(void* data) {
for (auto& label: fired_labels) {
LabelCallbackScope callback_scope;
bool write = true;
if (label.callback_1 != nullptr) {
write = label.callback_1(label.args);
}
if (write && label.dst_gpu_addr64 != nullptr) {
// Publishing EOP fences through physical backing keeps a fence word coherent even
// when unrelated bytes on its host page are
// protected for BufferCache GPU ownership.
WriteGuestLabel(label.dst_gpu_addr64, label.value64);
static std::atomic<uint32_t> log_count {0};
if (log_count.fetch_add(1) < 256) {
LOGF_COLOR(Log::Color::BrightGreen,
"EndOfPipe Signal!!! [0x%016" PRIx64 "] <- 0x%016" PRIx64 "\n",
reinterpret_cast<uint64_t>(label.dst_gpu_addr64), label.value64);
}
}
if (write && label.dst_gpu_addr32 != nullptr) {
WriteGuestLabel(label.dst_gpu_addr32, label.value32);
static std::atomic<uint32_t> log_count {0};
if (log_count.fetch_add(1) < 256) {
LOGF_COLOR(Log::Color::BrightGreen,
"EndOfPipe Signal!!! [0x%016" PRIx64 "] <- 0x%08" PRIx32 "\n",
reinterpret_cast<uint64_t>(label.dst_gpu_addr32), label.value32);
}
(void)label.callback_1(label.args);
}
if (label.callback_2 != nullptr) {
@@ -229,29 +185,15 @@ void LabelManager::ThreadRun(void* data) {
}
}
template <typename T>
Label* LabelManager::Create(GraphicContext* ctx, T* dst_gpu_addr, T value, LabelCallback callback_1,
LabelCallback callback_2, const uint64_t* args) {
static_assert(sizeof(T) == sizeof(uint32_t) || sizeof(T) == sizeof(uint64_t));
Label* LabelManager::Create(GraphicContext* ctx, LabelCallback callback_1, LabelCallback callback_2,
const uint64_t* args) {
EXIT_IF(ctx == nullptr);
Common::LockGuard lock(m_mutex);
auto* label = new Label;
label->status = LabelStatus::New;
if constexpr (sizeof(T) == sizeof(uint64_t)) {
label->callbacks.dst_gpu_addr64 = dst_gpu_addr;
label->callbacks.value64 = value;
label->callbacks.dst_gpu_addr32 = nullptr;
label->callbacks.value32 = 0;
} else {
label->callbacks.dst_gpu_addr32 = dst_gpu_addr;
label->callbacks.value32 = value;
label->callbacks.dst_gpu_addr64 = nullptr;
label->callbacks.value64 = 0;
}
label->status = LabelStatus::New;
label->device = ctx->device;
label->callbacks.callback_1 = callback_1;
label->callbacks.callback_2 = callback_2;
@@ -267,18 +209,6 @@ Label* LabelManager::Create(GraphicContext* ctx, T* dst_gpu_addr, T value, Label
return label;
}
Label* LabelManager::Create64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value,
LabelCallback callback_1, LabelCallback callback_2,
const uint64_t* args) {
return Create(ctx, dst_gpu_addr, value, callback_1, callback_2, args);
}
Label* LabelManager::Create32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value,
LabelCallback callback_1, LabelCallback callback_2,
const uint64_t* args) {
return Create(ctx, dst_gpu_addr, value, callback_1, callback_2, args);
}
bool LabelManager::Remove(Label* label) {
EXIT_IF(label == nullptr);
EXIT_IF(label->device == nullptr);
@@ -336,8 +266,8 @@ void LabelManager::Set(CommandBuffer* buffer, Label* label) {
label->status = LabelStatus::Active;
LabelSubmission submission {};
submission.callbacks = label->callbacks;
submission.completion = std::make_shared<LabelEvent>();
submission.callbacks = label->callbacks;
submission.completion = std::make_shared<LabelEvent>();
submission.completion->device = label->device;
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
@@ -385,18 +315,11 @@ void LabelInit() {
g_label_manager = new LabelManager;
}
Label* LabelCreate64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value,
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args) {
Label* LabelCreate(GraphicContext* ctx, LabelCallback callback_1, LabelCallback callback_2,
const uint64_t* args) {
EXIT_IF(g_label_manager == nullptr);
return g_label_manager->Create64(ctx, dst_gpu_addr, value, callback_1, callback_2, args);
}
Label* LabelCreate32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value,
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args) {
EXIT_IF(g_label_manager == nullptr);
return g_label_manager->Create32(ctx, dst_gpu_addr, value, callback_1, callback_2, args);
return g_label_manager->Create(ctx, callback_1, callback_2, args);
}
void LabelDelete(Label* label) {
@@ -416,15 +339,6 @@ void LabelDrain() {
g_label_manager->Drain();
}
void LabelWriteGuestMemory(void* address, const void* data, uint64_t size) {
if (address == nullptr || data == nullptr || size == 0) {
EXIT("invalid guest label write\n");
}
if (!Libs::LibKernel::Memory::TryWriteBacking(reinterpret_cast<uint64_t>(address), data, size)) {
std::memcpy(address, data, static_cast<size_t>(size));
}
}
bool LabelInCallback() noexcept {
return g_in_label_callback;
}
+2 -5
View File
@@ -15,14 +15,11 @@ void LabelInit();
constexpr int LABEL_ARGS_MAX = 5;
using LabelCallback = bool (*)(const uint64_t* args);
Label* LabelCreate64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value,
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args);
Label* LabelCreate32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value,
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args);
Label* LabelCreate(GraphicContext* ctx, LabelCallback callback_1, LabelCallback callback_2,
const uint64_t* args);
void LabelDelete(Label* label);
void LabelSet(CommandBuffer* buffer, Label* label);
void LabelDrain();
void LabelWriteGuestMemory(void* address, const void* data, uint64_t size);
[[nodiscard]] bool LabelInCallback() noexcept;
} // namespace Libs::Graphics