diff --git a/rpcs3/Emu/RSX/VK/VKDMA.cpp b/rpcs3/Emu/RSX/VK/VKDMA.cpp index bed73f70b9..455b4ef79b 100644 --- a/rpcs3/Emu/RSX/VK/VKDMA.cpp +++ b/rpcs3/Emu/RSX/VK/VKDMA.cpp @@ -359,6 +359,40 @@ namespace vk return block_head->get(map_range); } + void unmap_dma(u32 local_address, u32 length) + { + std::lock_guard lock(g_dma_mutex); + + const u32 start = (local_address & s_dma_block_mask); + const u32 end = utils::align(local_address + length, s_dma_block_length); + + for (u32 block = start; block < end;) + { + if (auto found = g_dma_pool.find(block); found != g_dma_pool.end()) + { + auto head = found->second->head(); + if (dynamic_cast(head)) + { + // Passthrough block. Must unmap from GPU + const u32 start_block = head->start(); + const u32 last_block = head->start() + head->size(); + + for (u32 block_ = start_block; block_ < last_block; block_ += s_dma_block_length) + { + g_dma_pool.erase(block_); + } + + block = last_block; + continue; + } + } + + block += s_dma_block_length; + } + + ensure(s_allocated_dma_pool_size == g_dma_pool.size() * s_dma_block_length); + } + template void sync_dma_impl(u32 local_address, u32 length) { diff --git a/rpcs3/Emu/RSX/VK/VKDMA.h b/rpcs3/Emu/RSX/VK/VKDMA.h index c0f0789f9a..e265283bb6 100644 --- a/rpcs3/Emu/RSX/VK/VKDMA.h +++ b/rpcs3/Emu/RSX/VK/VKDMA.h @@ -7,6 +7,7 @@ namespace vk std::pair map_dma(const command_buffer& cmd, u32 local_address, u32 length); void load_dma(u32 local_address, u32 length); void flush_dma(u32 local_address, u32 length); + void unmap_dma(u32 local_address, u32 length); void clear_dma_resources(); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index d05f720fd9..2a6f083241 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -738,13 +738,18 @@ void VKGSRender::on_invalidate_memory_range(const utils::address_range &range, r auto data = std::move(m_texture_cache.invalidate_range(m_secondary_command_buffer, range, cause)); AUDIT(data.empty()); - if (cause == rsx::invalidation_cause::unmap && data.violation_handled) + if (cause == rsx::invalidation_cause::unmap) { - m_texture_cache.purge_unreleased_sections(); + if (data.violation_handled) { - std::lock_guard lock(m_sampler_mutex); - m_samplers_dirty.store(true); + m_texture_cache.purge_unreleased_sections(); + { + std::lock_guard lock(m_sampler_mutex); + m_samplers_dirty.store(true); + } } + + vk::unmap_dma(range.start, range.length()); } }