From db09c05eecac461f33751c824546d12a46173945 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 4 Oct 2016 22:25:35 +1000 Subject: [PATCH] Vulkan: Fix bug with palette converted EFB copies This happened when the source texture was an EFB copy, therefore it had not been populated prior to the draw command buffer being executed, and the conversion was occurring in the init command list. --- .../Vulkan/PaletteTextureConverter.cpp | 19 +++++++++-------- .../Vulkan/PaletteTextureConverter.h | 7 ++++--- .../VideoBackends/Vulkan/TextureCache.cpp | 21 +++++++++++++++++-- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/PaletteTextureConverter.cpp b/Source/Core/VideoBackends/Vulkan/PaletteTextureConverter.cpp index f67ed33b28..b9a135cd7e 100644 --- a/Source/Core/VideoBackends/Vulkan/PaletteTextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/PaletteTextureConverter.cpp @@ -62,7 +62,9 @@ bool PaletteTextureConverter::Initialize() return true; } -void PaletteTextureConverter::ConvertTexture(StateTracker* state_tracker, VkRenderPass render_pass, +void PaletteTextureConverter::ConvertTexture(StateTracker* state_tracker, + VkCommandBuffer command_buffer, + VkRenderPass render_pass, VkFramebuffer dst_framebuffer, Texture2D* src_texture, u32 width, u32 height, void* palette, TlutFormat format) @@ -113,14 +115,14 @@ void PaletteTextureConverter::ConvertTexture(StateTracker* state_tracker, VkRend &m_palette_buffer_view}; vkUpdateDescriptorSets(g_vulkan_context->GetDevice(), 1, &texel_set_write, 0, nullptr); - Util::BufferMemoryBarrier(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), - m_palette_stream_buffer->GetBuffer(), VK_ACCESS_HOST_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT, palette_offset, palette_size, - VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + Util::BufferMemoryBarrier(command_buffer, m_palette_stream_buffer->GetBuffer(), + VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, palette_offset, + palette_size, VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); // Set up draw - UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), m_pipeline_layout, - render_pass, g_object_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE, + UtilityShaderDraw draw(command_buffer, m_pipeline_layout, render_pass, + g_object_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE, m_shaders[format]); VkRect2D region = {{0, 0}, {width, height}}; @@ -138,8 +140,7 @@ void PaletteTextureConverter::ConvertTexture(StateTracker* state_tracker, VkRend draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetPointSampler()); // We have to bind the texel buffer descriptor set separately. - vkCmdBindDescriptorSets(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), - VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1, + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1, &texel_buffer_descriptor_set, 0, nullptr); // Draw diff --git a/Source/Core/VideoBackends/Vulkan/PaletteTextureConverter.h b/Source/Core/VideoBackends/Vulkan/PaletteTextureConverter.h index 537b029595..e611e65b84 100644 --- a/Source/Core/VideoBackends/Vulkan/PaletteTextureConverter.h +++ b/Source/Core/VideoBackends/Vulkan/PaletteTextureConverter.h @@ -26,9 +26,10 @@ public: bool Initialize(); - void ConvertTexture(StateTracker* state_tracker, VkRenderPass render_pass, - VkFramebuffer dst_framebuffer, Texture2D* src_texture, u32 width, u32 height, - void* palette, TlutFormat format); + void ConvertTexture(StateTracker* state_tracker, VkCommandBuffer command_buffer, + VkRenderPass render_pass, VkFramebuffer dst_framebuffer, + Texture2D* src_texture, u32 width, u32 height, void* palette, + TlutFormat format); private: static const size_t NUM_PALETTE_CONVERSION_SHADERS = 3; diff --git a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp index 4b83a76b59..1a882716ce 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp @@ -92,9 +92,26 @@ void TextureCache::ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase* TCacheEntry* unconverted = static_cast(base_unconverted); _assert_(entry->config.rendertarget); + // EFB copies can be used as paletted textures as well. For these, we can't assume them to be + // contain the correct data before the frame begins (when the init command buffer is executed), + // so we must convert them at the appropriate time, during the drawing command buffer. + VkCommandBuffer command_buffer; + if (unconverted->IsEfbCopy()) + { + command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); + m_state_tracker->EndRenderPass(); + m_state_tracker->SetPendingRebind(); + } + else + { + // Use initialization command buffer and perform conversion before the drawing commands. + command_buffer = g_command_buffer_mgr->GetCurrentInitCommandBuffer(); + } + m_palette_texture_converter->ConvertTexture( - m_state_tracker, GetRenderPassForTextureUpdate(entry->GetTexture()), entry->GetFramebuffer(), - unconverted->GetTexture(), entry->config.width, entry->config.height, palette, format); + m_state_tracker, command_buffer, GetRenderPassForTextureUpdate(entry->GetTexture()), + entry->GetFramebuffer(), unconverted->GetTexture(), entry->config.width, entry->config.height, + palette, format); // Render pass transitions to SHADER_READ_ONLY. entry->GetTexture()->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);