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.
This commit is contained in:
Connor McLaughlin 2020-09-01 12:02:29 +10:00
parent e21fc9e253
commit dd0ae0fc9d
2 changed files with 9 additions and 19 deletions

View file

@ -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

View file

@ -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;