mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-01-30 16:14:11 +00:00
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).
This commit is contained in:
parent
236200ef63
commit
8c2664e5fb
@ -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)
|
||||
{
|
||||
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<string> &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<string> &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<string> &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<string> &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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user