From 59517318d6a237055bf244e05fed8ce059167e83 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 30 Oct 2017 22:58:43 +1000 Subject: [PATCH] Vulkan: Use new readback methods for texture encoding --- .../VideoBackends/Vulkan/TextureConverter.cpp | 107 +++++------------- .../VideoBackends/Vulkan/TextureConverter.h | 12 +- 2 files changed, 35 insertions(+), 84 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp index b8ac91d06b..e0dacded9e 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp @@ -67,9 +67,6 @@ TextureConverter::~TextureConverter() if (m_encoding_render_pass != VK_NULL_HANDLE) vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_encoding_render_pass, nullptr); - if (m_encoding_render_framebuffer != VK_NULL_HANDLE) - vkDestroyFramebuffer(g_vulkan_context->GetDevice(), m_encoding_render_framebuffer, nullptr); - for (auto& it : m_encoding_shaders) vkDestroyShaderModule(g_vulkan_context->GetDevice(), it.second, nullptr); @@ -111,12 +108,6 @@ bool TextureConverter::Initialize() return false; } - if (!CreateEncodingDownloadTexture()) - { - PanicAlert("Failed to create download texture"); - return false; - } - if (!CreateDecodingTexture()) { PanicAlert("Failed to create decoding texture"); @@ -245,8 +236,10 @@ 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); + static_cast(m_encoding_render_texture.get()) + ->GetRawTexIdentifier() + ->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), @@ -276,23 +269,15 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p render_height); VkRect2D render_region = {{0, 0}, {render_width, render_height}}; - draw.BeginRenderPass(m_encoding_render_framebuffer, render_region); + draw.BeginRenderPass(static_cast(m_encoding_render_texture.get())->GetFramebuffer(), + render_region); draw.DrawWithoutVertexBuffer(4); draw.EndRenderPass(); - // Transition the image before copying - 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); - - // Block until the GPU has finished copying to the staging texture. - Util::ExecuteCurrentCommandsAndRestoreState(false, true); - - // Copy from staging texture to the final destination, adjusting pitch if necessary. - m_encoding_download_texture->ReadTexels(0, 0, render_width, render_height, dest_ptr, - memory_stride); + MathUtil::Rectangle copy_rect(0, 0, render_width, render_height); + m_encoding_readback_texture->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0, + copy_rect); + m_encoding_readback_texture->ReadTexels(copy_rect, dest_ptr, memory_stride); } void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u32 dst_stride, @@ -304,8 +289,9 @@ void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u // Borrow framebuffer from EFB2RAM encoder. VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); src_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - m_encoding_render_texture->TransitionToLayout(command_buffer, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + static_cast(m_encoding_render_texture.get()) + ->GetRawTexIdentifier() + ->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // Use fragment shader to convert RGBA to YUYV. // Use linear sampler for downscaling. This texture is in BGRA order, so the data is already in @@ -317,7 +303,8 @@ void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u m_encoding_render_pass, g_shader_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE, m_rgb_to_yuyv_shader); VkRect2D region = {{0, 0}, {output_width, dst_height}}; - draw.BeginRenderPass(m_encoding_render_framebuffer, region); + draw.BeginRenderPass(static_cast(m_encoding_render_texture.get())->GetFramebuffer(), + region); draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetLinearSampler()); draw.DrawQuad(0, 0, static_cast(output_width), static_cast(dst_height), src_rect.left, src_rect.top, 0, src_rect.GetWidth(), src_rect.GetHeight(), @@ -325,18 +312,11 @@ void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u static_cast(src_texture->GetHeight())); draw.EndRenderPass(); - // Render pass transitions to TRANSFER_SRC. - 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(), - VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, output_width, - dst_height, 0, 0); - Util::ExecuteCurrentCommandsAndRestoreState(false, true); - - // Finally, copy to guest memory. This may have a different stride. - m_encoding_download_texture->ReadTexels(0, 0, output_width, dst_height, dst_ptr, dst_stride); + MathUtil::Rectangle copy_rect(0, 0, output_width, dst_height); + m_encoding_readback_texture->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0, + copy_rect); + m_encoding_readback_texture->ReadTexels(copy_rect, dst_ptr, dst_stride); } void TextureConverter::DecodeYUYVTextureFromMemory(VKTexture* dst_texture, const void* src_ptr, @@ -734,10 +714,10 @@ VkShaderModule TextureConverter::GetEncodingShader(const EFBCopyParams& params) 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_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}}; + {0, Util::GetVkFormatForHostTextureFormat(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_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}}; VkAttachmentReference color_attachment_references[] = { {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}}; @@ -769,43 +749,14 @@ bool TextureConverter::CreateEncodingRenderPass() bool TextureConverter::CreateEncodingTexture() { - m_encoding_render_texture = Texture2D::Create( - ENCODING_TEXTURE_WIDTH, ENCODING_TEXTURE_HEIGHT, 1, 1, ENCODING_TEXTURE_FORMAT, - VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - if (!m_encoding_render_texture) - return false; + TextureConfig config(ENCODING_TEXTURE_WIDTH, ENCODING_TEXTURE_HEIGHT, 1, 1, + ENCODING_TEXTURE_FORMAT, true); - VkImageView framebuffer_attachments[] = {m_encoding_render_texture->GetView()}; - VkFramebufferCreateInfo framebuffer_info = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - nullptr, - 0, - m_encoding_render_pass, - static_cast(ArraySize(framebuffer_attachments)), - framebuffer_attachments, - m_encoding_render_texture->GetWidth(), - m_encoding_render_texture->GetHeight(), - m_encoding_render_texture->GetLayers()}; + m_encoding_render_texture = g_renderer->CreateTexture(config); + m_encoding_readback_texture = + g_renderer->CreateStagingTexture(StagingTextureType::Readback, config); - VkResult res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr, - &m_encoding_render_framebuffer); - if (res != VK_SUCCESS) - { - LOG_VULKAN_ERROR(res, "vkCreateFramebuffer failed: "); - return false; - } - - return true; -} - -bool TextureConverter::CreateEncodingDownloadTexture() -{ - m_encoding_download_texture = - StagingTexture2D::Create(STAGING_BUFFER_TYPE_READBACK, ENCODING_TEXTURE_WIDTH, - ENCODING_TEXTURE_HEIGHT, ENCODING_TEXTURE_FORMAT); - - return m_encoding_download_texture && m_encoding_download_texture->Map(); + return m_encoding_render_texture && m_encoding_readback_texture; } bool TextureConverter::CreateDecodingTexture() diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.h b/Source/Core/VideoBackends/Vulkan/TextureConverter.h index 1a62590019..3adb26c5b7 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.h +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.h @@ -16,6 +16,9 @@ #include "VideoCommon/TextureDecoder.h" #include "VideoCommon/VideoCommon.h" +class AbstractTexture; +class AbstractStagingTexture; + namespace Vulkan { class StagingTexture2D; @@ -58,7 +61,7 @@ public: private: static const u32 ENCODING_TEXTURE_WIDTH = EFB_WIDTH * 4; static const u32 ENCODING_TEXTURE_HEIGHT = 1024; - static const VkFormat ENCODING_TEXTURE_FORMAT = VK_FORMAT_B8G8R8A8_UNORM; + static const AbstractTextureFormat ENCODING_TEXTURE_FORMAT = AbstractTextureFormat::BGRA8; static const size_t NUM_PALETTE_CONVERSION_SHADERS = 3; // Maximum size of a texture based on BP registers. @@ -75,8 +78,6 @@ private: bool CreateEncodingRenderPass(); bool CreateEncodingTexture(); - bool CreateEncodingDownloadTexture(); - bool CreateDecodingTexture(); bool CompileYUYVConversionShaders(); @@ -106,10 +107,9 @@ private: // Texture encoding - RGBA8->GX format in memory std::map m_encoding_shaders; + std::unique_ptr m_encoding_render_texture; + std::unique_ptr m_encoding_readback_texture; VkRenderPass m_encoding_render_pass = VK_NULL_HANDLE; - std::unique_ptr m_encoding_render_texture; - VkFramebuffer m_encoding_render_framebuffer = VK_NULL_HANDLE; - std::unique_ptr m_encoding_download_texture; // Texture decoding - GX format in memory->RGBA8 struct TextureDecodingPipeline