diff options
author | Fabian Bieler <[email protected]> | 2014-03-20 22:44:43 +0100 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2015-07-23 00:59:26 +0200 |
commit | 497eb295838baccde1420adfcc4ef7e8fdddd774 (patch) | |
tree | 517e56ea50330d128fca0ae95b4f7bf6a324fa6a | |
parent | 206af9d049cab6e794db5abf63e3d11281343423 (diff) |
glsl: add tessellation shader parsing support (v2)
v2: Fixed things that Ken suggested.
Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r-- | src/glsl/ast.h | 54 | ||||
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 166 | ||||
-rw-r--r-- | src/glsl/ast_type.cpp | 112 | ||||
-rw-r--r-- | src/glsl/glsl_parser.yy | 122 | ||||
-rw-r--r-- | src/glsl/glsl_parser_extras.cpp | 39 | ||||
-rw-r--r-- | src/glsl/glsl_parser_extras.h | 31 |
6 files changed, 476 insertions, 48 deletions
diff --git a/src/glsl/ast.h b/src/glsl/ast.h index 49212298e16..e185ed11e75 100644 --- a/src/glsl/ast.h +++ b/src/glsl/ast.h @@ -515,6 +515,17 @@ struct ast_type_qualifier { unsigned stream:1; /**< Has stream value assigned */ unsigned explicit_stream:1; /**< stream value assigned explicitly by shader code */ /** \} */ + + /** \name Layout qualifiers for GL_ARB_tessellation_shader */ + /** \{ */ + /* tess eval input layout */ + /* gs prim_type reused for primitive mode */ + unsigned vertex_spacing:1; + unsigned ordering:1; + unsigned point_mode:1; + /* tess control output layout */ + unsigned vertices:1; + /** \} */ } /** \brief Set of flags, accessed by name. */ q; @@ -550,7 +561,10 @@ struct ast_type_qualifier { /** Stream in GLSL 1.50 geometry shaders. */ unsigned stream; - /** Input or output primitive type in GLSL 1.50 geometry shaders */ + /** + * Input or output primitive type in GLSL 1.50 geometry shaders + * and tessellation shaders. + */ GLenum prim_type; /** @@ -577,6 +591,18 @@ struct ast_type_qualifier { */ int local_size[3]; + /** Tessellation evaluation shader: vertex spacing (equal, fractional even/odd) */ + GLenum vertex_spacing; + + /** Tessellation evaluation shader: vertex ordering (CW or CCW) */ + GLenum ordering; + + /** Tessellation evaluation shader: point mode */ + bool point_mode; + + /** Tessellation control shader: number of output vertices */ + int vertices; + /** * Image format specified with an ARB_shader_image_load_store * layout qualifier. @@ -632,6 +658,11 @@ struct ast_type_qualifier { _mesa_glsl_parse_state *state, ast_type_qualifier q); + bool merge_out_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q, + ast_node* &node); + bool merge_in_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state, ast_type_qualifier q, @@ -1032,6 +1063,27 @@ public: /** + * AST node representing a declaration of the output layout for tessellation + * control shaders. + */ +class ast_tcs_output_layout : public ast_node +{ +public: + ast_tcs_output_layout(const struct YYLTYPE &locp, int vertices) + : vertices(vertices) + { + set_location(locp); + } + + virtual ir_rvalue *hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state); + +private: + const int vertices; +}; + + +/** * AST node representing a declaration of the input layout for geometry * shaders. */ diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index b5c4ed9c667..391bee0b53f 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -79,6 +79,7 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) state->toplevel_ir = instructions; state->gs_input_prim_type_specified = false; + state->tcs_output_vertices_specified = false; state->cs_input_local_size_specified = false; /* Section 4.2 of the GLSL 1.20 specification states: @@ -2231,6 +2232,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual, * input output * ----- ------ * vertex explicit_loc sso + * tess control sso sso + * tess eval sso sso * geometry sso sso * fragment sso explicit_loc */ @@ -2253,6 +2256,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual, fail = true; break; + case MESA_SHADER_TESS_CTRL: + case MESA_SHADER_TESS_EVAL: case MESA_SHADER_GEOMETRY: if (var->data.mode == ir_var_shader_in || var->data.mode == ir_var_shader_out) { if (!state->check_separate_shader_objects_allowed(loc, var)) @@ -2312,6 +2317,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual, : (qual->location + VARYING_SLOT_VAR0); break; + case MESA_SHADER_TESS_CTRL: + case MESA_SHADER_TESS_EVAL: case MESA_SHADER_GEOMETRY: var->data.location = qual->location + VARYING_SLOT_VAR0; break; @@ -2592,7 +2599,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, case MESA_SHADER_VERTEX: if (var->data.mode == ir_var_shader_out) var->data.invariant = true; - break; + break; + case MESA_SHADER_TESS_CTRL: + case MESA_SHADER_TESS_EVAL: case MESA_SHADER_GEOMETRY: if ((var->data.mode == ir_var_shader_in) || (var->data.mode == ir_var_shader_out)) @@ -3132,30 +3141,13 @@ process_initializer(ir_variable *var, ast_declaration *decl, return result; } - -/** - * Do additional processing necessary for geometry shader input declarations - * (this covers both interface blocks arrays and bare input variables). - */ static void -handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, - YYLTYPE loc, ir_variable *var) +validate_layout_qualifier_vertex_count(struct _mesa_glsl_parse_state *state, + YYLTYPE loc, ir_variable *var, + unsigned num_vertices, + unsigned *size, + const char *var_category) { - unsigned num_vertices = 0; - if (state->gs_input_prim_type_specified) { - num_vertices = vertices_per_prim(state->in_qualifier->prim_type); - } - - /* Geometry shader input variables must be arrays. Caller should have - * reported an error for this. - */ - if (!var->type->is_array()) { - assert(state->error); - - /* To avoid cascading failures, short circuit the checks below. */ - return; - } - if (var->type->is_unsized_array()) { /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec says: * @@ -3165,6 +3157,8 @@ handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, * * Followed by a table mapping each allowed input layout qualifier to * the corresponding input length. + * + * Similarly for tessellation control shader outputs. */ if (num_vertices != 0) var->type = glsl_type::get_array_instance(var->type->fields.array, @@ -3191,22 +3185,63 @@ handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, */ if (num_vertices != 0 && var->type->length != num_vertices) { _mesa_glsl_error(&loc, state, - "geometry shader input size contradicts previously" - " declared layout (size is %u, but layout requires a" - " size of %u)", var->type->length, num_vertices); - } else if (state->gs_input_size != 0 && - var->type->length != state->gs_input_size) { + "%s size contradicts previously declared layout " + "(size is %u, but layout requires a size of %u)", + var_category, var->type->length, num_vertices); + } else if (*size != 0 && var->type->length != *size) { _mesa_glsl_error(&loc, state, - "geometry shader input sizes are " - "inconsistent (size is %u, but a previous " - "declaration has size %u)", - var->type->length, state->gs_input_size); + "%s sizes are inconsistent (size is %u, but a " + "previous declaration has size %u)", + var_category, var->type->length, *size); } else { - state->gs_input_size = var->type->length; + *size = var->type->length; } } } +static void +handle_tess_ctrl_shader_output_decl(struct _mesa_glsl_parse_state *state, + YYLTYPE loc, ir_variable *var) +{ + unsigned num_vertices = 0; + + if (state->tcs_output_vertices_specified) { + num_vertices = state->out_qualifier->vertices; + } + + validate_layout_qualifier_vertex_count(state, loc, var, num_vertices, + &state->tcs_output_size, + "geometry shader input"); +} + +/** + * Do additional processing necessary for geometry shader input declarations + * (this covers both interface blocks arrays and bare input variables). + */ +static void +handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, + YYLTYPE loc, ir_variable *var) +{ + unsigned num_vertices = 0; + + if (state->gs_input_prim_type_specified) { + num_vertices = vertices_per_prim(state->in_qualifier->prim_type); + } + + /* Geometry shader input variables must be arrays. Caller should have + * reported an error for this. + */ + if (!var->type->is_array()) { + assert(state->error); + + /* To avoid cascading failures, short circuit the checks below. */ + return; + } + + validate_layout_qualifier_vertex_count(state, loc, var, num_vertices, + &state->gs_input_size, + "geometry shader input"); +} void validate_identifier(const char *identifier, YYLTYPE loc, @@ -3796,6 +3831,10 @@ ast_declarator_list::hir(exec_list *instructions, } } } + + if (state->stage == MESA_SHADER_TESS_CTRL) { + handle_tess_ctrl_shader_output_decl(state, loc, var); + } } /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES, @@ -6059,6 +6098,67 @@ ast_interface_block::hir(exec_list *instructions, ir_rvalue * +ast_tcs_output_layout::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + YYLTYPE loc = this->get_location(); + + /* If any tessellation control output layout declaration preceded this + * one, make sure it was consistent with this one. + */ + if (state->tcs_output_vertices_specified && + state->out_qualifier->vertices != this->vertices) { + _mesa_glsl_error(&loc, state, + "tessellation control shader output layout does not " + "match previous declaration"); + return NULL; + } + + /* If any shader outputs occurred before this declaration and specified an + * array size, make sure the size they specified is consistent with the + * primitive type. + */ + unsigned num_vertices = this->vertices; + if (state->tcs_output_size != 0 && state->tcs_output_size != num_vertices) { + _mesa_glsl_error(&loc, state, + "this tessellation control shader output layout " + "specifies %u vertices, but a previous output " + "is declared with size %u", + num_vertices, state->tcs_output_size); + return NULL; + } + + state->tcs_output_vertices_specified = true; + + /* If any shader outputs occurred before this declaration and did not + * specify an array size, their size is determined now. + */ + foreach_in_list (ir_instruction, node, instructions) { + ir_variable *var = node->as_variable(); + if (var == NULL || var->data.mode != ir_var_shader_out) + continue; + + /* Note: Not all tessellation control shader output are arrays. */ + if (!var->type->is_unsized_array()) + continue; + + if (var->data.max_array_access >= num_vertices) { + _mesa_glsl_error(&loc, state, + "this tessellation control shader output layout " + "specifies %u vertices, but an access to element " + "%u of output `%s' already exists", num_vertices, + var->data.max_array_access, var->name); + } else { + var->type = glsl_type::get_array_instance(var->type->fields.array, + num_vertices); + } + } + + return NULL; +} + + +ir_rvalue * ast_gs_input_layout::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp index fa4806af1c0..f5c08d81e5f 100644 --- a/src/glsl/ast_type.cpp +++ b/src/glsl/ast_type.cpp @@ -212,6 +212,44 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, } } + if (q.flags.q.vertices) { + if (this->flags.q.vertices && this->vertices != q.vertices) { + _mesa_glsl_error(loc, state, + "tessellation control shader set conflicting " + "vertices (%d and %d)", + this->vertices, q.vertices); + return false; + } + this->vertices = q.vertices; + } + + if (q.flags.q.vertex_spacing) { + if (this->flags.q.vertex_spacing && this->vertex_spacing != q.vertex_spacing) { + _mesa_glsl_error(loc, state, + "conflicting vertex spacing used"); + return false; + } + this->vertex_spacing = q.vertex_spacing; + } + + if (q.flags.q.ordering) { + if (this->flags.q.ordering && this->ordering != q.ordering) { + _mesa_glsl_error(loc, state, + "conflicting ordering used"); + return false; + } + this->ordering = q.ordering; + } + + if (q.flags.q.point_mode) { + if (this->flags.q.point_mode && this->point_mode != q.point_mode) { + _mesa_glsl_error(loc, state, + "conflicting point mode used"); + return false; + } + this->point_mode = q.point_mode; + } + if ((q.flags.i & ubo_mat_mask.flags.i) != 0) this->flags.i &= ~ubo_mat_mask.flags.i; if ((q.flags.i & ubo_layout_mask.flags.i) != 0) @@ -257,6 +295,22 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, } bool +ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q, + ast_node* &node) +{ + void *mem_ctx = state; + const bool r = this->merge_qualifier(loc, state, q); + + if (state->stage == MESA_SHADER_TESS_CTRL) { + node = new(mem_ctx) ast_tcs_output_layout(*loc, q.vertices); + } + + return r; +} + +bool ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state, ast_type_qualifier q, @@ -269,6 +323,27 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, valid_in_mask.flags.i = 0; switch (state->stage) { + case MESA_SHADER_TESS_EVAL: + if (q.flags.q.prim_type) { + /* Make sure this is a valid input primitive type. */ + switch (q.prim_type) { + case GL_TRIANGLES: + case GL_QUADS: + case GL_ISOLINES: + break; + default: + _mesa_glsl_error(loc, state, + "invalid tessellation evaluation " + "shader input primitive type"); + break; + } + } + + valid_in_mask.flags.q.prim_type = 1; + valid_in_mask.flags.q.vertex_spacing = 1; + valid_in_mask.flags.q.ordering = 1; + valid_in_mask.flags.q.point_mode = 1; + break; case MESA_SHADER_GEOMETRY: if (q.flags.q.prim_type) { /* Make sure this is a valid input primitive type. */ @@ -324,7 +399,9 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, if (q.flags.q.prim_type && this->prim_type != q.prim_type) { _mesa_glsl_error(loc, state, - "conflicting input primitive types specified"); + "conflicting input primitive %s specified", + state->stage == MESA_SHADER_GEOMETRY ? + "type" : "mode"); } } else if (q.flags.q.prim_type) { state->in_qualifier->flags.q.prim_type = 1; @@ -346,6 +423,39 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, state->fs_early_fragment_tests = true; } + if (this->flags.q.vertex_spacing) { + if (q.flags.q.vertex_spacing && + this->vertex_spacing != q.vertex_spacing) { + _mesa_glsl_error(loc, state, + "conflicting vertex spacing specified"); + } + } else if (q.flags.q.vertex_spacing) { + this->flags.q.vertex_spacing = 1; + this->vertex_spacing = q.vertex_spacing; + } + + if (this->flags.q.ordering) { + if (q.flags.q.ordering && + this->ordering != q.ordering) { + _mesa_glsl_error(loc, state, + "conflicting ordering specified"); + } + } else if (q.flags.q.ordering) { + this->flags.q.ordering = 1; + this->ordering = q.ordering; + } + + if (this->flags.q.point_mode) { + if (q.flags.q.point_mode && + this->point_mode != q.point_mode) { + _mesa_glsl_error(loc, state, + "conflicting point mode specified"); + } + } else if (q.flags.q.point_mode) { + this->flags.q.point_mode = 1; + this->point_mode = q.point_mode; + } + if (create_gs_ast) { node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type); } else if (create_cs_ast) { diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 37c44014ba7..494907703ba 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -1385,6 +1385,89 @@ layout_qualifier_id: } } + /* Layout qualifiers for tessellation evaluation shaders. */ + if (!$$.flags.i) { + struct { + const char *s; + GLenum e; + } map[] = { + /* triangles already parsed by gs-specific code */ + { "quads", GL_QUADS }, + { "isolines", GL_ISOLINES }, + }; + for (unsigned i = 0; i < ARRAY_SIZE(map); i++) { + if (match_layout_qualifier($1, map[i].s, state) == 0) { + $$.flags.q.prim_type = 1; + $$.prim_type = map[i].e; + break; + } + } + + if ($$.flags.i && + !state->ARB_tessellation_shader_enable && + !state->is_version(400, 0)) { + _mesa_glsl_error(& @1, state, + "primitive mode qualifier `%s' requires " + "GLSL 4.00 or ARB_tessellation_shader", $1); + } + } + if (!$$.flags.i) { + struct { + const char *s; + GLenum e; + } map[] = { + { "equal_spacing", GL_EQUAL }, + { "fractional_odd_spacing", GL_FRACTIONAL_ODD }, + { "fractional_even_spacing", GL_FRACTIONAL_EVEN }, + }; + for (unsigned i = 0; i < ARRAY_SIZE(map); i++) { + if (match_layout_qualifier($1, map[i].s, state) == 0) { + $$.flags.q.vertex_spacing = 1; + $$.vertex_spacing = map[i].e; + break; + } + } + + if ($$.flags.i && + !state->ARB_tessellation_shader_enable && + !state->is_version(400, 0)) { + _mesa_glsl_error(& @1, state, + "vertex spacing qualifier `%s' requires " + "GLSL 4.00 or ARB_tessellation_shader", $1); + } + } + if (!$$.flags.i) { + if (match_layout_qualifier($1, "cw", state) == 0) { + $$.flags.q.ordering = 1; + $$.ordering = GL_CW; + } else if (match_layout_qualifier($1, "ccw", state) == 0) { + $$.flags.q.ordering = 1; + $$.ordering = GL_CCW; + } + + if ($$.flags.i && + !state->ARB_tessellation_shader_enable && + !state->is_version(400, 0)) { + _mesa_glsl_error(& @1, state, + "ordering qualifier `%s' requires " + "GLSL 4.00 or ARB_tessellation_shader", $1); + } + } + if (!$$.flags.i) { + if (match_layout_qualifier($1, "point_mode", state) == 0) { + $$.flags.q.point_mode = 1; + $$.point_mode = true; + } + + if ($$.flags.i && + !state->ARB_tessellation_shader_enable && + !state->is_version(400, 0)) { + _mesa_glsl_error(& @1, state, + "qualifier `point_mode' requires " + "GLSL 4.00 or ARB_tessellation_shader"); + } + } + if (!$$.flags.i) { _mesa_glsl_error(& @1, state, "unrecognized layout identifier " "`%s'", $1); @@ -1522,6 +1605,30 @@ layout_qualifier_id: } } + /* Layout qualifiers for tessellation control shaders. */ + if (match_layout_qualifier("vertices", $1, state) == 0) { + $$.flags.q.vertices = 1; + + if ($3 <= 0) { + _mesa_glsl_error(& @3, state, + "invalid vertices (%d) specified", $3); + YYERROR; + } else if ($3 > (int)state->Const.MaxPatchVertices) { + _mesa_glsl_error(& @3, state, + "vertices (%d) exceeds " + "GL_MAX_PATCH_VERTICES", $3); + YYERROR; + } else { + $$.vertices = $3; + if (!state->ARB_tessellation_shader_enable && + !state->is_version(400, 0)) { + _mesa_glsl_error(& @1, state, + "vertices qualifier requires GLSL 4.00 or " + "ARB_tessellation_shader"); + } + } + } + /* If the identifier didn't match any known layout identifiers, * emit an error. */ @@ -2743,11 +2850,8 @@ layout_defaults: | layout_qualifier OUT_TOK ';' { - if (state->stage != MESA_SHADER_GEOMETRY) { - _mesa_glsl_error(& @1, state, - "out layout qualifiers only valid in " - "geometry shaders"); - } else { + $$ = NULL; + if (state->stage == MESA_SHADER_GEOMETRY) { if ($1.flags.q.prim_type) { /* Make sure this is a valid output primitive type. */ switch ($1.prim_type) { @@ -2766,6 +2870,12 @@ layout_defaults: /* Allow future assigments of global out's stream id value */ state->out_qualifier->flags.q.explicit_stream = 0; + } else if (state->stage == MESA_SHADER_TESS_CTRL) { + if (!state->out_qualifier->merge_out_qualifier(& @1, state, $1, $$)) + YYERROR; + } else { + _mesa_glsl_error(& @1, state, + "out layout qualifiers only valid in " + "tessellation control or geometry shaders"); } - $$ = NULL; } diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 5412f0b7887..3bb5c4db2f7 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -145,6 +145,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, /* ARB_viewport_array */ this->Const.MaxViewports = ctx->Const.MaxViewports; + /* tessellation shader constants */ + this->Const.MaxPatchVertices = ctx->Const.MaxPatchVertices; + this->current_function = NULL; this->toplevel_ir = NULL; this->found_return = false; @@ -224,6 +227,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers = false; this->gs_input_prim_type_specified = false; + this->tcs_output_vertices_specified = false; this->gs_input_size = 0; this->in_qualifier = new(this) ast_type_qualifier(); this->out_qualifier = new(this) ast_type_qualifier(); @@ -389,6 +393,8 @@ _mesa_shader_stage_to_string(unsigned stage) case MESA_SHADER_FRAGMENT: return "fragment"; case MESA_SHADER_GEOMETRY: return "geometry"; case MESA_SHADER_COMPUTE: return "compute"; + case MESA_SHADER_TESS_CTRL: return "tess ctrl"; + case MESA_SHADER_TESS_EVAL: return "tess eval"; } unreachable("Unknown shader stage."); @@ -406,6 +412,8 @@ _mesa_shader_stage_to_abbrev(unsigned stage) case MESA_SHADER_FRAGMENT: return "FS"; case MESA_SHADER_GEOMETRY: return "GS"; case MESA_SHADER_COMPUTE: return "CS"; + case MESA_SHADER_TESS_CTRL: return "TCS"; + case MESA_SHADER_TESS_EVAL: return "TES"; } unreachable("Unknown shader stage."); @@ -574,6 +582,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_shader_texture_lod, true, false, ARB_shader_texture_lod), EXT(ARB_shading_language_420pack, true, false, ARB_shading_language_420pack), EXT(ARB_shading_language_packing, true, false, ARB_shading_language_packing), + EXT(ARB_tessellation_shader, true, false, ARB_tessellation_shader), EXT(ARB_texture_cube_map_array, true, false, ARB_texture_cube_map_array), EXT(ARB_texture_gather, true, false, ARB_texture_gather), EXT(ARB_texture_multisample, true, false, ARB_texture_multisample), @@ -1420,8 +1429,12 @@ static void set_shader_inout_layout(struct gl_shader *shader, struct _mesa_glsl_parse_state *state) { - if (shader->Stage != MESA_SHADER_GEOMETRY) { - /* Should have been prevented by the parser. */ + /* Should have been prevented by the parser. */ + if (shader->Stage == MESA_SHADER_TESS_CTRL) { + assert(!state->in_qualifier->flags.i); + } else if (shader->Stage == MESA_SHADER_TESS_EVAL) { + assert(!state->out_qualifier->flags.i); + } else if (shader->Stage != MESA_SHADER_GEOMETRY) { assert(!state->in_qualifier->flags.i); assert(!state->out_qualifier->flags.i); } @@ -1441,6 +1454,28 @@ set_shader_inout_layout(struct gl_shader *shader, } switch (shader->Stage) { + case MESA_SHADER_TESS_CTRL: + shader->TessCtrl.VerticesOut = 0; + if (state->tcs_output_vertices_specified) + shader->TessCtrl.VerticesOut = state->out_qualifier->vertices; + break; + case MESA_SHADER_TESS_EVAL: + shader->TessEval.PrimitiveMode = PRIM_UNKNOWN; + if (state->in_qualifier->flags.q.prim_type) + shader->TessEval.PrimitiveMode = state->in_qualifier->prim_type; + + shader->TessEval.Spacing = 0; + if (state->in_qualifier->flags.q.vertex_spacing) + shader->TessEval.Spacing = state->in_qualifier->vertex_spacing; + + shader->TessEval.VertexOrder = 0; + if (state->in_qualifier->flags.q.ordering) + shader->TessEval.VertexOrder = state->in_qualifier->ordering; + + shader->TessEval.PointMode = -1; + if (state->in_qualifier->flags.q.point_mode) + shader->TessEval.PointMode = state->in_qualifier->point_mode; + break; case MESA_SHADER_GEOMETRY: shader->Geom.VerticesOut = 0; if (state->out_qualifier->flags.q.max_vertices) diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index 4996b845044..de8f8c417fc 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -277,15 +277,19 @@ struct _mesa_glsl_parse_state { bool fs_redeclares_gl_fragcoord_with_no_layout_qualifiers; /** - * True if a geometry shader input primitive type was specified using a - * layout directive. + * True if a geometry shader input primitive type or tessellation control + * output vertices were specified using a layout directive. * - * Note: this value is computed at ast_to_hir time rather than at parse + * Note: these values are computed at ast_to_hir time rather than at parse * time. */ bool gs_input_prim_type_specified; + bool tcs_output_vertices_specified; - /** Input layout qualifiers from GLSL 1.50. (geometry shader controls)*/ + /** + * Input layout qualifiers from GLSL 1.50 (geometry shader controls), + * and GLSL 4.00 (tessellation evaluation shader) + */ struct ast_type_qualifier *in_qualifier; /** @@ -303,7 +307,10 @@ struct _mesa_glsl_parse_state { */ unsigned cs_input_local_size[3]; - /** Output layout qualifiers from GLSL 1.50. (geometry shader controls)*/ + /** + * Output layout qualifiers from GLSL 1.50 (geometry shader controls), + * and GLSL 4.00 (tessellation control shader). + */ struct ast_type_qualifier *out_qualifier; /** @@ -383,6 +390,9 @@ struct _mesa_glsl_parse_state { /* ARB_viewport_array */ unsigned MaxViewports; + + /* ARB_tessellation_shader */ + unsigned MaxPatchVertices; } Const; /** @@ -475,6 +485,8 @@ struct _mesa_glsl_parse_state { bool ARB_shading_language_420pack_warn; bool ARB_shading_language_packing_enable; bool ARB_shading_language_packing_warn; + bool ARB_tessellation_shader_enable; + bool ARB_tessellation_shader_warn; bool ARB_texture_cube_map_array_enable; bool ARB_texture_cube_map_array_warn; bool ARB_texture_gather_enable; @@ -545,6 +557,15 @@ struct _mesa_glsl_parse_state { bool fs_early_fragment_tests; + /** + * For tessellation control shaders, size of the most recently seen output + * declaration that was a sized array, or 0 if no sized output array + * declarations have been seen. + * + * Unused for other shader types. + */ + unsigned tcs_output_size; + /** Atomic counter offsets by binding */ unsigned atomic_counter_offsets[MAX_COMBINED_ATOMIC_BUFFERS]; |