From aaeff6c8885e202d4d8d5ebdccf93304330fd9da Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 18 Aug 2019 18:01:21 +0200 Subject: [PATCH] Move C code over to glslang_util.c --- Makefile.common | 1 + .../{glslang_util.cpp => glslang_util.c} | 229 +--------------- gfx/drivers_shader/glslang_util.h | 51 +--- gfx/drivers_shader/glslang_util_cxx.cpp | 256 ++++++++++++++++++ gfx/drivers_shader/glslang_util_cxx.h | 61 +++++ gfx/drivers_shader/shader_gl_core.cpp | 1 + gfx/drivers_shader/shader_vulkan.cpp | 1 + gfx/drivers_shader/slang_preprocess.h | 3 +- griffin/griffin.c | 4 + griffin/griffin_cpp.cpp | 2 +- 10 files changed, 336 insertions(+), 273 deletions(-) rename gfx/drivers_shader/{glslang_util.cpp => glslang_util.c} (53%) create mode 100644 gfx/drivers_shader/glslang_util_cxx.cpp create mode 100644 gfx/drivers_shader/glslang_util_cxx.h diff --git a/Makefile.common b/Makefile.common index 415b1376ec..523675a8e9 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1489,6 +1489,7 @@ ifeq ($(HAVE_SLANG),1) OBJ += gfx/drivers_shader/slang_process.o OBJ += gfx/drivers_shader/slang_preprocess.o OBJ += gfx/drivers_shader/glslang_util.o + OBJ += gfx/drivers_shader/glslang_util_cxx.o OBJ += gfx/drivers_shader/slang_reflection.o endif diff --git a/gfx/drivers_shader/glslang_util.cpp b/gfx/drivers_shader/glslang_util.c similarity index 53% rename from gfx/drivers_shader/glslang_util.cpp rename to gfx/drivers_shader/glslang_util.c index f05c8d42b3..3baf4af719 100644 --- a/gfx/drivers_shader/glslang_util.cpp +++ b/gfx/drivers_shader/glslang_util.c @@ -15,9 +15,6 @@ #include #include -#include -#include -#include #include #include @@ -30,9 +27,6 @@ #endif #include "glslang_util.h" -#if defined(HAVE_GLSLANG) -#include -#endif #include "../../verbosity.h" static void get_include_file( @@ -188,7 +182,7 @@ bool glslang_read_shader_file(const char *path, if (push_line != 0) { snprintf(tmp, sizeof(tmp), "#line %u \"%s\"", - unsigned(i + push_line), basename); + (unsigned)(i + push_line), basename); if (!string_list_append(output, tmp, attr)) goto error; } @@ -249,7 +243,7 @@ const char *glslang_format_to_string(enum glslang_format fmt) return glslang_formats[fmt]; } -static glslang_format glslang_find_format(const char *fmt) +enum glslang_format glslang_find_format(const char *fmt) { #undef FMT #define FMT(x) if (string_is_equal(fmt, #x)) return SLANG_FORMAT_ ## x @@ -289,222 +283,3 @@ static glslang_format glslang_find_format(const char *fmt) return SLANG_FORMAT_UNKNOWN; } - -static std::string build_stage_source( - const struct string_list *lines, const char *stage) -{ - /* Note: since we have to return a std::string anyway, - * there is nothing to be gained from trying to replace - * this ostringstream with a C-based alternative - * (would require a rewrite of deps/glslang/glslang.cpp) */ - std::ostringstream str; - bool active = true; - size_t i; - - if (!lines) - return ""; - - if (lines->size < 1) - return ""; - - /* Version header. */ - str << lines->elems[0].data;; - str << '\n'; - - for (i = 1; i < lines->size; i++) - { - const char *line = lines->elems[i].data; - - /* Identify 'stage' (fragment/vertex) */ - if (!strncmp("#pragma stage ", line, STRLEN_CONST("#pragma stage "))) - { - if (!string_is_empty(stage)) - { - char expected[128]; - - expected[0] = '\0'; - - strlcpy(expected, "#pragma stage ", sizeof(expected)); - strlcat(expected, stage, sizeof(expected)); - - active = strcmp(expected, line) == 0; - } - } - else if (!strncmp("#pragma name ", line, STRLEN_CONST("#pragma name ")) || - !strncmp("#pragma format ", line, STRLEN_CONST("#pragma format "))) - { - /* Ignore */ - } - else if (active) - str << line; - - str << '\n'; - } - - return str.str(); -} - -bool glslang_parse_meta(const struct string_list *lines, glslang_meta *meta) -{ - char id[64]; - char desc[64]; - size_t i; - - id[0] = '\0'; - desc[0] = '\0'; - - if (!lines) - return false; - - *meta = glslang_meta{}; - - for (i = 0; i < lines->size; i++) - { - const char *line = lines->elems[i].data; - - /* Check for shader identifier */ - if (!strncmp("#pragma name ", line, STRLEN_CONST("#pragma name "))) - { - const char *str = NULL; - - if (!meta->name.empty()) - { - RARCH_ERR("[slang]: Trying to declare multiple names for file.\n"); - return false; - } - - str = line + STRLEN_CONST("#pragma name "); - while (*str == ' ') - str++; - - meta->name = str; - } - /* Check for shader parameters */ - else if (!strncmp("#pragma parameter ", line, STRLEN_CONST("#pragma parameter "))) - { - float initial, minimum, maximum, step; - int ret = sscanf( - line, "#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) - { - bool parameter_found = false; - size_t parameter_index = 0; - size_t j; - - for (j = 0; j < meta->parameters.size(); j++) - { - /* Note: LHS is a std:string, RHS is a C string. - * (the glslang_meta stuff has to be C++) */ - if (meta->parameters[j].id == id) - { - parameter_found = true; - parameter_index = j; - break; - } - } - - /* Allow duplicate #pragma parameter, but only - * if they are exactly the same. */ - if (parameter_found) - { - const glslang_parameter *parameter = - &meta->parameters[parameter_index]; - - if ( parameter->desc != desc || - parameter->initial != initial || - parameter->minimum != minimum || - parameter->maximum != maximum || - parameter->step != step - ) - { - RARCH_ERR("[slang]: Duplicate parameters found for \"%s\", but arguments do not match.\n", id); - return false; - } - } - else - meta->parameters.push_back({ id, desc, initial, minimum, maximum, step }); - } - else - { - RARCH_ERR("[slang]: Invalid #pragma parameter line: \"%s\".\n", line); - return false; - } - } - /* Check for framebuffer format */ - else if (!strncmp("#pragma format ", line, 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"); - return false; - } - - str = line + 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); - return false; - } - } - } - - return true; -} - -bool glslang_compile_shader(const char *shader_path, glslang_output *output) -{ -#if defined(HAVE_GLSLANG) - struct string_list *lines = string_list_new(); - - if (!lines) - return false; - - RARCH_LOG("[slang]: Compiling shader \"%s\".\n", shader_path); - - if (!glslang_read_shader_file(shader_path, lines, true)) - goto error; - - if (!glslang_parse_meta(lines, &output->meta)) - goto error; - - if ( !glslang::compile_spirv(build_stage_source(lines, "vertex"), - glslang::StageVertex, &output->vertex)) - { - RARCH_ERR("Failed to compile vertex shader stage.\n"); - goto error; - } - - if ( !glslang::compile_spirv(build_stage_source(lines, "fragment"), - glslang::StageFragment, &output->fragment)) - { - RARCH_ERR("Failed to compile fragment shader stage.\n"); - goto error; - } - - string_list_free(lines); - - return true; - -error: - - if (lines) - string_list_free(lines); -#endif - - return false; -} diff --git a/gfx/drivers_shader/glslang_util.h b/gfx/drivers_shader/glslang_util.h index 8c5c0ae5be..d5ce6b5778 100644 --- a/gfx/drivers_shader/glslang_util.h +++ b/gfx/drivers_shader/glslang_util.h @@ -13,8 +13,8 @@ * If not, see . */ -#ifndef GLSLANG_UTIL_HPP -#define GLSLANG_UTIL_HPP +#ifndef GLSLANG_UTIL_H +#define GLSLANG_UTIL_H #include #include @@ -70,48 +70,11 @@ RETRO_BEGIN_DECLS const char *glslang_format_to_string(glslang_format fmt); +enum glslang_format glslang_find_format(const char *fmt); + +bool glslang_read_shader_file(const char *path, + struct string_list *output, bool root_file); + RETRO_END_DECLS -#ifdef __cplusplus -#include -#include - -struct glslang_parameter -{ - std::string id; - std::string desc; - float initial; - float minimum; - float maximum; - float step; -}; - -struct glslang_meta -{ - std::vector parameters; - std::string name; - glslang_format rt_format; - - glslang_meta() - { - rt_format = SLANG_FORMAT_UNKNOWN; - } -}; - -struct glslang_output -{ - std::vector vertex; - std::vector fragment; - glslang_meta meta; -}; - -bool glslang_compile_shader(const char *shader_path, glslang_output *output); - -/* Helpers for internal use. */ -bool glslang_read_shader_file(const char *path, struct string_list *output, bool root_file); -bool glslang_parse_meta(const struct string_list *lines, glslang_meta *meta); -#endif - -void *config_file_new_wrapper(const char *path); - #endif diff --git a/gfx/drivers_shader/glslang_util_cxx.cpp b/gfx/drivers_shader/glslang_util_cxx.cpp new file mode 100644 index 0000000000..8903ca594c --- /dev/null +++ b/gfx/drivers_shader/glslang_util_cxx.cpp @@ -0,0 +1,256 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2017 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "glslang_util.h" +#include "glslang_util_cxx.h" +#if defined(HAVE_GLSLANG) +#include +#endif +#include "../../verbosity.h" + +static std::string build_stage_source( + const struct string_list *lines, const char *stage) +{ + /* Note: since we have to return a std::string anyway, + * there is nothing to be gained from trying to replace + * this ostringstream with a C-based alternative + * (would require a rewrite of deps/glslang/glslang.cpp) */ + std::ostringstream str; + bool active = true; + size_t i; + + if (!lines) + return ""; + + if (lines->size < 1) + return ""; + + /* Version header. */ + str << lines->elems[0].data;; + str << '\n'; + + for (i = 1; i < lines->size; i++) + { + const char *line = lines->elems[i].data; + + /* Identify 'stage' (fragment/vertex) */ + if (!strncmp("#pragma stage ", line, STRLEN_CONST("#pragma stage "))) + { + if (!string_is_empty(stage)) + { + char expected[128]; + + expected[0] = '\0'; + + strlcpy(expected, "#pragma stage ", sizeof(expected)); + strlcat(expected, stage, sizeof(expected)); + + active = strcmp(expected, line) == 0; + } + } + else if (!strncmp("#pragma name ", line, STRLEN_CONST("#pragma name ")) || + !strncmp("#pragma format ", line, STRLEN_CONST("#pragma format "))) + { + /* Ignore */ + } + else if (active) + str << line; + + str << '\n'; + } + + return str.str(); +} + +bool glslang_parse_meta(const struct string_list *lines, glslang_meta *meta) +{ + char id[64]; + char desc[64]; + size_t i; + + id[0] = '\0'; + desc[0] = '\0'; + + if (!lines) + return false; + + *meta = glslang_meta{}; + + for (i = 0; i < lines->size; i++) + { + const char *line = lines->elems[i].data; + + /* Check for shader identifier */ + if (!strncmp("#pragma name ", line, STRLEN_CONST("#pragma name "))) + { + const char *str = NULL; + + if (!meta->name.empty()) + { + RARCH_ERR("[slang]: Trying to declare multiple names for file.\n"); + return false; + } + + str = line + STRLEN_CONST("#pragma name "); + while (*str == ' ') + str++; + + meta->name = str; + } + /* Check for shader parameters */ + else if (!strncmp("#pragma parameter ", line, STRLEN_CONST("#pragma parameter "))) + { + float initial, minimum, maximum, step; + int ret = sscanf( + line, "#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) + { + bool parameter_found = false; + size_t parameter_index = 0; + size_t j; + + for (j = 0; j < meta->parameters.size(); j++) + { + /* Note: LHS is a std:string, RHS is a C string. + * (the glslang_meta stuff has to be C++) */ + if (meta->parameters[j].id == id) + { + parameter_found = true; + parameter_index = j; + break; + } + } + + /* Allow duplicate #pragma parameter, but only + * if they are exactly the same. */ + if (parameter_found) + { + const glslang_parameter *parameter = + &meta->parameters[parameter_index]; + + if ( parameter->desc != desc || + parameter->initial != initial || + parameter->minimum != minimum || + parameter->maximum != maximum || + parameter->step != step + ) + { + RARCH_ERR("[slang]: Duplicate parameters found for \"%s\", but arguments do not match.\n", id); + return false; + } + } + else + meta->parameters.push_back({ id, desc, initial, minimum, maximum, step }); + } + else + { + RARCH_ERR("[slang]: Invalid #pragma parameter line: \"%s\".\n", line); + return false; + } + } + /* Check for framebuffer format */ + else if (!strncmp("#pragma format ", line, 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"); + return false; + } + + str = line + 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); + return false; + } + } + } + + return true; +} + +bool glslang_compile_shader(const char *shader_path, glslang_output *output) +{ +#if defined(HAVE_GLSLANG) + struct string_list *lines = string_list_new(); + + if (!lines) + return false; + + RARCH_LOG("[slang]: Compiling shader \"%s\".\n", shader_path); + + if (!glslang_read_shader_file(shader_path, lines, true)) + goto error; + + if (!glslang_parse_meta(lines, &output->meta)) + goto error; + + if ( !glslang::compile_spirv(build_stage_source(lines, "vertex"), + glslang::StageVertex, &output->vertex)) + { + RARCH_ERR("Failed to compile vertex shader stage.\n"); + goto error; + } + + if ( !glslang::compile_spirv(build_stage_source(lines, "fragment"), + glslang::StageFragment, &output->fragment)) + { + RARCH_ERR("Failed to compile fragment shader stage.\n"); + goto error; + } + + string_list_free(lines); + + return true; + +error: + + if (lines) + string_list_free(lines); +#endif + + return false; +} diff --git a/gfx/drivers_shader/glslang_util_cxx.h b/gfx/drivers_shader/glslang_util_cxx.h new file mode 100644 index 0000000000..0dc92666ca --- /dev/null +++ b/gfx/drivers_shader/glslang_util_cxx.h @@ -0,0 +1,61 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2017 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef GLSLANG_UTIL_HPP +#define GLSLANG_UTIL_HPP + +#include +#include + +#include + +#include +#include + +struct glslang_parameter +{ + std::string id; + std::string desc; + float initial; + float minimum; + float maximum; + float step; +}; + +struct glslang_meta +{ + std::vector parameters; + std::string name; + glslang_format rt_format; + + glslang_meta() + { + rt_format = SLANG_FORMAT_UNKNOWN; + } +}; + +struct glslang_output +{ + std::vector vertex; + std::vector fragment; + glslang_meta meta; +}; + +bool glslang_compile_shader(const char *shader_path, glslang_output *output); + +/* Helpers for internal use. */ +bool glslang_parse_meta(const struct string_list *lines, glslang_meta *meta); + +#endif diff --git a/gfx/drivers_shader/shader_gl_core.cpp b/gfx/drivers_shader/shader_gl_core.cpp index 89b9c3fc1b..556b01e7d7 100644 --- a/gfx/drivers_shader/shader_gl_core.cpp +++ b/gfx/drivers_shader/shader_gl_core.cpp @@ -15,6 +15,7 @@ #include "shader_gl_core.h" #include "glslang_util.h" +#include "glslang_util_cxx.h" #include #include diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index 204bd9fea1..f891dd2a57 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -16,6 +16,7 @@ #include "shader_vulkan.h" #include "glslang_util.h" +#include "glslang_util_cxx.h" #include #include #include diff --git a/gfx/drivers_shader/slang_preprocess.h b/gfx/drivers_shader/slang_preprocess.h index b730582ffe..bda938d00a 100644 --- a/gfx/drivers_shader/slang_preprocess.h +++ b/gfx/drivers_shader/slang_preprocess.h @@ -20,6 +20,7 @@ #include #include "../../retroarch.h" +#include "glslang_util.h" RETRO_BEGIN_DECLS @@ -33,7 +34,7 @@ RETRO_END_DECLS #ifdef __cplusplus -#include "glslang_util.h" +#include "glslang_util_cxx.h" bool slang_preprocess_parse_parameters(glslang_meta& meta, struct video_shader *shader); diff --git a/griffin/griffin.c b/griffin/griffin.c index 12958209c7..01e4527ea8 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -301,6 +301,10 @@ VIDEO SHADERS #include "../gfx/video_shader_parse.c" #endif +#ifdef HAVE_SLANG +#include "../gfx/drivers_shader/glslang_util.c" +#endif + #ifdef HAVE_CG #ifdef HAVE_OPENGL #include "../gfx/drivers_shader/shader_gl_cg.c" diff --git a/griffin/griffin_cpp.cpp b/griffin/griffin_cpp.cpp index 8799975bad..4570b9e1b1 100644 --- a/griffin/griffin_cpp.cpp +++ b/griffin/griffin_cpp.cpp @@ -115,7 +115,7 @@ VIDEO DRIVER #include "../deps/SPIRV-Cross/spirv_parser.cpp" #include "../deps/SPIRV-Cross/spirv_cross_parsed_ir.cpp" #ifdef HAVE_SLANG -#include "../gfx/drivers_shader/glslang_util.cpp" +#include "../gfx/drivers_shader/glslang_util_cxx.cpp" #include "../gfx/drivers_shader/slang_preprocess.cpp" #include "../gfx/drivers_shader/slang_process.cpp" #include "../gfx/drivers_shader/slang_reflection.cpp"