summaryrefslogtreecommitdiff
path: root/src/mesa/shader/slang
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2008-07-29 17:12:19 -0600
committerBrian Paul <brian.paul@tungstengraphics.com>2008-07-29 17:12:19 -0600
commit5bfbcf7265dfc72d85f6adbf3b243355b16334d9 (patch)
treecd1d54d6a7c7c5ec60ca47f95c43b4efa2c073b5 /src/mesa/shader/slang
parentc3ad1761586c640ba7d4060c4a6917ce61078cf9 (diff)
mesa: implement grammar/parsing for precision/invariant syntax
Plus, fix some issues with pre-defined preprocessor symbols and version checking.
Diffstat (limited to 'src/mesa/shader/slang')
-rw-r--r--src/mesa/shader/slang/library/slang_shader.syn71
-rw-r--r--src/mesa/shader/slang/library/slang_shader_syn.h29
-rw-r--r--src/mesa/shader/slang/slang_compile.c134
-rw-r--r--src/mesa/shader/slang/slang_preprocess.c27
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 1764d1ae68..52a792ad17 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> ::= <external_declaration>
- | <translation_unit> <external_declaration>
-*/
+ * <translation_unit> ::= <external_declaration>
+ * | <translation_unit> <external_declaration>
+ */
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> ::= <function_definition>
- | <declaration>
-*/
+ * <external_declaration> ::= <function_definition>
+ * | <declaration>
+ */
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_stmt> ::= "precision" <precision> <prectype>
+ */
+precision_stmt
+ "precision" .and space .and precision .error INVALID_PRECISION .and space .and prectype .error INVALID_PRECISION_TYPE .and semicolon;
+
+/*
+ * <precision> ::= "lowp"
+ * | "mediump"
+ * | "highp"
+ */
+precision
+ "lowp" .emit PRECISION_LOW .or
+ "mediump" .emit PRECISION_MEDIUM .or
+ "highp" .emit PRECISION_HIGH;
+
+/*
+ * <prectype> ::= "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_stmt> ::= "invariant" identifier;
+ */
+invariant_stmt
+ "invariant" .and space .and identifier .and semicolon;
+
+
+
/*
<function_definition> :: <function_prototype> <compound_statement_no_new_scope>
*/
diff --git a/src/mesa/shader/slang/library/slang_shader_syn.h b/src/mesa/shader/slang/library/slang_shader_syn.h
index fe37adcac4..c0fef6e4e3 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 20bca01c46..a4e7b4a35b 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 1645afcc18..d3f412c211 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) {