From dd0ae0fc9d7a39584d0af22d70840c3e3cb4d29b Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Tue, 1 Sep 2020 12:02:29 +1000 Subject: [PATCH] Vulkan/StagingTexture: Keep mapped throughout transfers The underlying bug here was not invalidating the buffer after mapping (is this supposed to be necessary?). But by keeping it mapped, we invalidate it anyway. Fixes screen corruption in Final Fantasy IX on Mali GPUs. --- src/common/vulkan/staging_texture.cpp | 26 ++++++++------------------ src/common/vulkan/staging_texture.h | 2 +- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/common/vulkan/staging_texture.cpp b/src/common/vulkan/staging_texture.cpp index 0403a1164..e9b62d598 100644 --- a/src/common/vulkan/staging_texture.cpp +++ b/src/common/vulkan/staging_texture.cpp @@ -209,10 +209,8 @@ void StagingTexture::Flush() void StagingTexture::ReadTexels(u32 src_x, u32 src_y, u32 width, u32 height, void* out_ptr, u32 out_stride) { Assert(m_staging_buffer.GetType() != StagingBuffer::Type::Upload); - if (!PrepareForAccess()) - return; - Assert((src_x + width) <= m_width && (src_y + height) <= m_height); + PrepareForAccess(); // Offset pointer to point to start of region being copied out. const char* current_ptr = m_staging_buffer.GetMapPointer(); @@ -239,10 +237,9 @@ void StagingTexture::ReadTexels(u32 src_x, u32 src_y, u32 width, u32 height, voi void StagingTexture::ReadTexel(u32 x, u32 y, void* out_ptr) { Assert(m_staging_buffer.GetType() != StagingBuffer::Type::Upload); - if (!PrepareForAccess()) - return; - Assert(x < m_width && y < m_height); + PrepareForAccess(); + const char* src_ptr = GetMappedPointer() + y * GetMappedStride() + x * m_texel_size; std::memcpy(out_ptr, src_ptr, m_texel_size); } @@ -250,10 +247,8 @@ void StagingTexture::ReadTexel(u32 x, u32 y, void* out_ptr) void StagingTexture::WriteTexels(u32 dst_x, u32 dst_y, u32 width, u32 height, const void* in_ptr, u32 in_stride) { Assert(m_staging_buffer.GetType() != StagingBuffer::Type::Readback); - if (!PrepareForAccess()) - return; - Assert((dst_x + width) <= m_width && (dst_y + height) <= m_height); + PrepareForAccess(); // Offset pointer to point to start of region being copied to. char* current_ptr = GetMappedPointer(); @@ -279,23 +274,18 @@ void StagingTexture::WriteTexels(u32 dst_x, u32 dst_y, u32 width, u32 height, co void StagingTexture::WriteTexel(u32 x, u32 y, const void* in_ptr) { - if (!PrepareForAccess()) - return; - Assert(x < m_width && y < m_height); + PrepareForAccess(); + char* dest_ptr = GetMappedPointer() + y * m_map_stride + x * m_texel_size; std::memcpy(dest_ptr, in_ptr, m_texel_size); } -bool StagingTexture::PrepareForAccess() +void StagingTexture::PrepareForAccess() { + Assert(IsMapped()); if (m_needs_flush) - { - if (IsMapped()) - Unmap(); Flush(); - } - return IsMapped() || Map(); } } // namespace Vulkan \ No newline at end of file diff --git a/src/common/vulkan/staging_texture.h b/src/common/vulkan/staging_texture.h index 7f03e04dd..f8d24836f 100644 --- a/src/common/vulkan/staging_texture.h +++ b/src/common/vulkan/staging_texture.h @@ -73,7 +73,7 @@ public: void WriteTexel(u32 x, u32 y, const void* in_ptr); private: - bool PrepareForAccess(); + void PrepareForAccess(); StagingBuffer m_staging_buffer; u64 m_flush_fence_counter = 0;