Merge pull request #2823 from Themaister/master

Vulkan: Add explicit render target format support.
This commit is contained in:
Twinaphex 2016-03-26 23:54:19 +01:00
commit 577f210b30
3 changed files with 227 additions and 12 deletions

View File

@ -99,7 +99,7 @@ static string build_stage_source(const vector<string> &lines, const char *stage)
for (auto itr = begin(lines) + 1; itr != end(lines); ++itr) 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) if (stage)
{ {
@ -115,7 +115,8 @@ static string build_stage_source(const vector<string> &lines, const char *stage)
str << '\n'; str << '\n';
} }
} }
else if (itr->find("#pragma name ") != string::npos) else if (itr->find("#pragma name ") == 0 ||
itr->find("#pragma format ") == 0)
{ {
// Ignore // Ignore
} }
@ -127,12 +128,96 @@ static string build_stage_source(const vector<string> &lines, const char *stage)
return str.str(); 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<string> &lines, glslang_meta *meta) static bool glslang_parse_meta(const vector<string> &lines, glslang_meta *meta)
{ {
*meta = glslang_meta{}; *meta = glslang_meta{};
for (auto &line : lines) for (auto &line : lines)
{ {
if (line.find("#pragma name ") != string::npos) if (line.find("#pragma name ") == 0)
{ {
if (!meta->name.empty()) if (!meta->name.empty())
{ {
@ -145,6 +230,25 @@ static bool glslang_parse_meta(const vector<string> &lines, glslang_meta *meta)
str++; str++;
meta->name = 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; return true;
} }
@ -161,7 +265,7 @@ bool glslang_compile_shader(const char *shader_path, glslang_output *output)
return false; return false;
auto &header = lines.front(); 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"); RARCH_ERR("First line of the shader must contain a valid #version string.\n");
return false; return false;

View File

@ -20,9 +20,53 @@
#include <vector> #include <vector>
#include <string> #include <string>
enum glslang_format
{
// 8-bit
SLANG_FORMAT_R8_UNORM = 0,
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_PACK32,
SLANG_FORMAT_A2B10G10R10_UINT_PACK32,
// 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_SFLOAT,
SLANG_FORMAT_R32G32_UINT,
SLANG_FORMAT_R32G32_SINT,
SLANG_FORMAT_R32G32_SFLOAT,
SLANG_FORMAT_R32G32B32A32_UINT,
SLANG_FORMAT_R32G32B32A32_SINT,
SLANG_FORMAT_R32G32B32A32_SFLOAT,
SLANG_FORMAT_UNKNOWN
};
struct glslang_meta struct glslang_meta
{ {
std::string name; std::string name;
glslang_format rt_format = SLANG_FORMAT_UNKNOWN;
}; };
struct glslang_output struct glslang_output
@ -33,7 +77,7 @@ struct glslang_output
}; };
bool glslang_compile_shader(const char *shader_path, glslang_output *output); bool glslang_compile_shader(const char *shader_path, glslang_output *output);
const char *glslang_format_to_string(enum glslang_format fmt);
#endif #endif

View File

@ -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( vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
const struct vulkan_filter_chain_create_info *info, const struct vulkan_filter_chain_create_info *info,
const char *path, vulkan_filter_chain_filter filter) 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; 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) if (!pass->fbo.valid)
{ {
pass_info.scale_type_x = i + 1 == shader->passes 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; : VULKAN_FILTER_CHAIN_SCALE_SOURCE;
pass_info.scale_x = 1.0f; pass_info.scale_x = 1.0f;
pass_info.scale_y = 1.0f; pass_info.scale_y = 1.0f;
pass_info.rt_format = i + 1 == shader->passes
? tmpinfo.swapchain.format if (i + 1 == shader->passes)
: VK_FORMAT_R8G8B8A8_UNORM; {
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 else
{ {
// TODO: Add more general format spec. // Preset overrides shader.
pass_info.rt_format = VK_FORMAT_R8G8B8A8_UNORM; // Kinda ugly ...
if (pass->fbo.srgb_fbo) 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) 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) switch (pass->fbo.type_x)
{ {