mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
Video Common: Add XFB decoding via the GPU
This commit is contained in:
parent
4d13f69dc1
commit
76b775d5be
@ -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,
|
||||
|
@ -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<u32>(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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -1262,12 +1262,41 @@ static const std::map<TextureFormat, DecodingShaderInfo> 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<u32, BUFFER_FORMAT_COUNT> 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)
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user