From fd2680d8b4830c312599d3579b0eb02ebf1903b8 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Thu, 1 Sep 2022 22:18:55 -0500 Subject: [PATCH] VideoBackends:Metal: Use a temporary buffer for large texture uploads --- Source/Core/VideoBackends/Metal/MTLTexture.mm | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/Metal/MTLTexture.mm b/Source/Core/VideoBackends/Metal/MTLTexture.mm index 7e1ec73f78..52a857f5d8 100644 --- a/Source/Core/VideoBackends/Metal/MTLTexture.mm +++ b/Source/Core/VideoBackends/Metal/MTLTexture.mm @@ -51,6 +51,10 @@ void Metal::Texture::ResolveFromTexture(const AbstractTexture* src, g_state_tracker->ResolveTexture(src_tex, m_tex, layer, level); } +// Use a temporary texture for large texture loads +// (Since the main upload buffer doesn't shrink after it grows) +static constexpr u32 STAGING_TEXTURE_UPLOAD_THRESHOLD = 1024 * 1024 * 4; + void Metal::Texture::Load(u32 level, u32 width, u32 height, u32 row_length, // const u8* buffer, size_t buffer_size) { @@ -60,7 +64,23 @@ void Metal::Texture::Load(u32 level, u32 width, u32 height, u32 row_length, // const u32 num_rows = Common::AlignUp(height, block_size) / block_size; const u32 source_pitch = CalculateStrideForFormat(m_config.format, row_length); const u32 upload_size = source_pitch * num_rows; - StateTracker::Map map = g_state_tracker->AllocateForTextureUpload(upload_size); + MRCOwned> tmp_buffer; + StateTracker::Map map; + if (upload_size > STAGING_TEXTURE_UPLOAD_THRESHOLD) + { + tmp_buffer = MRCTransfer([g_device + newBufferWithLength:upload_size + options:MTLResourceStorageModeShared | MTLResourceCPUCacheModeWriteCombined]); + [tmp_buffer setLabel:@"Temp Texture Upload"]; + map.gpu_buffer = tmp_buffer; + map.gpu_offset = 0; + map.cpu_buffer = [tmp_buffer contents]; + } + else + { + map = g_state_tracker->AllocateForTextureUpload(upload_size); + } + memcpy(map.cpu_buffer, buffer, upload_size); id encoder = g_state_tracker->GetTextureUploadEncoder(); [encoder copyFromBuffer:map.gpu_buffer