buffer_cache: Make ReadMemory thread-safe

This commit is contained in:
IndecisiveTurtle 2025-06-23 18:52:42 +03:00
parent bc148d0701
commit ec6fc48049
4 changed files with 38 additions and 20 deletions

View File

@ -73,6 +73,20 @@ Liverpool::~Liverpool() {
process_thread.join(); process_thread.join();
} }
void Liverpool::ProcessCommands() {
// Process incoming commands with high priority
while (num_commands) {
Common::UniqueFunction<void> callback{};
{
std::unique_lock lk{submit_mutex};
callback = std::move(command_queue.front());
command_queue.pop();
--num_commands;
}
callback();
}
}
void Liverpool::Process(std::stop_token stoken) { void Liverpool::Process(std::stop_token stoken) {
Common::SetCurrentThreadName("shadPS4:GpuCommandProcessor"); Common::SetCurrentThreadName("shadPS4:GpuCommandProcessor");
@ -91,18 +105,7 @@ void Liverpool::Process(std::stop_token stoken) {
curr_qid = -1; curr_qid = -1;
while (num_submits || num_commands) { while (num_submits || num_commands) {
ProcessCommands();
// Process incoming commands with high priority
while (num_commands) {
Common::UniqueFunction<void> callback{};
{
std::unique_lock lk{submit_mutex};
callback = std::move(command_queue.front());
command_queue.pop();
--num_commands;
}
callback();
}
curr_qid = (curr_qid + 1) % num_mapped_queues; curr_qid = (curr_qid + 1) % num_mapped_queues;
@ -148,6 +151,8 @@ Liverpool::Task Liverpool::ProcessCeUpdate(std::span<const u32> ccb) {
FIBER_ENTER(ccb_task_name); FIBER_ENTER(ccb_task_name);
while (!ccb.empty()) { while (!ccb.empty()) {
ProcessCommands();
const auto* header = reinterpret_cast<const PM4Header*>(ccb.data()); const auto* header = reinterpret_cast<const PM4Header*>(ccb.data());
const u32 type = header->type; const u32 type = header->type;
if (type != 3) { if (type != 3) {
@ -228,6 +233,8 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
const auto* header = reinterpret_cast<const PM4Header*>(dcb.data()); const auto* header = reinterpret_cast<const PM4Header*>(dcb.data());
const u32 type = header->type; const u32 type = header->type;
ProcessCommands();
switch (type) { switch (type) {
default: default:
UNREACHABLE_MSG("Wrong PM4 type {}", type); UNREACHABLE_MSG("Wrong PM4 type {}", type);
@ -815,6 +822,8 @@ Liverpool::Task Liverpool::ProcessCompute(const u32* acb, u32 acb_dwords, u32 vq
auto base_addr = reinterpret_cast<VAddr>(acb); auto base_addr = reinterpret_cast<VAddr>(acb);
while (acb_dwords > 0) { while (acb_dwords > 0) {
ProcessCommands();
auto* header = reinterpret_cast<const PM4Header*>(acb); auto* header = reinterpret_cast<const PM4Header*>(acb);
u32 next_dw_off = header->type3.NumWords() + 1; u32 next_dw_off = header->type3.NumWords() + 1;

View File

@ -1587,6 +1587,7 @@ private:
template <bool is_indirect = false> template <bool is_indirect = false>
Task ProcessCompute(const u32* acb, u32 acb_dwords, u32 vqid); Task ProcessCompute(const u32* acb, u32 acb_dwords, u32 vqid);
void ProcessCommands();
void Process(std::stop_token stoken); void Process(std::stop_token stoken);
struct GpuQueue { struct GpuQueue {

View File

@ -140,6 +140,11 @@ void BufferCache::InvalidateMemory(VAddr device_addr, u64 size) {
} }
void BufferCache::ReadMemory(VAddr device_addr, u64 size) { void BufferCache::ReadMemory(VAddr device_addr, u64 size) {
if (!memory_tracker.IsRegionGpuModified(device_addr, size)) {
return;
}
std::binary_semaphore sem{0};
liverpool->SendCommand([this, &sem, device_addr, size] {
ForEachBufferInRange(device_addr, size, [this, device_addr, size](BufferId buffer_id, Buffer& buffer) { ForEachBufferInRange(device_addr, size, [this, device_addr, size](BufferId buffer_id, Buffer& buffer) {
const VAddr buffer_start = buffer.CpuAddr(); const VAddr buffer_start = buffer.CpuAddr();
const VAddr buffer_end = buffer_start + buffer.SizeBytes(); const VAddr buffer_end = buffer_start + buffer.SizeBytes();
@ -148,6 +153,9 @@ void BufferCache::ReadMemory(VAddr device_addr, u64 size) {
const u64 download_size = download_end - download_start; const u64 download_size = download_end - download_start;
DownloadBufferMemory(buffer, download_start, download_size); DownloadBufferMemory(buffer, download_start, download_size);
}); });
sem.release();
});
sem.acquire();
} }
void BufferCache::DownloadBufferMemory(const Buffer& buffer, VAddr device_addr, u64 size) { void BufferCache::DownloadBufferMemory(const Buffer& buffer, VAddr device_addr, u64 size) {

View File

@ -488,7 +488,7 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) {
uses_dma |= stage->dma_types != Shader::IR::Type::Void; uses_dma |= stage->dma_types != Shader::IR::Type::Void;
} }
if (uses_dma && !fault_process_pending) { if (uses_dma) {
// We only use fault buffer for DMA right now. // We only use fault buffer for DMA right now.
{ {
// TODO: GPU might have written to memory (for example with EVENT_WRITE_EOP) // TODO: GPU might have written to memory (for example with EVENT_WRITE_EOP)