|
|
@@ -314,17 +314,29 @@ void MemoryManager::WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buf
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void MemoryManager::FlushRegion(GPUVAddr gpu_addr, size_t size) const {
|
|
|
+ size_t remaining_size{size};
|
|
|
+ size_t page_index{gpu_addr >> page_bits};
|
|
|
+ size_t page_offset{gpu_addr & page_mask};
|
|
|
+ while (remaining_size > 0) {
|
|
|
+ const size_t num_bytes{std::min(page_size - page_offset, remaining_size)};
|
|
|
+ if (const auto page_addr{GpuToCpuAddress(page_index << page_bits)}; page_addr) {
|
|
|
+ rasterizer->FlushRegion(*page_addr + page_offset, num_bytes);
|
|
|
+ }
|
|
|
+ ++page_index;
|
|
|
+ page_offset = 0;
|
|
|
+ remaining_size -= num_bytes;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void MemoryManager::CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std::size_t size) {
|
|
|
std::vector<u8> tmp_buffer(size);
|
|
|
ReadBlock(gpu_src_addr, tmp_buffer.data(), size);
|
|
|
- WriteBlock(gpu_dest_addr, tmp_buffer.data(), size);
|
|
|
-}
|
|
|
|
|
|
-void MemoryManager::CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr,
|
|
|
- std::size_t size) {
|
|
|
- std::vector<u8> tmp_buffer(size);
|
|
|
- ReadBlockUnsafe(gpu_src_addr, tmp_buffer.data(), size);
|
|
|
- WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size);
|
|
|
+ // The output block must be flushed in case it has data modified from the GPU.
|
|
|
+ // Fixes NPC geometry in Zombie Panic in Wonderland DX
|
|
|
+ FlushRegion(gpu_dest_addr, size);
|
|
|
+ WriteBlock(gpu_dest_addr, tmp_buffer.data(), size);
|
|
|
}
|
|
|
|
|
|
bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const {
|