diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 02bef9626..af4ff5447 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -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) { - const VAddr virtual_addr = std::bit_cast(address); - const auto& vma = FindVMA(virtual_addr)->second; - ASSERT_MSG(vma.Contains(virtual_addr, num_bytes), +bool MemoryManager::TryWriteBacking(void* address, const void* data, u32 size) { + VAddr virtual_addr = std::bit_cast(address); + const u8* src_data = std::bit_cast(data); + 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); - if (vma.type != VMAType::Direct) { - return false; + while (size) { + if (vma->second.type != VMAType::Direct) { + return false; + } + const u64 offset_in_vma = virtual_addr - vma->first; + u64 copy_size = std::min(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; } - u8* backing = impl.BackingBase() + vma.phys_base + (virtual_addr - vma.base); - memcpy(backing, data, num_bytes); return true; } diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 54d516e71..d16c64064 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -6,7 +6,6 @@ #include "common/alignment.h" #include "common/debug.h" #include "common/div_ceil.h" -#include "common/scope_exit.h" #include "common/types.h" #include "core/memory.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) { const VAddr copy_device_addr = buffer.CpuAddr() + copy.srcOffset; const u64 dst_offset = copy.dstOffset - offset; - ASSERT(memory->TryWriteBacking(std::bit_cast(copy_device_addr), download + dst_offset, - copy.size)); + if (!memory->TryWriteBacking(std::bit_cast(copy_device_addr), download + dst_offset, + copy.size)) { + std::memcpy(std::bit_cast(copy_device_addr), download + dst_offset, copy.size); + } } } @@ -249,8 +250,10 @@ bool BufferCache::CommitPendingDownloads(bool wait_done) { for (auto& copy : buffer_copies) { const VAddr copy_device_addr = buffer.CpuAddr() + copy.srcOffset; const u64 dst_offset = copy.dstOffset - offset; - ASSERT(memory->TryWriteBacking(std::bit_cast(copy_device_addr), - download + dst_offset, copy.size)); + if (!memory->TryWriteBacking(std::bit_cast(copy_device_addr), + download + dst_offset, copy.size)) { + std::memcpy(std::bit_cast(copy_device_addr), download + dst_offset, copy.size); + } } } }); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index b3a2a53ba..e16d12810 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -4,6 +4,7 @@ #include "common/config.h" #include "common/debug.h" #include "core/memory.h" +#include "common/scope_exit.h" #include "shader_recompiler/runtime_info.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/renderer_vulkan/vk_instance.h" @@ -61,7 +62,9 @@ void Rasterizer::CpSync() { } bool Rasterizer::CommitPendingDownloads(bool wait_done) { - scheduler.PopPendingOperations(); + SCOPE_EXIT { + scheduler.PopPendingOperations(); + }; 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; } - pipeline->BindResources(set_writes, buffer_barriers, push_data); - if (uses_dma && !fault_process_pending) { // We only use fault buffer for DMA right now. { @@ -503,6 +504,8 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) { fault_process_pending |= uses_dma; + pipeline->BindResources(set_writes, buffer_barriers, push_data); + return true; } diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index a7f9b65ff..c4f781cf2 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -98,12 +98,6 @@ void Scheduler::Wait(u64 tick) { Flush(info); } 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() {