From 236200ef63645a79f1bc1edfba09bb9ddd8d2fad Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 26 Mar 2016 22:52:32 +0100 Subject: [PATCH 1/2] Vulkan: Add format enum for various possible RT formats. Include all formats which are required to be supported in Vulkan 1.0 and GLES 3.x. Not all these formats are supported in GLES2, but that's up to shaders to decide whether they want to support GLES2 or not. --- gfx/drivers_shader/glslang_util.hpp | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/gfx/drivers_shader/glslang_util.hpp b/gfx/drivers_shader/glslang_util.hpp index 5e8037cd2e..c705ac057c 100644 --- a/gfx/drivers_shader/glslang_util.hpp +++ b/gfx/drivers_shader/glslang_util.hpp @@ -20,6 +20,49 @@ #include #include +enum glslang_format +{ + // 8-bit + SLANG_FORMAT_R8_UNORM, + SLANG_FORMAT_R8_UINT, + SLANG_FORMAT_R8_SINT, + SLANG_FORMAT_R8G8_UNORM, + SLANG_FORMAT_R8G8_UINT, + SLANG_FORMAT_R8G8_SINT, + SLANG_FORMAT_R8G8B8A8_UNORM, + SLANG_FORMAT_R8G8B8A8_UINT, + SLANG_FORMAT_R8G8B8A8_SINT, + SLANG_FORMAT_R8G8B8A8_SRGB, + + // 10-bit + SLANG_FORMAT_A2B10G10R10_UNORM, + SLANG_FORMAT_A2B10G10R10_UINT, + + // 16-bit + SLANG_FORMAT_R16_UINT, + SLANG_FORMAT_R16_SINT, + SLANG_FORMAT_R16_SFLOAT, + SLANG_FORMAT_R16G16_UINT, + SLANG_FORMAT_R16G16_SINT, + SLANG_FORMAT_R16G16_SFLOAT, + SLANG_FORMAT_R16G16B16A16_UINT, + SLANG_FORMAT_R16G16B16A16_SINT, + SLANG_FORMAT_R16G16B16A16_SFLOAT, + + // 32-bit + SLANG_FORMAT_R32_UINT, + SLANG_FORMAT_R32_SINT, + SLANG_FORMAT_R32_FLOAT, + SLANG_FORMAT_R32G32_UINT, + SLANG_FORMAT_R32G32_SINT, + SLANG_FORMAT_R32G32_FLOAT, + SLANG_FORMAT_R32G32B32A32_UINT, + SLANG_FORMAT_R32G32B32A32_SINT, + SLANG_FORMAT_R32G32B32A32_FLOAT, + + SLANG_FORMAT_INVALID +}; + struct glslang_meta { std::string name; From 8c2664e5fb5a7f7a80a63448b8460e6416019401 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 26 Mar 2016 23:49:57 +0100 Subject: [PATCH 2/2] Vulkan: Add explicit render target format support. Supports all required formats in Vulkan 1.0 as well as GLES 3.x/GL 3.x (for future). --- gfx/drivers_shader/glslang_util.cpp | 112 ++++++++++++++++++++++++++- gfx/drivers_shader/glslang_util.hpp | 17 ++-- gfx/drivers_shader/shader_vulkan.cpp | 81 +++++++++++++++++-- 3 files changed, 191 insertions(+), 19 deletions(-) diff --git a/gfx/drivers_shader/glslang_util.cpp b/gfx/drivers_shader/glslang_util.cpp index e112267216..90aee21a75 100644 --- a/gfx/drivers_shader/glslang_util.cpp +++ b/gfx/drivers_shader/glslang_util.cpp @@ -99,7 +99,7 @@ static string build_stage_source(const vector &lines, const char *stage) for (auto itr = begin(lines) + 1; itr != end(lines); ++itr) { - if (itr->find("#pragma stage ") != string::npos) + if (itr->find("#pragma stage ") == 0) { if (stage) { @@ -115,7 +115,8 @@ static string build_stage_source(const vector &lines, const char *stage) str << '\n'; } } - else if (itr->find("#pragma name ") != string::npos) + else if (itr->find("#pragma name ") == 0 || + itr->find("#pragma format ") == 0) { // Ignore } @@ -127,12 +128,96 @@ static string build_stage_source(const vector &lines, const char *stage) return str.str(); } +static const char *glslang_formats[] = { + "R8_UNORM", + "R8_UINT", + "R8_SINT", + "R8G8_UNORM", + "R8G8_UINT", + "R8G8_SINT", + "R8G8B8A8_UNORM", + "R8G8B8A8_UINT", + "R8G8B8A8_SINT", + "R8G8B8A8_SRGB", + + "A2B10G10R10_UNORM_PACK32", + "A2B10G10R10_UINT_PACK32", + + "R16_UINT", + "R16_SINT", + "R16_SFLOAT", + "R16G16_UINT", + "R16G16_SINT", + "R16G16_SFLOAT", + "R16G16B16A16_UINT", + "R16G16B16A16_SINT", + "R16G16B16A16_SFLOAT", + + "R32_UINT", + "R32_SINT", + "R32_SFLOAT", + "R32G32_UINT", + "R32G32_SINT", + "R32G32_SFLOAT", + "R32G32B32A32_UINT", + "R32G32B32A32_SINT", + "R32G32B32A32_SFLOAT", + + "UNKNOWN", +}; + +const char *glslang_format_to_string(enum glslang_format fmt) +{ + return glslang_formats[fmt]; +} + +static glslang_format glslang_find_format(const char *fmt) +{ +#undef FMT +#define FMT(x) if (!strcmp(fmt, #x)) return SLANG_FORMAT_ ## x + FMT(R8_UNORM); + FMT(R8_UINT); + FMT(R8_SINT); + FMT(R8G8_UNORM); + FMT(R8G8_UINT); + FMT(R8G8_SINT); + FMT(R8G8B8A8_UNORM); + FMT(R8G8B8A8_UINT); + FMT(R8G8B8A8_SINT); + FMT(R8G8B8A8_SRGB); + + FMT(A2B10G10R10_UNORM_PACK32); + FMT(A2B10G10R10_UINT_PACK32); + + FMT(R16_UINT); + FMT(R16_SINT); + FMT(R16_SFLOAT); + FMT(R16G16_UINT); + FMT(R16G16_SINT); + FMT(R16G16_SFLOAT); + FMT(R16G16B16A16_UINT); + FMT(R16G16B16A16_SINT); + FMT(R16G16B16A16_SFLOAT); + + FMT(R32_UINT); + FMT(R32_SINT); + FMT(R32_SFLOAT); + FMT(R32G32_UINT); + FMT(R32G32_SINT); + FMT(R32G32_SFLOAT); + FMT(R32G32B32A32_UINT); + FMT(R32G32B32A32_SINT); + FMT(R32G32B32A32_SFLOAT); + + return SLANG_FORMAT_UNKNOWN; +} + static bool glslang_parse_meta(const vector &lines, glslang_meta *meta) { *meta = glslang_meta{}; for (auto &line : lines) { - if (line.find("#pragma name ") != string::npos) + if (line.find("#pragma name ") == 0) { if (!meta->name.empty()) { @@ -145,6 +230,25 @@ static bool glslang_parse_meta(const vector &lines, glslang_meta *meta) str++; meta->name = str; } + else if (line.find("#pragma format ") == 0) + { + if (meta->rt_format != SLANG_FORMAT_UNKNOWN) + { + RARCH_ERR("[slang]: Trying to declare format multiple times for file.\n"); + return false; + } + + const char *str = line.c_str() + strlen("#pragma format "); + while (*str == ' ') + str++; + + meta->rt_format = glslang_find_format(str); + if (meta->rt_format == SLANG_FORMAT_UNKNOWN) + { + RARCH_ERR("[slang]: Failed to find format \"%s\".\n", str); + return false; + } + } } return true; } @@ -161,7 +265,7 @@ bool glslang_compile_shader(const char *shader_path, glslang_output *output) return false; auto &header = lines.front(); - if (header.find_first_of("#version ") == string::npos) + if (header.find_first_of("#version ") != 0) { RARCH_ERR("First line of the shader must contain a valid #version string.\n"); return false; diff --git a/gfx/drivers_shader/glslang_util.hpp b/gfx/drivers_shader/glslang_util.hpp index c705ac057c..a28d7fbd19 100644 --- a/gfx/drivers_shader/glslang_util.hpp +++ b/gfx/drivers_shader/glslang_util.hpp @@ -23,7 +23,7 @@ enum glslang_format { // 8-bit - SLANG_FORMAT_R8_UNORM, + SLANG_FORMAT_R8_UNORM = 0, SLANG_FORMAT_R8_UINT, SLANG_FORMAT_R8_SINT, SLANG_FORMAT_R8G8_UNORM, @@ -35,8 +35,8 @@ enum glslang_format SLANG_FORMAT_R8G8B8A8_SRGB, // 10-bit - SLANG_FORMAT_A2B10G10R10_UNORM, - SLANG_FORMAT_A2B10G10R10_UINT, + SLANG_FORMAT_A2B10G10R10_UNORM_PACK32, + SLANG_FORMAT_A2B10G10R10_UINT_PACK32, // 16-bit SLANG_FORMAT_R16_UINT, @@ -52,20 +52,21 @@ enum glslang_format // 32-bit SLANG_FORMAT_R32_UINT, SLANG_FORMAT_R32_SINT, - SLANG_FORMAT_R32_FLOAT, + SLANG_FORMAT_R32_SFLOAT, SLANG_FORMAT_R32G32_UINT, SLANG_FORMAT_R32G32_SINT, - SLANG_FORMAT_R32G32_FLOAT, + SLANG_FORMAT_R32G32_SFLOAT, SLANG_FORMAT_R32G32B32A32_UINT, SLANG_FORMAT_R32G32B32A32_SINT, - SLANG_FORMAT_R32G32B32A32_FLOAT, + SLANG_FORMAT_R32G32B32A32_SFLOAT, - SLANG_FORMAT_INVALID + SLANG_FORMAT_UNKNOWN }; struct glslang_meta { std::string name; + glslang_format rt_format = SLANG_FORMAT_UNKNOWN; }; struct glslang_output @@ -76,7 +77,7 @@ struct glslang_output }; bool glslang_compile_shader(const char *shader_path, glslang_output *output); - +const char *glslang_format_to_string(enum glslang_format fmt); #endif diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index 8bfacb3b89..cd60cb65ae 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -2029,6 +2029,51 @@ struct ConfigDeleter } }; +static VkFormat glslang_format_to_vk(glslang_format fmt) +{ +#undef FMT +#define FMT(x) case SLANG_FORMAT_##x: return VK_FORMAT_##x + switch (fmt) + { + FMT(R8_UNORM); + FMT(R8_SINT); + FMT(R8_UINT); + FMT(R8G8_UNORM); + FMT(R8G8_SINT); + FMT(R8G8_UINT); + FMT(R8G8B8A8_UNORM); + FMT(R8G8B8A8_SINT); + FMT(R8G8B8A8_UINT); + FMT(R8G8B8A8_SRGB); + + FMT(A2B10G10R10_UNORM_PACK32); + FMT(A2B10G10R10_UINT_PACK32); + + FMT(R16_UINT); + FMT(R16_SINT); + FMT(R16_SFLOAT); + FMT(R16G16_UINT); + FMT(R16G16_SINT); + FMT(R16G16_SFLOAT); + FMT(R16G16B16A16_UINT); + FMT(R16G16B16A16_SINT); + FMT(R16G16B16A16_SFLOAT); + + FMT(R32_UINT); + FMT(R32_SINT); + FMT(R32_SFLOAT); + FMT(R32G32_UINT); + FMT(R32G32_SINT); + FMT(R32G32_SFLOAT); + FMT(R32G32B32A32_UINT); + FMT(R32G32B32A32_SINT); + FMT(R32G32B32A32_SFLOAT); + + default: + return VK_FORMAT_UNDEFINED; + } +} + vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( const struct vulkan_filter_chain_create_info *info, const char *path, vulkan_filter_chain_filter filter) @@ -2097,6 +2142,12 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( VULKAN_FILTER_CHAIN_NEAREST; } + bool explicit_format = output.meta.rt_format != SLANG_FORMAT_UNKNOWN; + + // Set a reasonable default. + if (output.meta.rt_format == SLANG_FORMAT_UNKNOWN) + output.meta.rt_format = SLANG_FORMAT_R8G8B8A8_UNORM; + if (!pass->fbo.valid) { pass_info.scale_type_x = i + 1 == shader->passes @@ -2107,18 +2158,34 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( : VULKAN_FILTER_CHAIN_SCALE_SOURCE; pass_info.scale_x = 1.0f; pass_info.scale_y = 1.0f; - pass_info.rt_format = i + 1 == shader->passes - ? tmpinfo.swapchain.format - : VK_FORMAT_R8G8B8A8_UNORM; + + if (i + 1 == shader->passes) + { + pass_info.rt_format = tmpinfo.swapchain.format; + + if (explicit_format) + RARCH_WARN("[slang]: Using explicit format for last pass in chain, but it is not rendered to framebuffer, using swapchain format instead.\n"); + } + else + { + pass_info.rt_format = glslang_format_to_vk(output.meta.rt_format); + RARCH_LOG("[slang]: Using render target format %s for pass output #%u.\n", + glslang_format_to_string(output.meta.rt_format), i); + } } else { - // TODO: Add more general format spec. - pass_info.rt_format = VK_FORMAT_R8G8B8A8_UNORM; + // Preset overrides shader. + // Kinda ugly ... if (pass->fbo.srgb_fbo) - pass_info.rt_format = VK_FORMAT_R8G8B8A8_SRGB; + output.meta.rt_format = SLANG_FORMAT_R8G8B8A8_SRGB; else if (pass->fbo.fp_fbo) - pass_info.rt_format = VK_FORMAT_R16G16B16A16_SFLOAT; + output.meta.rt_format = SLANG_FORMAT_R16G16B16A16_SFLOAT; + /// + + pass_info.rt_format = glslang_format_to_vk(output.meta.rt_format); + RARCH_LOG("[slang]: Using render target format %s for pass output #%u.\n", + glslang_format_to_string(output.meta.rt_format), i); switch (pass->fbo.type_x) {