mirror of
https://github.com/libretro/RetroArch
synced 2025-01-31 06:32:48 +00:00
Refactor code for glslang shader presets - buffer entire file
into memory before passing it on
This commit is contained in:
parent
05fecc4e15
commit
0fee6a9ef4
@ -38,7 +38,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool glslang_read_shader_file(const char *path, vector<string> *output, bool root_file)
|
||||
static bool glslang_read_shader_file(const char *path, vector<string> *output, bool root_file)
|
||||
{
|
||||
vector<const char *> lines;
|
||||
char include_path[PATH_MAX_LENGTH];
|
||||
@ -283,6 +283,113 @@ static glslang_format glslang_find_format(const char *fmt)
|
||||
return SLANG_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
bool glslang_parse_meta(void *data, glslang_meta *meta)
|
||||
{
|
||||
char id[64];
|
||||
char desc[64];
|
||||
size_t line_index = 0;
|
||||
struct string_list *lines = (struct string_list*)data;
|
||||
|
||||
id[0] = desc[0] = '\0';
|
||||
|
||||
*meta = glslang_meta{};
|
||||
|
||||
while (line_index < lines->size)
|
||||
{
|
||||
const char *line_c = lines->elems[line_index].data;
|
||||
line_index++;
|
||||
|
||||
if (!strncmp("#pragma name", line_c, STRLEN_CONST("#pragma name")))
|
||||
{
|
||||
const char *str = NULL;
|
||||
|
||||
if (!meta->name.empty())
|
||||
{
|
||||
RARCH_ERR("[slang]: Trying to declare multiple names for file.\n");
|
||||
string_list_free(lines);
|
||||
return false;
|
||||
}
|
||||
|
||||
str = line_c + STRLEN_CONST("#pragma name ");
|
||||
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
meta->name = str;
|
||||
}
|
||||
if (!strncmp("#pragma parameter", line_c, STRLEN_CONST("#pragma parameter")))
|
||||
{
|
||||
float initial, minimum, maximum, step;
|
||||
int ret = sscanf(line_c, "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f",
|
||||
id, desc, &initial, &minimum, &maximum, &step);
|
||||
|
||||
if (ret == 5)
|
||||
{
|
||||
step = 0.1f * (maximum - minimum);
|
||||
ret = 6;
|
||||
}
|
||||
|
||||
if (ret == 6)
|
||||
{
|
||||
auto itr = find_if(begin(meta->parameters), end(meta->parameters), [&](const glslang_parameter ¶m) {
|
||||
return param.id == id;
|
||||
});
|
||||
|
||||
/* Allow duplicate #pragma parameter, but only
|
||||
* if they are exactly the same. */
|
||||
if (itr != end(meta->parameters))
|
||||
{
|
||||
if ( itr->desc != desc ||
|
||||
itr->initial != initial ||
|
||||
itr->minimum != minimum ||
|
||||
itr->maximum != maximum ||
|
||||
itr->step != step
|
||||
)
|
||||
{
|
||||
RARCH_ERR("[slang]: Duplicate parameters found for \"%s\", but arguments do not match.\n", id);
|
||||
string_list_free(lines);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
meta->parameters.push_back({ id, desc, initial, minimum, maximum, step });
|
||||
}
|
||||
else
|
||||
{
|
||||
RARCH_ERR("[slang]: Invalid #pragma parameter line: \"%s\".\n", line_c);
|
||||
string_list_free(lines);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!strncmp("#pragma format", line_c, STRLEN_CONST("#pragma format")))
|
||||
{
|
||||
const char *str = NULL;
|
||||
|
||||
if (meta->rt_format != SLANG_FORMAT_UNKNOWN)
|
||||
{
|
||||
RARCH_ERR("[slang]: Trying to declare format multiple times for file.\n");
|
||||
string_list_free(lines);
|
||||
return false;
|
||||
}
|
||||
|
||||
str = line_c + STRLEN_CONST("#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);
|
||||
string_list_free(lines);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_list_free(lines);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool glslang_parse_meta(const vector<string> &lines, glslang_meta *meta)
|
||||
{
|
||||
char id[64];
|
||||
|
@ -105,9 +105,8 @@ struct glslang_output
|
||||
|
||||
bool glslang_compile_shader(const char *shader_path, glslang_output *output);
|
||||
|
||||
/* Helpers for internal use. */
|
||||
bool glslang_read_shader_file(const char *path, std::vector<std::string> *output, bool root_file);
|
||||
bool glslang_parse_meta(const std::vector<std::string> &lines, glslang_meta *meta);
|
||||
bool glslang_parse_meta(void *data, glslang_meta *meta);
|
||||
#endif
|
||||
|
||||
void *config_file_new_wrapper(const char *path);
|
||||
|
@ -89,14 +89,11 @@ bool slang_preprocess_parse_parameters(glslang_meta& meta,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool slang_preprocess_parse_parameters(const char *shader_path,
|
||||
struct video_shader *shader)
|
||||
bool slang_preprocess_parse_parameters(void *data, struct video_shader *shader)
|
||||
{
|
||||
glslang_meta meta;
|
||||
vector<string> lines;
|
||||
struct string_list *lines = (struct string_list*)data;
|
||||
|
||||
if (!glslang_read_shader_file(shader_path, &lines, true))
|
||||
return false;
|
||||
if (!glslang_parse_meta(lines, &meta))
|
||||
return false;
|
||||
return slang_preprocess_parse_parameters(meta, shader);
|
||||
|
@ -26,7 +26,7 @@ RETRO_BEGIN_DECLS
|
||||
/* Utility function to implement the same parameter reflection
|
||||
* which happens in the slang backend.
|
||||
* This does preprocess over the input file to handle #includes and so on. */
|
||||
bool slang_preprocess_parse_parameters(const char *shader_path,
|
||||
bool slang_preprocess_parse_parameters(void *data,
|
||||
struct video_shader *shader);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
@ -496,20 +496,6 @@ bool video_shader_resolve_parameters(config_file_t *conf,
|
||||
if (!path_is_valid(path))
|
||||
continue;
|
||||
|
||||
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
|
||||
/* First try to use the more robust slang
|
||||
* implementation to support #includes. */
|
||||
/* FIXME: The check for slang can be removed
|
||||
* if it's sufficiently tested for
|
||||
* GLSL/Cg as well, it should be the same implementation. */
|
||||
if (string_is_equal(path_get_extension(path), "slang") &&
|
||||
slang_preprocess_parse_parameters(path, shader))
|
||||
continue;
|
||||
|
||||
/* If that doesn't work, fallback to the old path.
|
||||
* Ideally, we'd get rid of this path sooner or later. */
|
||||
#endif
|
||||
|
||||
/* Read file contents */
|
||||
if (!filestream_read_file(path, (void**)&buf, &buf_len))
|
||||
continue;
|
||||
@ -525,7 +511,21 @@ bool video_shader_resolve_parameters(config_file_t *conf,
|
||||
if (!lines)
|
||||
continue;
|
||||
|
||||
/* even though the pass is set in the loop too, not all passes have parameters */
|
||||
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
|
||||
/* First try to use the more robust slang
|
||||
* implementation to support #includes. */
|
||||
/* FIXME: The check for slang can be removed
|
||||
* if it's sufficiently tested for
|
||||
* GLSL/Cg as well, it should be the same implementation. */
|
||||
if (string_is_equal(path_get_extension(path), "slang") &&
|
||||
slang_preprocess_parse_parameters(lines, shader))
|
||||
continue;
|
||||
|
||||
/* If that doesn't work, fallback to the old path.
|
||||
* Ideally, we'd get rid of this path sooner or later. */
|
||||
#endif
|
||||
/* even though the pass is set in the loop too, not all
|
||||
* passes have parameters */
|
||||
param->pass = i;
|
||||
|
||||
while ((shader->num_parameters < ARRAY_SIZE(shader->parameters)) &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user