From 76b775d5be1f9228c648b8edc1f7bb9533acb471 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Tue, 8 Aug 2017 00:09:25 -0500 Subject: [PATCH] Video Common: Add XFB decoding via the GPU --- .../Core/VideoBackends/OGL/TextureCache.cpp | 1 + .../VideoBackends/Vulkan/TextureConverter.cpp | 20 ++++++++++++- .../VideoBackends/Vulkan/TextureConverter.h | 1 + .../VideoCommon/TextureConversionShader.cpp | 29 +++++++++++++++++++ .../VideoCommon/TextureConversionShader.h | 1 + 5 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index df4bcb7f00..997b53f74b 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -391,6 +391,7 @@ void TextureCache::CreateTextureDecodingResources() GL_R8UI, // BUFFER_FORMAT_R8_UINT GL_R16UI, // BUFFER_FORMAT_R16_UINT GL_RG32UI, // BUFFER_FORMAT_R32G32_UINT + GL_RGBA8UI, // BUFFER_FORMAT_RGBA8_UINT }; glGenTextures(TextureConversionShader::BUFFER_FORMAT_COUNT, diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp index 75f274f917..b646a59fa8 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp @@ -61,6 +61,8 @@ TextureConverter::~TextureConverter() vkDestroyBufferView(g_vulkan_context->GetDevice(), m_texel_buffer_view_r32g32_uint, nullptr); if (m_texel_buffer_view_rgba8_unorm != VK_NULL_HANDLE) vkDestroyBufferView(g_vulkan_context->GetDevice(), m_texel_buffer_view_rgba8_unorm, nullptr); + if (m_texel_buffer_view_rgba8_uint != VK_NULL_HANDLE) + vkDestroyBufferView(g_vulkan_context->GetDevice(), m_texel_buffer_view_rgba8_uint, nullptr); if (m_encoding_render_pass != VK_NULL_HANDLE) vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_encoding_render_pass, nullptr); @@ -487,11 +489,22 @@ void TextureConverter::DecodeTexture(VkCommandBuffer command_buffer, // Copy/commit upload buffer. u32 texel_buffer_offset = static_cast(m_texel_buffer->GetCurrentOffset()); + + Util::BufferMemoryBarrier(g_command_buffer_mgr->GetCurrentCommandBuffer(), + m_texel_buffer->GetBuffer(), VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_HOST_WRITE_BIT, texel_buffer_offset, total_upload_size, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT); + std::memcpy(m_texel_buffer->GetCurrentHostPointer(), data, data_size); if (has_palette) std::memcpy(m_texel_buffer->GetCurrentHostPointer() + palette_offset, palette, palette_size); m_texel_buffer->CommitMemory(total_upload_size); + Util::BufferMemoryBarrier(g_command_buffer_mgr->GetCurrentCommandBuffer(), + m_texel_buffer->GetBuffer(), VK_ACCESS_HOST_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, texel_buffer_offset, total_upload_size, + VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + // Determine uniforms. PushConstants constants = { {width, height}, @@ -513,6 +526,9 @@ void TextureConverter::DecodeTexture(VkCommandBuffer command_buffer, case TextureConversionShader::BUFFER_FORMAT_R32G32_UINT: data_view = m_texel_buffer_view_r32g32_uint; break; + case TextureConversionShader::BUFFER_FORMAT_RGBA8_UINT: + data_view = m_texel_buffer_view_rgba8_uint; + break; default: break; } @@ -564,10 +580,12 @@ bool TextureConverter::CreateTexelBuffer() m_texel_buffer_view_r16_uint = CreateTexelBufferView(VK_FORMAT_R16_UINT); m_texel_buffer_view_r32g32_uint = CreateTexelBufferView(VK_FORMAT_R32G32_UINT); m_texel_buffer_view_rgba8_unorm = CreateTexelBufferView(VK_FORMAT_R8G8B8A8_UNORM); + m_texel_buffer_view_rgba8_uint= CreateTexelBufferView(VK_FORMAT_R8G8B8A8_UINT); return m_texel_buffer_view_r8_uint != VK_NULL_HANDLE && m_texel_buffer_view_r16_uint != VK_NULL_HANDLE && m_texel_buffer_view_r32g32_uint != VK_NULL_HANDLE && - m_texel_buffer_view_rgba8_unorm != VK_NULL_HANDLE; + m_texel_buffer_view_rgba8_unorm != VK_NULL_HANDLE && + m_texel_buffer_view_rgba8_uint != VK_NULL_HANDLE; } VkBufferView TextureConverter::CreateTexelBufferView(VkFormat format) const diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.h b/Source/Core/VideoBackends/Vulkan/TextureConverter.h index 2465691901..1a62590019 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.h +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.h @@ -97,6 +97,7 @@ private: VkBufferView m_texel_buffer_view_r8_uint = VK_NULL_HANDLE; VkBufferView m_texel_buffer_view_r16_uint = VK_NULL_HANDLE; VkBufferView m_texel_buffer_view_r32g32_uint = VK_NULL_HANDLE; + VkBufferView m_texel_buffer_view_rgba8_uint = VK_NULL_HANDLE; VkBufferView m_texel_buffer_view_rgba8_unorm = VK_NULL_HANDLE; size_t m_texel_buffer_size = 0; diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index 04b7bb3a01..1f608651ca 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -1262,12 +1262,41 @@ static const std::map s_decoding_shader_info{ vec4 norm_color = GetPaletteColorNormalized(index); imageStore(output_image, ivec3(ivec2(coords), 0), norm_color); } + )"}}, + + // We do the inverse BT.601 conversion for YCbCr to RGB + // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion + { TextureFormat::XFB, + { BUFFER_FORMAT_RGBA8_UINT, 0, 8, 8, false, + R"( + layout(local_size_x = 8, local_size_y = 8) in; + + void main() + { + uvec2 uv = gl_GlobalInvocationID.xy; + int buffer_pos = int(u_src_offset + (uv.y * u_src_row_stride) + (uv.x / 2)); + vec4 yuyv = texelFetch(s_input_buffer, buffer_pos); + + float y = mix(yuyv.r, yuyv.b, (uv.x & 1u) == 1u); + + float yComp = 1.164 * (y - 16); + float uComp = yuyv.g - 128; + float vComp = yuyv.a - 128; + + vec4 rgb = vec4(yComp + (1.596 * vComp), + yComp - (0.813 * vComp) - (0.391 * uComp), + yComp + (2.018 * uComp), + 255.0); + vec4 rgba_norm = rgb / 255.0; + imageStore(output_image, ivec3(ivec2(uv), 0), rgba_norm); + } )"}}}; static const std::array s_buffer_bytes_per_texel = {{ 1, // BUFFER_FORMAT_R8_UINT 2, // BUFFER_FORMAT_R16_UINT 8, // BUFFER_FORMAT_R32G32_UINT + 4, // BUFFER_FORMAT_RGBA8_UINT }}; const DecodingShaderInfo* GetDecodingShaderInfo(TextureFormat format) diff --git a/Source/Core/VideoCommon/TextureConversionShader.h b/Source/Core/VideoCommon/TextureConversionShader.h index 9b1feb8b45..2680cd3c5b 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.h +++ b/Source/Core/VideoCommon/TextureConversionShader.h @@ -27,6 +27,7 @@ enum BufferFormat BUFFER_FORMAT_R8_UINT, BUFFER_FORMAT_R16_UINT, BUFFER_FORMAT_R32G32_UINT, + BUFFER_FORMAT_RGBA8_UINT, BUFFER_FORMAT_COUNT };