diff options
-rw-r--r-- | src/glsl/ast.h | 6 | ||||
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 5 | ||||
-rw-r--r-- | src/glsl/ast_type.cpp | 81 | ||||
-rw-r--r-- | src/glsl/glsl_parser.yy | 57 | ||||
-rw-r--r-- | src/glsl/glsl_parser_extras.cpp | 6 | ||||
-rw-r--r-- | src/glsl/glsl_parser_extras.h | 7 |
6 files changed, 96 insertions, 66 deletions
diff --git a/src/glsl/ast.h b/src/glsl/ast.h index 9140ca13cda..c4f28b0cc90 100644 --- a/src/glsl/ast.h +++ b/src/glsl/ast.h @@ -587,6 +587,12 @@ struct ast_type_qualifier { bool merge_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state, ast_type_qualifier q); + + bool merge_in_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q, + ast_node* &node); + }; class ast_declarator_list; diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index e731d839d2a..f754652dc9c 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -2842,7 +2842,7 @@ handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, { unsigned num_vertices = 0; if (state->gs_input_prim_type_specified) { - num_vertices = vertices_per_prim(state->gs_input_prim_type); + num_vertices = vertices_per_prim(state->in_qualifier->prim_type); } /* Geometry shader input variables must be arrays. Caller should have @@ -5332,7 +5332,7 @@ ast_gs_input_layout::hir(exec_list *instructions, * was consistent with this one. */ if (state->gs_input_prim_type_specified && - state->gs_input_prim_type != this->prim_type) { + state->in_qualifier->prim_type != this->prim_type) { _mesa_glsl_error(&loc, state, "geometry shader input layout does not match" " previous declaration"); @@ -5353,7 +5353,6 @@ ast_gs_input_layout::hir(exec_list *instructions, } state->gs_input_prim_type_specified = true; - state->gs_input_prim_type = this->prim_type; /* If any shader inputs occurred before this declaration and did not * specify an array size, their size is determined now. diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp index 200566c6d3f..2f36cf43c11 100644 --- a/src/glsl/ast_type.cpp +++ b/src/glsl/ast_type.cpp @@ -198,3 +198,84 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, return true; } +bool +ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q, + ast_node* &node) +{ + void *mem_ctx = state; + bool create_gs_ast = false; + bool create_cs_ast = false; + + switch (state->stage) { + case MESA_SHADER_GEOMETRY: + if (q.flags.q.prim_type) { + /* Make sure this is a valid input primitive type. */ + switch (q.prim_type) { + case GL_POINTS: + case GL_LINES: + case GL_LINES_ADJACENCY: + case GL_TRIANGLES: + case GL_TRIANGLES_ADJACENCY: + break; + default: + _mesa_glsl_error(loc, state, + "invalid geometry shader input primitive type"); + break; + } + } + + create_gs_ast |= + q.flags.q.prim_type && + !state->in_qualifier->flags.q.prim_type; + break; + case MESA_SHADER_FRAGMENT: + if (q.flags.q.early_fragment_tests) { + state->early_fragment_tests = true; + } else { + _mesa_glsl_error(loc, state, "invalid input layout qualifier"); + } + break; + case MESA_SHADER_COMPUTE: + create_cs_ast |= + q.flags.q.local_size != 0 && + state->in_qualifier->flags.q.local_size == 0; + break; + default: + _mesa_glsl_error(loc, state, + "input layout qualifiers only valid in " + "geometry, fragment and compute shaders"); + break; + } + + /* Input layout qualifiers can be specified multiple + * times in separate declarations, as long as they match. + */ + if (this->flags.q.prim_type) { + if (q.flags.q.prim_type && + this->prim_type != q.prim_type) { + _mesa_glsl_error(loc, state, + "conflicting input primitive types specified"); + } + } else if (q.flags.q.prim_type) { + state->in_qualifier->flags.q.prim_type = 1; + state->in_qualifier->prim_type = q.prim_type; + } + + if (create_gs_ast) { + node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type); + } else if (create_cs_ast) { + /* Infer a local_size of 1 for every unspecified dimension */ + unsigned local_size[3]; + for (int i = 0; i < 3; i++) { + if (q.flags.q.local_size & (1 << i)) + local_size[i] = q.local_size[i]; + else + local_size[i] = 1; + } + node = new(mem_ctx) ast_cs_input_layout(*loc, local_size); + } + + return true; +} diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 369da5034d6..c3fa4555e14 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -2487,62 +2487,9 @@ layout_defaults: | layout_qualifier IN_TOK ';' { - void *ctx = state; $$ = NULL; - switch (state->stage) { - case MESA_SHADER_GEOMETRY: { - if (!$1.flags.q.prim_type) { - _mesa_glsl_error(& @1, state, - "input layout qualifiers must specify a primitive" - " type"); - } else { - /* Make sure this is a valid input primitive type. */ - switch ($1.prim_type) { - case GL_POINTS: - case GL_LINES: - case GL_LINES_ADJACENCY: - case GL_TRIANGLES: - case GL_TRIANGLES_ADJACENCY: - $$ = new(ctx) ast_gs_input_layout(@1, $1.prim_type); - break; - default: - _mesa_glsl_error(&@1, state, - "invalid geometry shader input primitive type"); - break; - } - } - } - break; - case MESA_SHADER_FRAGMENT: - if ($1.flags.q.early_fragment_tests) { - state->early_fragment_tests = true; - } else { - _mesa_glsl_error(& @1, state, "invalid input layout qualifier"); - } - break; - case MESA_SHADER_COMPUTE: { - if ($1.flags.q.local_size == 0) { - _mesa_glsl_error(& @1, state, - "input layout qualifiers must specify a local " - "size"); - } else { - /* Infer a local_size of 1 for every unspecified dimension */ - unsigned local_size[3]; - for (int i = 0; i < 3; i++) { - if ($1.flags.q.local_size & (1 << i)) - local_size[i] = $1.local_size[i]; - else - local_size[i] = 1; - } - $$ = new(ctx) ast_cs_input_layout(@1, local_size); - } - } - break; - default: - _mesa_glsl_error(& @1, state, - "input layout qualifiers only valid in " - "geometry, fragment and compute shaders"); - break; + if (!state->in_qualifier->merge_in_qualifier(& @1, state, $1, $$)) { + YYERROR; } } diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 901124d2c39..f102b11bc6d 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -202,8 +202,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->default_uniform_qualifier->flags.q.column_major = 1; this->gs_input_prim_type_specified = false; - this->gs_input_prim_type = GL_POINTS; this->gs_input_size = 0; + this->in_qualifier = new(this) ast_type_qualifier(); this->out_qualifier = new(this) ast_type_qualifier(); this->early_fragment_tests = false; memset(this->atomic_counter_offsets, 0, @@ -1348,7 +1348,7 @@ set_shader_inout_layout(struct gl_shader *shader, { if (shader->Stage != MESA_SHADER_GEOMETRY) { /* Should have been prevented by the parser. */ - assert(!state->gs_input_prim_type_specified); + assert(!state->in_qualifier->flags.i); assert(!state->out_qualifier->flags.i); } @@ -1364,7 +1364,7 @@ set_shader_inout_layout(struct gl_shader *shader, shader->Geom.VerticesOut = state->out_qualifier->max_vertices; if (state->gs_input_prim_type_specified) { - shader->Geom.InputType = state->gs_input_prim_type; + shader->Geom.InputType = state->in_qualifier->prim_type; } else { shader->Geom.InputType = PRIM_UNKNOWN; } diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index ad4ef014687..d98474e6572 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -190,11 +190,8 @@ struct _mesa_glsl_parse_state { */ bool gs_input_prim_type_specified; - /** - * If gs_input_prim_type_specified is true, the primitive type that was - * specified. Otherwise ignored. - */ - GLenum gs_input_prim_type; + /** Input layout qualifiers from GLSL 1.50. (geometry shader controls)*/ + struct ast_type_qualifier *in_qualifier; /** * True if a compute shader input local size was specified using a layout |