glsl: add tessellation shader parsing support (v2)

v2: Fixed things that Ken suggested.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Fabian Bieler 2014-03-20 22:44:43 +01:00 committed by Marek Olšák
parent 206af9d049
commit 497eb29583
6 changed files with 476 additions and 48 deletions

View File

@ -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,
@ -1031,6 +1062,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.

View File

@ -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,
@ -6058,6 +6097,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)

View File

@ -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)
@ -256,6 +294,22 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
return true;
}
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,
@ -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) {

View File

@ -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;
}

View File

@ -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)

View File

@ -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];