From ebcdbff6f1f6fa4749e88f9984b0df784a3d9a0c Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 16 Jul 2008 14:27:50 -0600 Subject: [PATCH] mesa: implement grammar/parsing for precision/invariant syntax Plus, fix some issues with pre-defined preprocessor symbols and version checking. --- .../shader/slang/library/slang_shader.syn | 71 +++++++++- .../shader/slang/library/slang_shader_syn.h | 29 ++++ src/mesa/shader/slang/slang_compile.c | 134 +++++++++++++++++- src/mesa/shader/slang/slang_preprocess.c | 27 ++++ 4 files changed, 251 insertions(+), 10 deletions(-) diff --git a/src/mesa/shader/slang/library/slang_shader.syn b/src/mesa/shader/slang/library/slang_shader.syn index 1764d1ae689..52a792ad179 100644 --- a/src/mesa/shader/slang/library/slang_shader.syn +++ b/src/mesa/shader/slang/library/slang_shader.syn @@ -51,10 +51,17 @@ /* revision number - increment after each change affecting emitted output */ .emtcode REVISION 3 -/* external declaration */ +/* external declaration (or precision or invariant stmt) */ .emtcode EXTERNAL_NULL 0 .emtcode EXTERNAL_FUNCTION_DEFINITION 1 .emtcode EXTERNAL_DECLARATION 2 +.emtcode DEFAULT_PRECISION 3 +.emtcode INVARIANT_STMT 4 + +/* precision */ +.emtcode PRECISION_LOW 0 +.emtcode PRECISION_MEDIUM 1 +.emtcode PRECISION_HIGH 2 /* declaration */ .emtcode DECLARATION_FUNCTION_PROTOTYPE 1 @@ -240,6 +247,9 @@ .errtext LBRACE_EXPECTED "2003: '{' expected but '$err_token$' found." .errtext LPAREN_EXPECTED "2004: '(' expected but '$err_token$' found." .errtext RPAREN_EXPECTED "2005: ')' expected but '$err_token$' found." +.errtext INVALID_PRECISION "2006: Invalid precision specifier '$err_token$'." +.errtext INVALID_PRECISION_TYPE "2007: Invalid precision type '$err_token$'." + /* tells whether the shader that is being parsed is a built-in shader or not */ /* 0 - normal behaviour */ @@ -1226,23 +1236,70 @@ asm_argument var_with_field variable_identifier .and dot .and field_selection .emit OP_FIELD; + /* - ::= - | -*/ + * ::= + * | + */ translation_unit optional_space .emit REVISION .and external_declaration .error INVALID_EXTERNAL_DECLARATION .and .loop external_declaration .and optional_space .and '\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL; + /* - ::= - | -*/ + * ::= + * | + */ external_declaration + precision_stmt .emit DEFAULT_PRECISION .or + invariant_stmt .emit INVARIANT_STMT .or function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or declaration .emit EXTERNAL_DECLARATION; + +/* + * ::= "precision" + */ +precision_stmt + "precision" .and space .and precision .error INVALID_PRECISION .and space .and prectype .error INVALID_PRECISION_TYPE .and semicolon; + +/* + * ::= "lowp" + * | "mediump" + * | "highp" + */ +precision + "lowp" .emit PRECISION_LOW .or + "mediump" .emit PRECISION_MEDIUM .or + "highp" .emit PRECISION_HIGH; + +/* + * ::= "int" + * | "float" + * | "a sampler type" + */ +prectype + "int" .emit TYPE_SPECIFIER_INT .or + "float" .emit TYPE_SPECIFIER_FLOAT .or + "sampler1D" .emit TYPE_SPECIFIER_SAMPLER1D .or + "sampler2D" .emit TYPE_SPECIFIER_SAMPLER2D .or + "sampler3D" .emit TYPE_SPECIFIER_SAMPLER3D .or + "samplerCube" .emit TYPE_SPECIFIER_SAMPLERCUBE .or + "sampler1DShadow" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or + "sampler2DShadow" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or + "sampler2DRect" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or + "sampler2DRectShadow" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW; + + +/* + * ::= "invariant" identifier; + */ +invariant_stmt + "invariant" .and space .and identifier .and semicolon; + + + /* :: */ diff --git a/src/mesa/shader/slang/library/slang_shader_syn.h b/src/mesa/shader/slang/library/slang_shader_syn.h index fe37adcac4a..c0fef6e4e3d 100644 --- a/src/mesa/shader/slang/library/slang_shader_syn.h +++ b/src/mesa/shader/slang/library/slang_shader_syn.h @@ -6,6 +6,11 @@ ".emtcode EXTERNAL_NULL 0\n" ".emtcode EXTERNAL_FUNCTION_DEFINITION 1\n" ".emtcode EXTERNAL_DECLARATION 2\n" +".emtcode DEFAULT_PRECISION 3\n" +".emtcode INVARIANT_STMT 4\n" +".emtcode PRECISION_LOW 0\n" +".emtcode PRECISION_MEDIUM 1\n" +".emtcode PRECISION_HIGH 2\n" ".emtcode DECLARATION_FUNCTION_PROTOTYPE 1\n" ".emtcode DECLARATION_INIT_DECLARATOR_LIST 2\n" ".emtcode FUNCTION_ORDINARY 0\n" @@ -41,6 +46,7 @@ ".emtcode TYPE_QUALIFIER_UNIFORM 4\n" ".emtcode TYPE_QUALIFIER_FIXEDOUTPUT 5\n" ".emtcode TYPE_QUALIFIER_FIXEDINPUT 6\n" +".emtcode TYPE_QUALIFIER_INVARIANT_VARYING 7\n" ".emtcode TYPE_SPECIFIER_VOID 0\n" ".emtcode TYPE_SPECIFIER_BOOL 1\n" ".emtcode TYPE_SPECIFIER_BVEC2 2\n" @@ -137,6 +143,8 @@ ".errtext LBRACE_EXPECTED \"2003: '{' expected but '$err_token$' found.\"\n" ".errtext LPAREN_EXPECTED \"2004: '(' expected but '$err_token$' found.\"\n" ".errtext RPAREN_EXPECTED \"2005: ')' expected but '$err_token$' found.\"\n" +".errtext INVALID_PRECISION \"2006: Invalid precision specifier '$err_token$'.\"\n" +".errtext INVALID_PRECISION_TYPE \"2007: Invalid precision type '$err_token$'.\"\n" ".regbyte parsing_builtin 0\n" ".regbyte shader_type 0\n" "variable_identifier\n" @@ -597,8 +605,29 @@ " .loop external_declaration .and optional_space .and\n" " '\\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL;\n" "external_declaration\n" +" precision_stmt .emit DEFAULT_PRECISION .or\n" +" invariant_stmt .emit INVARIANT_STMT .or\n" " function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or\n" " declaration .emit EXTERNAL_DECLARATION;\n" +"precision_stmt\n" +" \"precision\" .and space .and precision .error INVALID_PRECISION .and space .and prectype .error INVALID_PRECISION_TYPE .and semicolon;\n" +"precision\n" +" \"lowp\" .emit PRECISION_LOW .or\n" +" \"mediump\" .emit PRECISION_MEDIUM .or\n" +" \"highp\" .emit PRECISION_HIGH;\n" +"prectype\n" +" \"int\" .emit TYPE_SPECIFIER_INT .or\n" +" \"float\" .emit TYPE_SPECIFIER_FLOAT .or\n" +" \"sampler1D\" .emit TYPE_SPECIFIER_SAMPLER1D .or\n" +" \"sampler2D\" .emit TYPE_SPECIFIER_SAMPLER2D .or\n" +" \"sampler3D\" .emit TYPE_SPECIFIER_SAMPLER3D .or\n" +" \"samplerCube\" .emit TYPE_SPECIFIER_SAMPLERCUBE .or\n" +" \"sampler1DShadow\" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or\n" +" \"sampler2DShadow\" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or\n" +" \"sampler2DRect\" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or\n" +" \"sampler2DRectShadow\" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW;\n" +"invariant_stmt\n" +" \"invariant\" .and space .and identifier .and semicolon;\n" "function_definition\n" " function_prototype .and compound_statement_no_new_scope;\n" "digit_oct\n" diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index 29c5ca2f4b2..fd5d4afacb6 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -56,6 +56,9 @@ */ +/** re-defined below, should be the same though */ +#define TYPE_SPECIFIER_COUNT 32 + /** * Allocate storage for a variable of 'size' bytes from given pool. @@ -129,6 +132,7 @@ typedef struct slang_parse_ctx_ GLboolean global_scope; /**< Is object being declared a global? */ slang_atom_pool *atoms; slang_unit_type type; /**< Vertex vs. Fragment */ + GLuint version; /**< user-specified (or default) #version */ } slang_parse_ctx; /* slang_output_ctx */ @@ -141,6 +145,7 @@ typedef struct slang_output_ctx_ slang_var_pool *global_pool; struct gl_program *program; slang_var_table *vartable; + GLuint default_precision[TYPE_SPECIFIER_COUNT]; } slang_output_ctx; /* _slang_compile() */ @@ -525,7 +530,7 @@ parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual) #define TYPE_SPECIFIER_MAT42 29 #define TYPE_SPECIFIER_MAT34 30 #define TYPE_SPECIFIER_MAT43 31 - +#define TYPE_SPECIFIER_COUNT 32 static int parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O, @@ -1817,10 +1822,111 @@ parse_declaration(slang_parse_ctx * C, slang_output_ctx * O) return 1; } -/* external declaration */ + +#define PRECISION_LOW 0 +#define PRECISION_MEDIUM 1 +#define PRECISION_HIGH 2 + +static int +parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O) +{ +#if FEATURE_es2_glsl + int precision, type; + + precision = *C->I++; + switch (precision) { + case PRECISION_LOW: + case PRECISION_MEDIUM: + case PRECISION_HIGH: + /* OK */ + break; + default: + _mesa_problem(NULL, "unexpected precision %d at %s:%d\n", + precision, __FILE__, __LINE__); + return 0; + } + + type = *C->I++; + switch (type) { + case TYPE_SPECIFIER_FLOAT: + case TYPE_SPECIFIER_INT: + case TYPE_SPECIFIER_SAMPLER1D: + case TYPE_SPECIFIER_SAMPLER2D: + case TYPE_SPECIFIER_SAMPLER3D: + case TYPE_SPECIFIER_SAMPLERCUBE: + case TYPE_SPECIFIER_SAMPLER1DSHADOW: + case TYPE_SPECIFIER_SAMPLER2DSHADOW: + case TYPE_SPECIFIER_SAMPLER2DRECT: + case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW: + /* OK */ + break; + default: + _mesa_problem(NULL, "unexpected type %d at %s:%d\n", + type, __FILE__, __LINE__); + return 0; + } + + assert(type < TYPE_SPECIFIER_COUNT); + O->default_precision[type] = precision; + + return 1; +#else + slang_info_log_error(C->L, "syntax error at \"precision\""); + return 0; +#endif +} + + +/** + * Initialize the default precision for all types. + * XXX this info isn't used yet. + */ +static void +init_default_precision(slang_output_ctx *O, slang_unit_type type) +{ + GLuint i; + for (i = 0; i < TYPE_SPECIFIER_COUNT; i++) { +#if FEATURE_es2_glsl + O->default_precision[i] = PRECISION_LOW; +#else + O->default_precision[i] = PRECISION_HIGH; +#endif + } +#if FEATURE_es2_glsl + if (type == SLANG_UNIT_VERTEX_SHADER) { + O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH; + O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH; + } + else { + O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_MEDIUM; + } +#endif +} + + +static int +parse_invariant(slang_parse_ctx * C, slang_output_ctx * O) +{ + if (C->version >= 120 || FEATURE_es2_glsl) { + slang_atom *a = parse_identifier(C); + /* XXX not doing anything with this var yet */ + /*printf("ID: %s\n", (char*) a);*/ + return a ? 1 : 0; + } + else { + slang_info_log_error(C->L, "syntax error at \"invariant\""); + return 0; + } +} + + +/* external declaration or default precision specifier */ #define EXTERNAL_NULL 0 #define EXTERNAL_FUNCTION_DEFINITION 1 #define EXTERNAL_DECLARATION 2 +#define DEFAULT_PRECISION 3 +#define INVARIANT_STMT 4 + static GLboolean parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit, @@ -1843,6 +1949,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit, } /* setup output context */ + init_default_precision(&o, unit->type); o.funs = &unit->funs; o.structs = &unit->structs; o.vars = &unit->vars; @@ -1868,6 +1975,12 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit, case EXTERNAL_DECLARATION: success = parse_declaration(C, &o); break; + case DEFAULT_PRECISION: + success = parse_default_precision(C, &o); + break; + case INVARIANT_STMT: + success = parse_invariant(C, &o); + break; default: success = GL_FALSE; } @@ -1904,6 +2017,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit, static GLboolean compile_binary(const byte * prod, slang_code_unit * unit, + GLuint version, slang_unit_type type, slang_info_log * infolog, slang_code_unit * builtin, slang_code_unit * downlink, struct gl_program *program) @@ -1919,6 +2033,7 @@ compile_binary(const byte * prod, slang_code_unit * unit, C.global_scope = GL_TRUE; C.atoms = &unit->object->atompool; C.type = type; + C.version = version; if (!check_revision(&C)) return GL_FALSE; @@ -1946,6 +2061,8 @@ compile_with_grammar(grammar id, const char *source, slang_code_unit * unit, #if FEATURE_ARB_shading_language_120 maxVersion = 120; +#elif FEATURE_es2_glsl + maxVersion = 100; #else maxVersion = 110; #endif @@ -1995,7 +2112,7 @@ compile_with_grammar(grammar id, const char *source, slang_code_unit * unit, slang_string_free(&preprocessed); /* Syntax is okay - translate it to internal representation. */ - if (!compile_binary(prod, unit, type, infolog, builtin, + if (!compile_binary(prod, unit, version, type, infolog, builtin, &builtin[SLANG_BUILTIN_TOTAL - 1], program)) { grammar_alloc_free(prod); @@ -2039,6 +2156,7 @@ compile_object(grammar * id, const char *source, slang_code_object * object, struct gl_program *program) { slang_code_unit *builtins = NULL; + GLuint base_version = 110; /* load GLSL grammar */ *id = grammar_load_from_text((const byte *) (slang_shader_syn)); @@ -2066,6 +2184,7 @@ compile_object(grammar * id, const char *source, slang_code_object * object, /* compile core functionality first */ if (!compile_binary(slang_core_gc, &object->builtin[SLANG_BUILTIN_CORE], + base_version, SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL, NULL, NULL)) return GL_FALSE; @@ -2073,6 +2192,7 @@ compile_object(grammar * id, const char *source, slang_code_object * object, #if FEATURE_ARB_shading_language_120 if (!compile_binary(slang_120_core_gc, &object->builtin[SLANG_BUILTIN_120_CORE], + 120, SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL, &object->builtin[SLANG_BUILTIN_CORE], NULL)) return GL_FALSE; @@ -2081,6 +2201,11 @@ compile_object(grammar * id, const char *source, slang_code_object * object, /* compile common functions and variables, link to core */ if (!compile_binary(slang_common_builtin_gc, &object->builtin[SLANG_BUILTIN_COMMON], +#if FEATURE_ARB_shading_language_120 + 120, +#else + base_version, +#endif SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL, #if FEATURE_ARB_shading_language_120 &object->builtin[SLANG_BUILTIN_120_CORE], @@ -2094,12 +2219,14 @@ compile_object(grammar * id, const char *source, slang_code_object * object, if (type == SLANG_UNIT_FRAGMENT_SHADER) { if (!compile_binary(slang_fragment_builtin_gc, &object->builtin[SLANG_BUILTIN_TARGET], + base_version, SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL, &object->builtin[SLANG_BUILTIN_COMMON], NULL)) return GL_FALSE; #if FEATURE_ARB_shading_language_120 if (!compile_binary(slang_120_fragment_gc, &object->builtin[SLANG_BUILTIN_TARGET], + 120, SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL, &object->builtin[SLANG_BUILTIN_COMMON], NULL)) return GL_FALSE; @@ -2108,6 +2235,7 @@ compile_object(grammar * id, const char *source, slang_code_object * object, else if (type == SLANG_UNIT_VERTEX_SHADER) { if (!compile_binary(slang_vertex_builtin_gc, &object->builtin[SLANG_BUILTIN_TARGET], + base_version, SLANG_UNIT_VERTEX_BUILTIN, infolog, NULL, &object->builtin[SLANG_BUILTIN_COMMON], NULL)) return GL_FALSE; diff --git a/src/mesa/shader/slang/slang_preprocess.c b/src/mesa/shader/slang/slang_preprocess.c index 1645afcc18f..d3f412c211e 100644 --- a/src/mesa/shader/slang/slang_preprocess.c +++ b/src/mesa/shader/slang/slang_preprocess.c @@ -729,6 +729,14 @@ expand (expand_state *e, pp_symbols *symbols) slang_string_pushi (e->output, e->state->version); slang_string_pushc (e->output, ' '); } +#if FEATURE_es2_glsl + else if (_mesa_strcmp (id, "GL_ES") == 0 || + _mesa_strcmp (id, "GL_FRAGMENT_PRECISION_HIGH") == 0) { + slang_string_pushc (e->output, ' '); + slang_string_pushi (e->output, '1'); + slang_string_pushc (e->output, ' '); + } +#endif else { pp_symbol *symbol; @@ -829,6 +837,16 @@ static GLboolean preprocess_source (slang_string *output, const char *source, grammar pid, grammar eid, slang_info_log *elog) { + static const char *predefined[] = { + "__FILE__", + "__LINE__", + "__VERSION__", +#if FEATURE_es2_glsl + "GL_ES", + "GL_FRAGMENT_PRECISION_HIGH", +#endif + NULL + }; byte *prod; GLuint size, i; pp_state state; @@ -840,6 +858,15 @@ preprocess_source (slang_string *output, const char *source, grammar pid, gramma pp_state_init (&state, elog); + /* add the predefined symbols to the symbol table */ + for (i = 0; predefined[i]; i++) { + pp_symbol *symbol = NULL; + symbol = pp_symbols_push(&state.symbols); + assert(symbol); + slang_string_pushs(&symbol->name, + predefined[i], _mesa_strlen(predefined[i])); + } + i = 0; while (i < size) { if (prod[i] != ESCAPE_TOKEN) { -- 2.30.2