From 34357f00fb5cb280503fbb2d61669ce2667971ba Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 8 Oct 2013 13:36:15 -0700 Subject: [PATCH] finish up GLSL conversion stuff and make some minor tweaks to shader parser --- README | 5 +- libobs-opengl/gl-shaderparser.c | 320 +++++++++++++++++++++++++++++--- libobs-opengl/gl-shaderparser.h | 1 - libobs/graphics/effect-parser.c | 2 - libobs/graphics/shader-parser.c | 7 +- libobs/graphics/shader-parser.h | 8 +- 6 files changed, 305 insertions(+), 38 deletions(-) diff --git a/README b/README index 5acc89f36..f6a1006f0 100644 --- a/README +++ b/README @@ -14,9 +14,8 @@ What's the goal of rewriting OBS? necessary for user interface. It also means allowing the use of OpenGL as well as Direct3D. - - Separate the application from the core, allowing custom user interfaces and - custom appliction of the core if desired, and easier extending of the user - interface. + - Separate the application from the core, allowing custom custom appliction of + the core if desired, and easier extending of the user interface. - Simplify complex systems to not only make it easier to use, but easier to maintain. diff --git a/libobs-opengl/gl-shaderparser.c b/libobs-opengl/gl-shaderparser.c index e72bf3796..11f586d10 100644 --- a/libobs-opengl/gl-shaderparser.c +++ b/libobs-opengl/gl-shaderparser.c @@ -18,7 +18,10 @@ #include "gl-subsystem.h" #include "gl-shaderparser.h" -static void gl_write_type_n(struct gl_shader_parser *glsp, +static void gl_write_function_contents(struct gl_shader_parser *glsp, + struct cf_token **p_token, const char *end); + +static bool gl_write_type_n(struct gl_shader_parser *glsp, const char *type, size_t len) { if (astrcmp_n(type, "float2", len) == 0) @@ -40,19 +43,22 @@ static void gl_write_type_n(struct gl_shader_parser *glsp, else if (astrcmp_n(type, "texture_cube", len) == 0) dstr_cat(&glsp->gl_string, "samplerCube"); else - dstr_ncat(&glsp->gl_string, type, len); + return false; + + return true; } static inline void gl_write_type(struct gl_shader_parser *glsp, const char *type) { - gl_write_type_n(glsp, type, strlen(type)); + if (!gl_write_type_n(glsp, type, strlen(type))) + dstr_cat(&glsp->gl_string, type); } -static inline void gl_write_type_token(struct gl_shader_parser *glsp, +static inline bool gl_write_type_token(struct gl_shader_parser *glsp, struct cf_token *token) { - gl_write_type_n(glsp, token->str.array, token->str.len); + return gl_write_type_n(glsp, token->str.array, token->str.len); } static void gl_write_var(struct gl_shader_parser *glsp, struct shader_var *var) @@ -65,7 +71,6 @@ static void gl_write_var(struct gl_shader_parser *glsp, struct shader_var *var) gl_write_type(glsp, var->type); dstr_cat(&glsp->gl_string, " "); dstr_cat(&glsp->gl_string, var->name); - dstr_cat(&glsp->gl_string, ";\n"); } static inline void gl_write_params(struct gl_shader_parser *glsp) @@ -74,6 +79,7 @@ static inline void gl_write_params(struct gl_shader_parser *glsp) for (i = 0; i < glsp->parser.params.num; i++) { struct shader_var *var = glsp->parser.params.array+i; gl_write_var(glsp, var); + dstr_cat(&glsp->gl_string, ";\n"); } dstr_cat(&glsp->gl_string, "\n"); @@ -85,7 +91,7 @@ static void gl_write_storage_var(struct gl_shader_parser *glsp, /* unwraps a structure that's used for input/output */ static void gl_unwrap_storage_struct(struct gl_shader_parser *glsp, - struct shader_struct *st, const char *storage, + struct shader_struct *st, const char *name, const char *storage, const char *prefix) { struct dstr prefix_str; @@ -94,7 +100,7 @@ static void gl_unwrap_storage_struct(struct gl_shader_parser *glsp, dstr_init(&prefix_str); if (prefix) dstr_copy(&prefix_str, prefix); - dstr_cat(&prefix_str, st->name); + dstr_cat(&prefix_str, name); dstr_cat(&prefix_str, "_"); for (i = 0; i < st->vars.num; i++) { @@ -112,7 +118,7 @@ static void gl_write_storage_var(struct gl_shader_parser *glsp, var->type); if (st) { - gl_unwrap_storage_struct(glsp, st, storage, prefix); + gl_unwrap_storage_struct(glsp, st, var->name, storage, prefix); } else { if (storage) { dstr_cat(&glsp->gl_string, storage); @@ -132,25 +138,23 @@ static inline void gl_write_inputs(struct gl_shader_parser *glsp, struct shader_func *main) { size_t i; - for (i = 0; i < main->params.num; i++) { - struct shader_var *var = main->params.array+i; - gl_write_storage_var(glsp, var, "in", "in_"); - } + for (i = 0; i < main->params.num; i++) + gl_write_storage_var(glsp, main->params.array+i, "in", + "inputval_"); + dstr_cat(&glsp->gl_string, "\n"); } static void gl_write_outputs(struct gl_shader_parser *glsp, struct shader_func *main) { - struct shader_var var; + struct shader_var var = {0}; + var.type = main->return_type; + var.name = "outputval"; + if (main->mapping) + var.mapping = main->mapping; - shader_var_init(&var); - var.type = bstrdup(main->return_type); - var.name = bstrdup("return_val"); - if (main->return_mapping) - var.mapping = bstrdup(main->return_mapping); - - gl_write_storage_var(glsp, &var, "out", "out_"); - shader_var_free(&var); + gl_write_storage_var(glsp, &var, "out", NULL); + dstr_cat(&glsp->gl_string, "\n"); } static void gl_write_struct(struct gl_shader_parser *glsp, @@ -166,6 +170,7 @@ static void gl_write_struct(struct gl_shader_parser *glsp, dstr_cat(&glsp->gl_string, "\t"); gl_write_var(glsp, var); + dstr_cat(&glsp->gl_string, ";\n"); } dstr_cat(&glsp->gl_string, "};\n\n"); @@ -203,8 +208,272 @@ static inline void gl_write_structs(struct gl_shader_parser *glsp) * All else can be left as-is */ -static void gl_write_functions(struct gl_shader_parser *glsp) +static inline bool gl_write_texture_call(struct gl_shader_parser *glsp, + struct shader_var *var, const char *call) { + struct cf_parser *cfp = &glsp->parser.cfp; + if (!go_to_token(cfp, ",", NULL)) + return false; + + dstr_cat(&glsp->gl_string, call); + dstr_cat(&glsp->gl_string, "("); + dstr_cat(&glsp->gl_string, var->name); + dstr_cat(&glsp->gl_string, ", "); + return true; +} + +/* processes texture.Sample(sampler, texcoord) */ +static bool gl_write_texture_code(struct gl_shader_parser *glsp, + struct cf_token **p_token, struct shader_var *var) +{ + struct cf_parser *cfp = &glsp->parser.cfp; + bool written = false; + cfp->cur_token = *p_token; + + if (!next_token(cfp)) return false; + if (!token_is(cfp, ".")) return false; + if (!next_token(cfp)) return false; + + if (token_is(cfp, "Sample")) + written = gl_write_texture_call(glsp, var, "texture"); + else if (token_is(cfp, "SampleBias")) + written = gl_write_texture_call(glsp, var, "texture"); + else if (token_is(cfp, "SampleGrad")) + written = gl_write_texture_call(glsp, var, "textureGrad"); + else if (token_is(cfp, "SampleLevel")) + written = gl_write_texture_call(glsp, var, "textureLod"); + + if (!written) + return false; + + if (!next_token(cfp)) return false; + + gl_write_function_contents(glsp, &cfp->cur_token, ")"); + dstr_cat(&glsp->gl_string, ")"); + + *p_token = cfp->cur_token; + return true; +} + +static inline struct shader_var *sp_getparam(struct gl_shader_parser *glsp, + struct cf_token *token) +{ + size_t i; + for (i = 0; i < glsp->parser.params.num; i++) { + struct shader_var *param = glsp->parser.params.array+i; + if (strref_cmp(&token->str, param->name) == 0) + return param; + } + + return NULL; +} + +static bool gl_write_intrinsic(struct gl_shader_parser *glsp, + struct cf_token **p_token) +{ + struct cf_token *token = *p_token; + bool written = true; + + if (strref_cmp(&token->str, "atan2") == 0) { + dstr_cat(&glsp->gl_string, "atan2"); + } else if (strref_cmp(&token->str, "ddx") == 0) { + dstr_cat(&glsp->gl_string, "dFdx"); + } else if (strref_cmp(&token->str, "ddy") == 0) { + dstr_cat(&glsp->gl_string, "dFdy"); + } else if (strref_cmp(&token->str, "frac") == 0) { + dstr_cat(&glsp->gl_string, "fract"); + } else if (strref_cmp(&token->str, "lerp") == 0) { + dstr_cat(&glsp->gl_string, "mix"); + } else if (strref_cmp(&token->str, "rsqrt") == 0) { + dstr_cat(&glsp->gl_string, "inversesqrt"); + } else { + struct shader_var *var = sp_getparam(glsp, token); + if (var && astrcmp_n(var->type, "texture", 7) == 0) + written = gl_write_texture_code(glsp, &token, var); + else + written = false; + } + + if (written) + *p_token = token; + return written; +} + +static void gl_write_function_contents(struct gl_shader_parser *glsp, + struct cf_token **p_token, const char *end) +{ + struct cf_token *token = *p_token; + + dstr_cat_strref(&glsp->gl_string, &token->str); + + while (token->type != CFTOKEN_NONE) { + token++; + + if (end && strref_cmp(&token->str, end) == 0) + break; + + if (token->type == CFTOKEN_NAME) { + if (!gl_write_type_token(glsp, token) && + !gl_write_intrinsic(glsp, &token)) + dstr_cat_strref(&glsp->gl_string, &token->str); + + } else if (token->type == CFTOKEN_OTHER) { + if (*token->str.array == '{') + gl_write_function_contents(glsp, &token, "}"); + else if (*token->str.array == '(') + gl_write_function_contents(glsp, &token, ")"); + + dstr_cat_strref(&glsp->gl_string, &token->str); + + } else { + dstr_cat_strref(&glsp->gl_string, &token->str); + } + } + + *p_token = token; +} + +static void gl_write_function(struct gl_shader_parser *glsp, + struct shader_func *func) +{ + size_t i; + struct cf_token *token; + + gl_write_type(glsp, func->return_type); + dstr_cat(&glsp->gl_string, " "); + + if (strcmp(func->name, "main") == 0) + dstr_cat(&glsp->gl_string, "__main__"); + else + dstr_cat(&glsp->gl_string, func->name); + + dstr_cat(&glsp->gl_string, "("); + + for (i = 0; i < func->params.num; i++) { + struct shader_var *param = func->params.array+i; + + if (i > 0) + dstr_cat(&glsp->gl_string, ", "); + gl_write_var(glsp, param); + } + + dstr_cat(&glsp->gl_string, ")\n"); + + token = func->start; + gl_write_function_contents(glsp, &token, "}"); + dstr_cat(&glsp->gl_string, "}\n\n"); +} + +static inline void gl_write_functions(struct gl_shader_parser *glsp) +{ + size_t i; + for (i = 0; i < glsp->parser.funcs.num; i++) { + struct shader_func *func = glsp->parser.funcs.array+i; + gl_write_function(glsp, func); + } +} + +static void gl_write_main_storage_var(struct gl_shader_parser *glsp, + struct shader_var *var, const char *dst, const char *src, + bool input) +{ + struct shader_struct *st; + struct dstr dst_copy = {0}; + char ch_left = input ? '.' : '_'; + char ch_right = input ? '_' : '.'; + + if (dst) { + dstr_copy(&dst_copy, dst); + dstr_cat_ch(&dst_copy, ch_left); + } else { + dstr_copy(&dst_copy, "\t"); + } + + dstr_cat(&dst_copy, var->name); + + st = shader_parser_getstruct(&glsp->parser, var->type); + if (st) { + struct dstr src_copy = {0}; + size_t i; + + if (src) + dstr_copy(&src_copy, src); + dstr_cat(&src_copy, var->name); + dstr_cat_ch(&src_copy, ch_right); + + for (i = 0; i < st->vars.num; i++) { + struct shader_var *var = st->vars.array+i; + gl_write_main_storage_var(glsp, var, dst_copy.array, + src_copy.array, input); + } + + dstr_free(&src_copy); + } else { + if (!dstr_isempty(&dst_copy)) + dstr_cat_dstr(&glsp->gl_string, &dst_copy); + dstr_cat(&glsp->gl_string, " = "); + if (src) + dstr_cat(&glsp->gl_string, src); + dstr_cat(&glsp->gl_string, var->name); + dstr_cat(&glsp->gl_string, ";\n"); + } + + dstr_free(&dst_copy); +} + +static void gl_write_main_storage_output(struct gl_shader_parser *glsp, + bool input, const char *type) +{ + struct shader_var var = {0}; + + if (input) { + var.name = "inputval"; + var.type = (char*)type; + gl_write_main_storage_var(glsp, &var, NULL, NULL, true); + } else { + var.name = "outputval"; + var.type = (char*)type; + gl_write_main_storage_var(glsp, &var, NULL, NULL, false); + } +} + +static void gl_write_main(struct gl_shader_parser *glsp, + struct shader_func *main) +{ + size_t i; + dstr_cat(&glsp->gl_string, "void main(void)\n{\n"); + for (i = 0; i < main->params.num; i++) { + dstr_cat(&glsp->gl_string, "\t"); + dstr_cat(&glsp->gl_string, main->params.array[i].type); + dstr_cat(&glsp->gl_string, " "); + dstr_cat(&glsp->gl_string, main->params.array[i].name); + dstr_cat(&glsp->gl_string, "\n"); + } + + if (!main->mapping) { + dstr_cat(&glsp->gl_string, "\t"); + dstr_cat(&glsp->gl_string, main->return_type); + dstr_cat(&glsp->gl_string, " outputval;\n\n"); + } + + /* gl_write_main_storage(glsp, true, main->params.array[0].type); */ + gl_write_main_storage_var(glsp, main->params.array, NULL, + "inputval_", true); + + dstr_cat(&glsp->gl_string, "\n\toutputval = __main__("); + for (i = 0; i < main->params.num; i++) { + if (i) + dstr_cat(&glsp->gl_string, ", "); + dstr_cat(&glsp->gl_string, main->params.array[i].name); + } + dstr_cat(&glsp->gl_string, ");\n"); + + if (!main->mapping) { + dstr_cat(&glsp->gl_string, "\n"); + gl_write_main_storage_output(glsp, false, main->return_type); + } + + dstr_cat(&glsp->gl_string, "}\n"); } static bool gl_shader_buildstring(struct gl_shader_parser *glsp) @@ -221,7 +490,7 @@ static bool gl_shader_buildstring(struct gl_shader_parser *glsp) gl_write_outputs(glsp, main); gl_write_structs(glsp); gl_write_functions(glsp); - // gl_write_main(glsp); + gl_write_main(glsp, main); return true; } @@ -236,5 +505,8 @@ bool gl_shader_parse(struct gl_shader_parser *glsp, bfree(str); } + if (success) + success = gl_shader_buildstring(glsp); + return success; } diff --git a/libobs-opengl/gl-shaderparser.h b/libobs-opengl/gl-shaderparser.h index bcc4cb59d..0625a0ba7 100644 --- a/libobs-opengl/gl-shaderparser.h +++ b/libobs-opengl/gl-shaderparser.h @@ -29,7 +29,6 @@ struct gl_shader_parser { struct dstr gl_string; - struct dstr gl_main_func; struct shader_parser parser; }; diff --git a/libobs/graphics/effect-parser.c b/libobs/graphics/effect-parser.c index b51836975..56c462a51 100644 --- a/libobs/graphics/effect-parser.c +++ b/libobs/graphics/effect-parser.c @@ -971,8 +971,6 @@ static inline void ep_write_param(struct dstr *shader, struct ep_param *param, struct dstr new; dstr_init_copy(&new, param->name); darray_push_back(sizeof(struct dstr), used_params, &new); - - dstr_cat(shader, "uniform "); } dstr_cat(shader, param->type); diff --git a/libobs/graphics/shader-parser.c b/libobs/graphics/shader-parser.c index e8c33937c..a7c2bfe52 100644 --- a/libobs/graphics/shader-parser.c +++ b/libobs/graphics/shader-parser.c @@ -304,8 +304,7 @@ error: static inline int sp_check_for_keyword(struct shader_parser *sp, const char *keyword, bool *val) { - bool new_val; - new_val = token_is(&sp->cfp, keyword); + bool new_val = token_is(&sp->cfp, keyword); if (new_val) { if (!next_valid_token(&sp->cfp)) return PARSE_EOF; @@ -325,7 +324,7 @@ static inline int sp_parse_func_param(struct shader_parser *sp, struct shader_func *func, struct shader_var *var) { int errcode; - bool is_uniform; + bool is_uniform = false; if (!next_valid_token(&sp->cfp)) return PARSE_EOF; @@ -418,7 +417,7 @@ static void sp_parse_function(struct shader_parser *sp, char *type, char *name) if (errorcode != PARSE_SUCCESS) goto error; - func.return_mapping = mapping; + func.mapping = mapping; if (!next_valid_token(&sp->cfp)) goto error; diff --git a/libobs/graphics/shader-parser.h b/libobs/graphics/shader-parser.h index d2c1b9e03..d93c0795b 100644 --- a/libobs/graphics/shader-parser.h +++ b/libobs/graphics/shader-parser.h @@ -141,10 +141,10 @@ static inline void shader_struct_free(struct shader_struct *ss) struct shader_func { char *name; char *return_type; - char *return_mapping; + char *mapping; DARRAY(struct shader_var) params; - const struct cf_token *start, *end; + struct cf_token *start, *end; }; static inline void shader_func_init(struct shader_func *sf, @@ -153,7 +153,7 @@ static inline void shader_func_init(struct shader_func *sf, da_init(sf->params); sf->return_type = return_type; - sf->return_mapping = NULL; + sf->mapping = NULL; sf->name = name; sf->start = NULL; sf->end = NULL; @@ -168,7 +168,7 @@ static inline void shader_func_free(struct shader_func *sf) bfree(sf->name); bfree(sf->return_type); - bfree(sf->return_mapping); + bfree(sf->mapping); da_free(sf->params); }