buffer_cache: Backing memory write fixes

This commit is contained in:
IndecisiveTurtle 2025-06-23 12:02:34 +03:00
parent e580073430
commit f03d0c841e
4 changed files with 31 additions and 22 deletions

View File

@ -135,16 +135,25 @@ void MemoryManager::CopySparseMemory(VAddr virtual_addr, u8* dest, u64 size) {
} }
} }
bool MemoryManager::TryWriteBacking(void* address, const void* data, u32 num_bytes) { bool MemoryManager::TryWriteBacking(void* address, const void* data, u32 size) {
const VAddr virtual_addr = std::bit_cast<VAddr>(address); VAddr virtual_addr = std::bit_cast<VAddr>(address);
const auto& vma = FindVMA(virtual_addr)->second; const u8* src_data = std::bit_cast<const u8*>(data);
ASSERT_MSG(vma.Contains(virtual_addr, num_bytes), auto vma = FindVMA(virtual_addr);
ASSERT_MSG(vma->second.Contains(virtual_addr, 0),
"Attempting to access out of bounds memory at address {:#x}", virtual_addr); "Attempting to access out of bounds memory at address {:#x}", virtual_addr);
if (vma.type != VMAType::Direct) { while (size) {
if (vma->second.type != VMAType::Direct) {
return false; return false;
} }
u8* backing = impl.BackingBase() + vma.phys_base + (virtual_addr - vma.base); const u64 offset_in_vma = virtual_addr - vma->first;
memcpy(backing, data, num_bytes); u64 copy_size = std::min<u64>(vma->second.size - offset_in_vma, size);
u8* backing = impl.BackingBase() + vma->second.phys_base + offset_in_vma;
std::memcpy(backing, src_data, copy_size);
size -= copy_size;
virtual_addr += copy_size;
src_data += copy_size;
++vma;
}
return true; return true;
} }

View File

@ -6,7 +6,6 @@
#include "common/alignment.h" #include "common/alignment.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/div_ceil.h" #include "common/div_ceil.h"
#include "common/scope_exit.h"
#include "common/types.h" #include "common/types.h"
#include "core/memory.h" #include "core/memory.h"
#include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/liverpool.h"
@ -183,8 +182,10 @@ void BufferCache::DownloadBufferMemory(const Buffer& buffer, VAddr device_addr,
for (const auto& copy : copies) { for (const auto& copy : copies) {
const VAddr copy_device_addr = buffer.CpuAddr() + copy.srcOffset; const VAddr copy_device_addr = buffer.CpuAddr() + copy.srcOffset;
const u64 dst_offset = copy.dstOffset - offset; const u64 dst_offset = copy.dstOffset - offset;
ASSERT(memory->TryWriteBacking(std::bit_cast<u8*>(copy_device_addr), download + dst_offset, if (!memory->TryWriteBacking(std::bit_cast<u8*>(copy_device_addr), download + dst_offset,
copy.size)); copy.size)) {
std::memcpy(std::bit_cast<u8*>(copy_device_addr), download + dst_offset, copy.size);
}
} }
} }
@ -249,8 +250,10 @@ bool BufferCache::CommitPendingDownloads(bool wait_done) {
for (auto& copy : buffer_copies) { for (auto& copy : buffer_copies) {
const VAddr copy_device_addr = buffer.CpuAddr() + copy.srcOffset; const VAddr copy_device_addr = buffer.CpuAddr() + copy.srcOffset;
const u64 dst_offset = copy.dstOffset - offset; const u64 dst_offset = copy.dstOffset - offset;
ASSERT(memory->TryWriteBacking(std::bit_cast<u8*>(copy_device_addr), if (!memory->TryWriteBacking(std::bit_cast<u8*>(copy_device_addr),
download + dst_offset, copy.size)); download + dst_offset, copy.size)) {
std::memcpy(std::bit_cast<u8*>(copy_device_addr), download + dst_offset, copy.size);
}
} }
} }
}); });

View File

@ -4,6 +4,7 @@
#include "common/config.h" #include "common/config.h"
#include "common/debug.h" #include "common/debug.h"
#include "core/memory.h" #include "core/memory.h"
#include "common/scope_exit.h"
#include "shader_recompiler/runtime_info.h" #include "shader_recompiler/runtime_info.h"
#include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/liverpool.h"
#include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_instance.h"
@ -61,7 +62,9 @@ void Rasterizer::CpSync() {
} }
bool Rasterizer::CommitPendingDownloads(bool wait_done) { bool Rasterizer::CommitPendingDownloads(bool wait_done) {
SCOPE_EXIT {
scheduler.PopPendingOperations(); scheduler.PopPendingOperations();
};
return buffer_cache.CommitPendingDownloads(wait_done); return buffer_cache.CommitPendingDownloads(wait_done);
} }
@ -485,8 +488,6 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) {
uses_dma |= stage->dma_types != Shader::IR::Type::Void; uses_dma |= stage->dma_types != Shader::IR::Type::Void;
} }
pipeline->BindResources(set_writes, buffer_barriers, push_data);
if (uses_dma && !fault_process_pending) { if (uses_dma && !fault_process_pending) {
// We only use fault buffer for DMA right now. // We only use fault buffer for DMA right now.
{ {
@ -503,6 +504,8 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) {
fault_process_pending |= uses_dma; fault_process_pending |= uses_dma;
pipeline->BindResources(set_writes, buffer_barriers, push_data);
return true; return true;
} }

View File

@ -98,12 +98,6 @@ void Scheduler::Wait(u64 tick) {
Flush(info); Flush(info);
} }
master_semaphore.Wait(tick); master_semaphore.Wait(tick);
// CAUTION: This can introduce unexpected variation in the wait time.
// We don't currently sync the GPU, and some games are very sensitive to this.
// If this becomes a problem, it can be commented out.
// Idealy we would implement proper gpu sync.
PopPendingOperations();
} }
void Scheduler::AllocateWorkerCommandBuffers() { void Scheduler::AllocateWorkerCommandBuffers() {