diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp index a707d8ad0e..e102be287a 100644 --- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp @@ -183,24 +183,12 @@ bool FramebufferManager::CreateEFBRenderPass() VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - // Ensure all reads have finished from the resolved texture before overwriting it. - VkSubpassDependency dependencies[] = { - {VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}, - {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}}; subpass_description.pDepthStencilAttachment = nullptr; pass_info.pAttachments = &resolve_attachment; pass_info.attachmentCount = 1; - pass_info.dependencyCount = static_cast(ArraySize(dependencies)); - pass_info.pDependencies = dependencies; res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr, &m_depth_resolve_render_pass); @@ -696,6 +684,9 @@ bool FramebufferManager::PopulateColorReadbackTexture() if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT) { + m_color_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), m_copy_color_render_pass, g_object_cache->GetScreenQuadVertexShader(), @@ -720,7 +711,6 @@ bool FramebufferManager::PopulateColorReadbackTexture() } // Use this as a source texture now. - m_color_copy_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); src_texture = m_color_copy_texture.get(); } @@ -777,6 +767,9 @@ bool FramebufferManager::PopulateDepthReadbackTexture() } if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT) { + m_depth_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), m_copy_depth_render_pass, g_object_cache->GetScreenQuadVertexShader(), @@ -801,7 +794,6 @@ bool FramebufferManager::PopulateDepthReadbackTexture() } // Use this as a source texture now. - m_depth_copy_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); src_texture = m_depth_copy_texture.get(); src_aspect = VK_IMAGE_ASPECT_COLOR_BIT; } @@ -840,15 +832,15 @@ void FramebufferManager::InvalidatePeekCache() bool FramebufferManager::CreateReadbackRenderPasses() { VkAttachmentDescription copy_attachment = { - 0, // VkAttachmentDescriptionFlags flags - EFB_COLOR_TEXTURE_FORMAT, // VkFormat format - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout initialLayout - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout + 0, // VkAttachmentDescriptionFlags flags + EFB_COLOR_TEXTURE_FORMAT, // VkFormat format + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout }; VkAttachmentReference copy_attachment_ref = { 0, // uint32_t attachment @@ -866,14 +858,6 @@ bool FramebufferManager::CreateReadbackRenderPasses() 0, // uint32_t preserveAttachmentCount nullptr // const uint32_t* pPreserveAttachments }; - VkSubpassDependency copy_dependency = { - 0, - VK_SUBPASS_EXTERNAL, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - VK_DEPENDENCY_BY_REGION_BIT}; VkRenderPassCreateInfo copy_pass = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType nullptr, // const void* pNext @@ -882,8 +866,8 @@ bool FramebufferManager::CreateReadbackRenderPasses() ©_attachment, // const VkAttachmentDescription* pAttachments 1, // uint32_t subpassCount ©_subpass, // const VkSubpassDescription* pSubpasses - 1, // uint32_t dependencyCount - ©_dependency // const VkSubpassDependency* pDependencies + 0, // uint32_t dependencyCount + nullptr // const VkSubpassDependency* pDependencies }; VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), ©_pass, nullptr, @@ -1023,12 +1007,6 @@ bool FramebufferManager::CreateReadbackTextures() return false; } - // Transition to TRANSFER_SRC, as this is expected by the render pass. - m_color_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - m_depth_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - return true; } diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 291f3e07e8..fea355341a 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -613,6 +613,9 @@ void Renderer::DrawVirtualXFB(VkRenderPass render_pass, const TargetRectangle& t for (u32 i = 0; i < xfb_count; ++i) { const XFBSource* xfb_source = static_cast(xfb_sources[i]); + xfb_source->GetTexture()->GetTexture()->TransitionToLayout( + g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + TargetRectangle source_rect = xfb_source->sourceRc; TargetRectangle draw_rect; @@ -646,6 +649,9 @@ void Renderer::DrawRealXFB(VkRenderPass render_pass, const TargetRectangle& targ for (u32 i = 0; i < xfb_count; ++i) { const XFBSource* xfb_source = static_cast(xfb_sources[i]); + xfb_source->GetTexture()->GetTexture()->TransitionToLayout( + g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + TargetRectangle source_rect = xfb_source->sourceRc; TargetRectangle draw_rect = target_rect; source_rect.right -= fb_stride - fb_width; diff --git a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp index b13e2fe4ec..78892f9fb3 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp @@ -36,10 +36,8 @@ TextureCache::TextureCache() TextureCache::~TextureCache() { - if (m_initialize_render_pass != VK_NULL_HANDLE) - vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_initialize_render_pass, nullptr); - if (m_update_render_pass != VK_NULL_HANDLE) - vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_update_render_pass, nullptr); + if (m_render_pass != VK_NULL_HANDLE) + vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_render_pass, nullptr); TextureCache::DeleteShaders(); } @@ -87,11 +85,7 @@ void TextureCache::ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase* TCacheEntry* entry = static_cast(base_entry); TCacheEntry* unconverted = static_cast(base_unconverted); - m_texture_converter->ConvertTexture( - entry, unconverted, GetRenderPassForTextureUpdate(entry->GetTexture()), palette, format); - - // Render pass transitions to SHADER_READ_ONLY. - entry->GetTexture()->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + m_texture_converter->ConvertTexture(entry, unconverted, m_render_pass, palette, format); } static bool IsDepthCopyFormat(PEControl::PixelFormat format) @@ -203,11 +197,10 @@ void TextureCache::ScaleTextureRectangle(TCacheEntry* dst_texture, src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); dst_texture->GetTexture()->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), - g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), - GetRenderPassForTextureUpdate(dst_texture->GetTexture()), + g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), m_render_pass, g_object_cache->GetPassthroughVertexShader(), g_object_cache->GetPassthroughGeometryShader(), m_copy_shader); @@ -221,9 +214,6 @@ void TextureCache::ScaleTextureRectangle(TCacheEntry* dst_texture, static_cast(src_texture->GetWidth()), static_cast(src_texture->GetHeight())); draw.EndRenderPass(); - - // Render pass transitions destination texture to SHADER_READ_ONLY. - dst_texture->GetTexture()->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConfig& config) @@ -251,7 +241,7 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, - m_initialize_render_pass, + m_render_pass, static_cast(ArraySize(framebuffer_attachments)), framebuffer_attachments, texture->GetWidth(), @@ -281,17 +271,6 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry bool TextureCache::CreateRenderPasses() { - static constexpr VkAttachmentDescription initialize_attachment = { - 0, - TEXTURECACHE_TEXTURE_FORMAT, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; - static constexpr VkAttachmentDescription update_attachment = { 0, TEXTURECACHE_TEXTURE_FORMAT, @@ -300,8 +279,8 @@ bool TextureCache::CreateRenderPasses() VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; static constexpr VkAttachmentReference color_attachment_reference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; @@ -313,36 +292,6 @@ bool TextureCache::CreateRenderPasses() nullptr, nullptr, 0, nullptr}; - static constexpr VkSubpassDependency initialize_dependancies[] = { - {VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}, - {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}}; - - static constexpr VkSubpassDependency update_dependancies[] = { - {VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}, - {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}}; - - VkRenderPassCreateInfo initialize_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - nullptr, - 0, - 1, - &initialize_attachment, - 1, - &subpass_description, - static_cast(ArraySize(initialize_dependancies)), - initialize_dependancies}; - VkRenderPassCreateInfo update_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, @@ -350,44 +299,20 @@ bool TextureCache::CreateRenderPasses() &update_attachment, 1, &subpass_description, - static_cast(ArraySize(update_dependancies)), - update_dependancies}; + 0, + nullptr}; - VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &initialize_info, nullptr, - &m_initialize_render_pass); + VkResult res = + vkCreateRenderPass(g_vulkan_context->GetDevice(), &update_info, nullptr, &m_render_pass); if (res != VK_SUCCESS) { - LOG_VULKAN_ERROR(res, "vkCreateRenderPass (initialize) failed: "); - return false; - } - - res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &update_info, nullptr, - &m_update_render_pass); - if (res != VK_SUCCESS) - { - LOG_VULKAN_ERROR(res, "vkCreateRenderPass (update) failed: "); + LOG_VULKAN_ERROR(res, "vkCreateRenderPass failed: "); return false; } return true; } -VkRenderPass TextureCache::GetRenderPassForTextureUpdate(const Texture2D* texture) const -{ - // EFB copies can be re-used as part of the texture pool. If this is the case, we need to insert - // a pipeline barrier to ensure that all reads from the texture expecting the old data have - // completed before overwriting the texture's contents. New textures will be in TRANSFER_DST - // due to the clear after creation. - - // These two render passes are compatible, so even though the framebuffer was created with - // the initialize render pass it's still allowed. - - if (texture->GetLayout() == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) - return m_initialize_render_pass; - else - return m_update_render_pass; -} - TextureCache::TCacheEntry::TCacheEntry(const TCacheEntryConfig& config_, std::unique_ptr texture, VkFramebuffer framebuffer) @@ -410,27 +335,23 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, width = std::max(1u, std::min(width, m_texture->GetWidth() >> level)); height = std::max(1u, std::min(height, m_texture->GetHeight() >> level)); - // We don't care about the existing contents of the texture, so we set the image layout to - // VK_IMAGE_LAYOUT_UNDEFINED here. However, if this texture is being re-used from the texture - // pool, it may still be in use. We assume that it's not, as non-efb-copy textures are only - // returned to the pool when the frame number is different, furthermore, we're doing this - // on the initialize command buffer, so a texture being re-used mid-frame would have undesirable - // effects regardless. - VkImageMemoryBarrier barrier = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void* pNext - 0, // VkAccessFlags srcAccessMask - VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - m_texture->GetImage(), // VkImage image - {VK_IMAGE_ASPECT_COLOR_BIT, level, 1, 0, 1}, // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); + // We don't care about the existing contents of the texture, so we could the image layout to + // VK_IMAGE_LAYOUT_UNDEFINED here. However, under section 2.2.1, Queue Operation of the Vulkan + // specification, it states: + // + // Command buffer submissions to a single queue must always adhere to command order and + // API order, but otherwise may overlap or execute out of order. + // + // Therefore, if a previous frame's command buffer is still sampling from this texture, and we + // overwrite it without a pipeline barrier, a texture sample could occur in parallel with the + // texture upload/copy. I'm not sure if any drivers currently take advantage of this, but we + // should insert an explicit pipeline barrier just in case (done by TransitionToLayout). + // + // We transition to TRANSFER_DST, ready for the image copy, and leave the texture in this state. + // This is so that the remaining mip levels can be uploaded without barriers, and then when the + // texture is used, it can be transitioned to SHADER_READ_ONLY (see TCacheEntry::Bind). + m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // Does this texture data fit within the streaming buffer? u32 upload_width = width; @@ -513,16 +434,6 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, m_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, width, height, level, 0); } - - // Transition to shader read only. - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkCmdPipelineBarrier(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); - m_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat src_format, @@ -559,11 +470,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat scale_by_half ? g_object_cache->GetLinearSampler() : g_object_cache->GetPointSampler(); VkImageLayout original_layout = src_texture->GetLayout(); src_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + m_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); UtilityShaderDraw draw( command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT), - TextureCache::GetInstance()->GetRenderPassForTextureUpdate(m_texture.get()), - g_object_cache->GetPassthroughVertexShader(), g_object_cache->GetPassthroughGeometryShader(), + TextureCache::GetInstance()->m_render_pass, g_object_cache->GetPassthroughVertexShader(), + g_object_cache->GetPassthroughGeometryShader(), is_depth_copy ? TextureCache::GetInstance()->m_efb_depth_to_tex_shader : TextureCache::GetInstance()->m_efb_color_to_tex_shader); @@ -587,7 +499,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat src_texture->TransitionToLayout(command_buffer, original_layout); // Render pass transitions texture to SHADER_READ_ONLY. - m_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + m_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase* source, @@ -607,6 +519,8 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase* void TextureCache::TCacheEntry::Bind(unsigned int stage) { + m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); StateTracker::GetInstance()->SetTexture(stage, m_texture->GetView()); } diff --git a/Source/Core/VideoBackends/Vulkan/TextureCache.h b/Source/Core/VideoBackends/Vulkan/TextureCache.h index f59a66e063..4b60d39272 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureCache.h +++ b/Source/Core/VideoBackends/Vulkan/TextureCache.h @@ -68,7 +68,6 @@ public: private: bool CreateRenderPasses(); - VkRenderPass GetRenderPassForTextureUpdate(const Texture2D* texture) const; // Copies the contents of a texture using vkCmdCopyImage void CopyTextureRectangle(TCacheEntry* dst_texture, const MathUtil::Rectangle& dst_rect, @@ -78,8 +77,7 @@ private: void ScaleTextureRectangle(TCacheEntry* dst_texture, const MathUtil::Rectangle& dst_rect, Texture2D* src_texture, const MathUtil::Rectangle& src_rect); - VkRenderPass m_initialize_render_pass = VK_NULL_HANDLE; - VkRenderPass m_update_render_pass = VK_NULL_HANDLE; + VkRenderPass m_render_pass = VK_NULL_HANDLE; std::unique_ptr m_texture_upload_buffer; diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp index 51f668f583..9c943e4b40 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp @@ -180,6 +180,10 @@ void TextureConverter::ConvertTexture(TextureCache::TCacheEntry* dst_entry, m_texel_buffer->CommitMemory(palette_size); VkCommandBuffer command_buffer = GetCommandBufferForTextureConversion(src_entry); + src_entry->GetTexture()->TransitionToLayout(command_buffer, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + dst_entry->GetTexture()->TransitionToLayout(command_buffer, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // Bind and draw to the destination. UtilityShaderDraw draw(command_buffer, @@ -216,6 +220,9 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p // Can't do our own draw within a render pass. StateTracker::GetInstance()->EndRenderPass(); + m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT), m_encoding_render_pass, g_object_cache->GetScreenQuadVertexShader(), @@ -242,7 +249,8 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p draw.EndRenderPass(); // Transition the image before copying - m_encoding_render_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); m_encoding_download_texture->CopyFromImage( g_command_buffer_mgr->GetCurrentCommandBuffer(), m_encoding_render_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, render_width, render_height, 0, 0); @@ -286,7 +294,8 @@ void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u draw.EndRenderPass(); // Render pass transitions to TRANSFER_SRC. - m_encoding_render_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); // Copy from encoding texture to download buffer. m_encoding_download_texture->CopyFromImage(command_buffer, m_encoding_render_texture->GetImage(), @@ -530,8 +539,8 @@ bool TextureConverter::CreateEncodingRenderPass() VkAttachmentDescription attachments[] = { {0, ENCODING_TEXTURE_FORMAT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL}}; + VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}}; VkAttachmentReference color_attachment_references[] = { {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}}; @@ -540,12 +549,6 @@ bool TextureConverter::CreateEncodingRenderPass() color_attachment_references, nullptr, nullptr, 0, nullptr}}; - VkSubpassDependency dependancies[] = { - {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}}; - VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, @@ -553,8 +556,8 @@ bool TextureConverter::CreateEncodingRenderPass() attachments, static_cast(ArraySize(subpass_descriptions)), subpass_descriptions, - static_cast(ArraySize(dependancies)), - dependancies}; + 0, + nullptr}; VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr, &m_encoding_render_pass);