VideoBackends: Support updated texture encoding shader generators

This commit is contained in:
Stenzek
2017-04-04 23:55:36 +10:00
parent 3847e226ab
commit e9850aa0f2
20 changed files with 194 additions and 279 deletions

View File

@ -88,9 +88,9 @@ void TextureCache::ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase*
m_texture_converter->ConvertTexture(entry, unconverted, m_render_pass, palette, format);
}
void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool is_intensity, bool scale_by_half)
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
// Flush EFB pokes first, as they're expected to be included.
FramebufferManager::GetInstance()->FlushEFBPokes();
@ -120,7 +120,7 @@ void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_
m_texture_converter->EncodeTextureToMemory(src_texture->GetView(), dst, format, native_width,
bytes_per_row, num_blocks_y, memory_stride,
is_depth_copy, is_intensity, scale_by_half, src_rect);
is_depth_copy, src_rect, scale_by_half);
// Transition back to original state
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), original_layout);

View File

@ -59,9 +59,9 @@ public:
void ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase* base_unconverted, void* palette,
TlutFormat format) override;
void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect,
bool is_intensity, bool scale_by_half) override;
void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half) override;
void CopyRectangleFromTexture(TCacheEntry* dst_texture, const MathUtil::Rectangle<int>& dst_rect,
Texture2D* src_texture, const MathUtil::Rectangle<int>& src_rect);

View File

@ -57,11 +57,8 @@ TextureConverter::~TextureConverter()
if (m_encoding_render_framebuffer != VK_NULL_HANDLE)
vkDestroyFramebuffer(g_vulkan_context->GetDevice(), m_encoding_render_framebuffer, nullptr);
for (VkShaderModule shader : m_encoding_shaders)
{
if (shader != VK_NULL_HANDLE)
vkDestroyShaderModule(g_vulkan_context->GetDevice(), shader, nullptr);
}
for (auto& it : m_encoding_shaders)
vkDestroyShaderModule(g_vulkan_context->GetDevice(), it.second, nullptr);
for (const auto& it : m_decoding_pipelines)
{
@ -89,12 +86,6 @@ bool TextureConverter::Initialize()
return false;
}
if (!CompileEncodingShaders())
{
PanicAlert("Failed to compile texture encoding shaders");
return false;
}
if (!CreateEncodingRenderPass())
{
PanicAlert("Failed to create encode render pass");
@ -221,15 +212,17 @@ void TextureConverter::ConvertTexture(TextureCache::TCacheEntry* dst_entry,
draw.EndRenderPass();
}
void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr, u32 format,
u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 memory_stride, bool is_depth_copy,
bool is_intensity, int scale_by_half,
const EFBRectangle& src_rect)
void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr,
const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect,
bool scale_by_half)
{
if (m_encoding_shaders[format] == VK_NULL_HANDLE)
VkShaderModule shader = GetEncodingShader(format);
if (shader == VK_NULL_HANDLE)
{
ERROR_LOG(VIDEO, "Missing encoding fragment shader for format %u", format);
ERROR_LOG(VIDEO, "Missing encoding fragment shader for format %u->%u", format.efb_format,
static_cast<u32>(format.copy_format));
return;
}
@ -242,7 +235,7 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
m_encoding_render_pass, g_object_cache->GetScreenQuadVertexShader(),
VK_NULL_HANDLE, m_encoding_shaders[format]);
VK_NULL_HANDLE, shader);
// Uniform - int4 of left,top,native_width,scale
s32 position_uniform[4] = {src_rect.left, src_rect.top, static_cast<s32>(native_width),
@ -681,24 +674,25 @@ bool TextureConverter::CompilePaletteConversionShaders()
m_palette_conversion_shaders[GX_TL_RGB5A3] != VK_NULL_HANDLE;
}
bool TextureConverter::CompileEncodingShaders()
VkShaderModule TextureConverter::CompileEncodingShader(const EFBCopyFormat& format)
{
// Texture encoding shaders
static const u32 texture_encoding_shader_formats[] = {
GX_TF_I4, GX_TF_I8, GX_TF_IA4, GX_TF_IA8, GX_TF_RGB565, GX_TF_RGB5A3, GX_TF_RGBA8,
GX_CTF_R4, GX_CTF_RA4, GX_CTF_RA8, GX_CTF_A8, GX_CTF_R8, GX_CTF_G8, GX_CTF_B8,
GX_CTF_RG8, GX_CTF_GB8, GX_CTF_Z8H, GX_TF_Z8, GX_CTF_Z16R, GX_TF_Z16, GX_TF_Z24X8,
GX_CTF_Z4, GX_CTF_Z8M, GX_CTF_Z8L, GX_CTF_Z16L};
for (u32 format : texture_encoding_shader_formats)
{
const char* shader_source =
TextureConversionShader::GenerateEncodingShader(format, APIType::Vulkan);
m_encoding_shaders[format] = Util::CompileAndCreateFragmentShader(shader_source);
if (m_encoding_shaders[format] == VK_NULL_HANDLE)
return false;
}
const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::Vulkan);
VkShaderModule module = Util::CompileAndCreateFragmentShader(shader);
if (module == VK_NULL_HANDLE)
PanicAlert("Failed to compile texture encoding shader.");
return true;
return module;
}
VkShaderModule TextureConverter::GetEncodingShader(const EFBCopyFormat& format)
{
auto iter = m_encoding_shaders.find(format);
if (iter != m_encoding_shaders.end())
return iter->second;
VkShaderModule shader = CompileEncodingShader(format);
m_encoding_shaders.emplace(format, shader);
return shader;
}
bool TextureConverter::CreateEncodingRenderPass()

View File

@ -35,10 +35,10 @@ public:
// Uses an encoding shader to copy src_texture to dest_ptr.
// NOTE: Executes the current command buffer.
void EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr, u32 format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool is_intensity, int scale_by_half,
const EFBRectangle& source);
void EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr, const EFBCopyFormat& format,
u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect,
bool scale_by_half);
// Encodes texture to guest memory in XFB (YUYV) format.
void EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u32 dst_stride, u32 dst_height,
@ -55,7 +55,6 @@ public:
TlutFormat palette_format);
private:
static const u32 NUM_TEXTURE_ENCODING_SHADERS = 64;
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;
@ -70,7 +69,9 @@ private:
bool CompilePaletteConversionShaders();
bool CompileEncodingShaders();
VkShaderModule CompileEncodingShader(const EFBCopyFormat& format);
VkShaderModule GetEncodingShader(const EFBCopyFormat& format);
bool CreateEncodingRenderPass();
bool CreateEncodingTexture();
bool CreateEncodingDownloadTexture();
@ -102,7 +103,7 @@ private:
std::array<VkShaderModule, NUM_PALETTE_CONVERSION_SHADERS> m_palette_conversion_shaders = {};
// Texture encoding - RGBA8->GX format in memory
std::array<VkShaderModule, NUM_TEXTURE_ENCODING_SHADERS> m_encoding_shaders = {};
std::map<EFBCopyFormat, VkShaderModule> m_encoding_shaders;
VkRenderPass m_encoding_render_pass = VK_NULL_HANDLE;
std::unique_ptr<Texture2D> m_encoding_render_texture;
VkFramebuffer m_encoding_render_framebuffer = VK_NULL_HANDLE;