From 59e46f09b785470fc05d2d323fe3493100406225 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 29 Dec 2020 22:53:08 +0300 Subject: [PATCH] vk/dma: Disable memory inheritance - It is not possible to emulate passthrough memory cleanly, and we don't need to A stupid race condition appears when trying to synchronize DMA blocks with memory inheritance. Since the usage pattern is to acquire a range and then load or write+flush, this new data is going to be.. overwritten by the commandbuffer execution sequence later. Acquiring a scratch buffer to hold CPU content during the transition is not worth the effort.. as the data will be destroyed anyway during the transfer process immediately afterwards. Fixes data corruption when moving data around using the emulated DMA passthrough --- rpcs3/Emu/RSX/VK/VKDMA.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKDMA.cpp b/rpcs3/Emu/RSX/VK/VKDMA.cpp index 1e13291416..8e476bd647 100644 --- a/rpcs3/Emu/RSX/VK/VKDMA.cpp +++ b/rpcs3/Emu/RSX/VK/VKDMA.cpp @@ -192,12 +192,8 @@ namespace vk if (allocated_memory) { - VkBufferCopy copy{}; - copy.srcOffset = 0; - copy.dstOffset = inheritance_info.block_offset; - copy.size = allocated_memory->size(); - vkCmdCopyBuffer(cmd, allocated_memory->value, parent->allocated_memory->value, 1, ©); - + // Acquired blocks are always to be assumed dirty. It is not possible to synchronize host access and inline + // buffer copies without causing weird issues. Overlapped incomplete data ends up overwriting host-uploaded data. auto gc = vk::get_resource_manager(); gc->dispose(allocated_memory); @@ -219,10 +215,8 @@ namespace vk dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0); - VkBufferCopy copy{}; - copy.size = allocated_memory->size(); - vkCmdCopyBuffer(cmd, allocated_memory->value, new_allocation->value, 1, ©); - + // Acquired blocks are always to be assumed dirty. It is not possible to synchronize host access and inline + // buffer copies without causing weird issues. Overlapped incomplete data ends up overwriting host-uploaded data. auto gc = vk::get_resource_manager(); gc->dispose(allocated_memory); allocated_memory = std::move(new_allocation); @@ -251,13 +245,16 @@ namespace vk const auto limit = local_address + length - 1; auto last_block = (limit & s_dma_block_mask); - if (first_block == last_block) [[likely]] + if (auto found = g_dma_pool.find(first_block); found != g_dma_pool.end()) { - if (auto found = g_dma_pool.find(first_block); found != g_dma_pool.end()) + if (found->second.end() >= limit) { return found->second.get(map_range); } + } + if (first_block == last_block) [[likely]] + { auto &block_info = g_dma_pool[first_block]; block_info.init(*g_render_device, first_block, s_dma_block_length); return block_info.get(map_range); @@ -274,6 +271,7 @@ namespace vk const auto end = found->second.end(); last_block = std::max(last_block, end & s_dma_block_mask); block_end = std::max(block_end, end + 1); + break; } }