ast_case_statement *case_statement;
ast_case_statement_list *case_statement_list;
ast_interface_block *interface_block;
-
+ ast_subroutine_list *subroutine_list;
struct {
ast_node *cond;
ast_expression *rest;
}
%token ATTRIBUTE CONST_TOK BOOL_TOK FLOAT_TOK INT_TOK UINT_TOK DOUBLE_TOK
-%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
+%token BREAK BUFFER CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4 DVEC2 DVEC3 DVEC4
%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING SAMPLE
%token NOPERSPECTIVE FLAT SMOOTH
%token IMAGE1DSHADOW IMAGE2DSHADOW IMAGE1DARRAYSHADOW IMAGE2DARRAYSHADOW
%token COHERENT VOLATILE RESTRICT READONLY WRITEONLY
%token ATOMIC_UINT
+%token SHARED
%token STRUCT VOID_TOK WHILE
%token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER
%type <identifier> any_identifier
%type <interface_block> instance_name_opt
+%type <interface_block> buffer_instance_name_opt
%token <real> FLOATCONSTANT
%token <dreal> DOUBLECONSTANT
%token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT
%token PRAGMA_OPTIMIZE_ON PRAGMA_OPTIMIZE_OFF
%token PRAGMA_INVARIANT_ALL
%token LAYOUT_TOK
-
+%token DOT_TOK
/* Reserved words that are not actually used in the grammar.
*/
%token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS PACKED_TOK GOTO
%type <type_qualifier> layout_qualifier
%type <type_qualifier> layout_qualifier_id_list layout_qualifier_id
%type <type_qualifier> interface_block_layout_qualifier
+%type <type_qualifier> memory_qualifier
+%type <type_qualifier> subroutine_qualifier
+%type <subroutine_list> subroutine_type_list
%type <type_qualifier> interface_qualifier
+%type <type_qualifier> buffer_interface_qualifier
%type <type_specifier> type_specifier
%type <type_specifier> type_specifier_nonarray
%type <array_specifier> array_specifier
%type <expression> function_call_generic
%type <expression> function_call_or_method
%type <expression> function_call
-%type <expression> method_call_generic
-%type <expression> method_call_header_with_parameters
-%type <expression> method_call_header_no_parameters
-%type <expression> method_call_header
%type <n> assignment_operator
%type <n> unary_operator
%type <expression> function_identifier
%type <node> conditionopt
%type <node> for_init_statement
%type <for_rest_statement> for_rest_statement
-%type <n> integer_constant
%type <node> layout_defaults
%right THEN ELSE
{
delete state->symbols;
state->symbols = new(ralloc_parent(state)) glsl_symbol_table;
+ if (state->es_shader) {
+ if (state->stage == MESA_SHADER_FRAGMENT) {
+ state->symbols->add_default_precision_qualifier("int", ast_precision_medium);
+ } else {
+ state->symbols->add_default_precision_qualifier("float", ast_precision_high);
+ state->symbols->add_default_precision_qualifier("int", ast_precision_high);
+ }
+ state->symbols->add_default_precision_qualifier("sampler2D", ast_precision_low);
+ state->symbols->add_default_precision_qualifier("samplerExternalOES", ast_precision_low);
+ state->symbols->add_default_precision_qualifier("samplerCube", ast_precision_low);
+ state->symbols->add_default_precision_qualifier("atomic_uint", ast_precision_high);
+ }
_mesa_glsl_initialize_types(state);
}
;
{
$$ = $1;
}
- | postfix_expression '.' any_identifier
+ | postfix_expression DOT_TOK FIELD_SELECTION
{
void *ctx = state;
$$ = new(ctx) ast_expression(ast_field_selection, $1, NULL, NULL);
function_call_or_method:
function_call_generic
- | postfix_expression '.' method_call_generic
- {
- void *ctx = state;
- $$ = new(ctx) ast_expression(ast_field_selection, $1, $3, NULL);
- $$->set_location_range(@1, @3);
- }
;
function_call_generic:
$$ = new(ctx) ast_function_expression($1);
$$->set_location(@1);
}
- | variable_identifier
+ | postfix_expression
{
void *ctx = state;
- ast_expression *callee = new(ctx) ast_expression($1);
- callee->set_location(@1);
- $$ = new(ctx) ast_function_expression(callee);
- $$->set_location(@1);
- }
- | FIELD_SELECTION
- {
- void *ctx = state;
- ast_expression *callee = new(ctx) ast_expression($1);
- callee->set_location(@1);
- $$ = new(ctx) ast_function_expression(callee);
+ $$ = new(ctx) ast_function_expression($1);
$$->set_location(@1);
}
;
-method_call_generic:
- method_call_header_with_parameters ')'
- | method_call_header_no_parameters ')'
- ;
-
-method_call_header_no_parameters:
- method_call_header VOID_TOK
- | method_call_header
- ;
-
-method_call_header_with_parameters:
- method_call_header assignment_expression
- {
- $$ = $1;
- $$->set_location(@1);
- $$->expressions.push_tail(& $2->link);
- }
- | method_call_header_with_parameters ',' assignment_expression
- {
- $$ = $1;
- $$->set_location(@1);
- $$->expressions.push_tail(& $3->link);
- }
- ;
-
// Grammar Note: Constructors look like methods, but lexical
// analysis recognized most of them as keywords. They are now
// recognized through "type_specifier".
-method_call_header:
- variable_identifier '('
- {
- void *ctx = state;
- ast_expression *callee = new(ctx) ast_expression($1);
- callee->set_location(@1);
- $$ = new(ctx) ast_function_expression(callee);
- $$->set_location(@1);
- }
- ;
// Grammar Note: No traditional style type casts.
unary_expression:
$$->return_type = $1;
$$->identifier = $2;
- state->symbols->add_function(new(state) ir_function($2));
+ if ($1->qualifier.flags.q.subroutine) {
+ /* add type for IDENTIFIER search */
+ state->symbols->add_type($2, glsl_type::get_subroutine_instance($2));
+ } else
+ state->symbols->add_function(new(state) ir_function($2));
state->symbols->push_scope();
}
;
if (($1.flags.q.in || $1.flags.q.out) && ($2.flags.q.in || $2.flags.q.out))
_mesa_glsl_error(&@1, state, "duplicate in/out/inout qualifier");
- if (!state->ARB_shading_language_420pack_enable && $2.flags.q.constant)
+ if (!state->has_420pack_or_es31() && $2.flags.q.constant)
_mesa_glsl_error(&@1, state, "in/out/inout must come after const "
"or precise");
if ($2.precision != ast_precision_none)
_mesa_glsl_error(&@1, state, "duplicate precision qualifier");
- if (!state->ARB_shading_language_420pack_enable && $2.flags.i != 0)
+ if (!state->has_420pack_or_es31() &&
+ $2.flags.i != 0)
_mesa_glsl_error(&@1, state, "precision qualifiers must come last");
$$ = $2;
$$.precision = $1;
}
+ | memory_qualifier parameter_qualifier
+ {
+ $$ = $1;
+ $$.merge_qualifier(&@1, state, $2);
+ }
parameter_direction_qualifier:
IN_TOK
$$->set_location_range(@1, @2);
$$->qualifier = $1;
$$->specifier = $2;
+ if ($$->specifier->structure != NULL &&
+ $$->specifier->structure->is_declaration) {
+ $$->specifier->structure->layout = &$$->qualifier;
+ }
}
;
}
;
-integer_constant:
- INTCONSTANT { $$ = $1; }
- | UINTCONSTANT { $$ = $1; }
- ;
-
layout_qualifier_id:
any_identifier
{
/* Layout qualifiers for AMD/ARB_conservative_depth. */
if (!$$.flags.i &&
(state->AMD_conservative_depth_enable ||
- state->ARB_conservative_depth_enable)) {
+ state->ARB_conservative_depth_enable ||
+ state->is_version(420, 0))) {
if (match_layout_qualifier($1, "depth_any", state) == 0) {
$$.flags.q.depth_any = 1;
} else if (match_layout_qualifier($1, "depth_greater", state) == 0) {
$$.flags.q.std140 = 1;
} else if (match_layout_qualifier($1, "shared", state) == 0) {
$$.flags.q.shared = 1;
+ } else if (match_layout_qualifier($1, "std430", state) == 0) {
+ $$.flags.q.std430 = 1;
} else if (match_layout_qualifier($1, "column_major", state) == 0) {
$$.flags.q.column_major = 1;
/* "row_major" is a reserved word in GLSL 1.30+. Its token is parsed
/* Layout qualifiers for ARB_shader_image_load_store. */
if (state->ARB_shader_image_load_store_enable ||
- state->is_version(420, 0)) {
+ state->is_version(420, 310)) {
if (!$$.flags.i) {
static const struct {
const char *name;
GLenum format;
glsl_base_type base_type;
+ /** Minimum desktop GLSL version required for the image
+ * format. Use 130 if already present in the original
+ * ARB extension.
+ */
+ unsigned required_glsl;
+ /** Minimum GLSL ES version required for the image format. */
+ unsigned required_essl;
} map[] = {
- { "rgba32f", GL_RGBA32F, GLSL_TYPE_FLOAT },
- { "rgba16f", GL_RGBA16F, GLSL_TYPE_FLOAT },
- { "rg32f", GL_RG32F, GLSL_TYPE_FLOAT },
- { "rg16f", GL_RG16F, GLSL_TYPE_FLOAT },
- { "r11f_g11f_b10f", GL_R11F_G11F_B10F, GLSL_TYPE_FLOAT },
- { "r32f", GL_R32F, GLSL_TYPE_FLOAT },
- { "r16f", GL_R16F, GLSL_TYPE_FLOAT },
- { "rgba32ui", GL_RGBA32UI, GLSL_TYPE_UINT },
- { "rgba16ui", GL_RGBA16UI, GLSL_TYPE_UINT },
- { "rgb10_a2ui", GL_RGB10_A2UI, GLSL_TYPE_UINT },
- { "rgba8ui", GL_RGBA8UI, GLSL_TYPE_UINT },
- { "rg32ui", GL_RG32UI, GLSL_TYPE_UINT },
- { "rg16ui", GL_RG16UI, GLSL_TYPE_UINT },
- { "rg8ui", GL_RG8UI, GLSL_TYPE_UINT },
- { "r32ui", GL_R32UI, GLSL_TYPE_UINT },
- { "r16ui", GL_R16UI, GLSL_TYPE_UINT },
- { "r8ui", GL_R8UI, GLSL_TYPE_UINT },
- { "rgba32i", GL_RGBA32I, GLSL_TYPE_INT },
- { "rgba16i", GL_RGBA16I, GLSL_TYPE_INT },
- { "rgba8i", GL_RGBA8I, GLSL_TYPE_INT },
- { "rg32i", GL_RG32I, GLSL_TYPE_INT },
- { "rg16i", GL_RG16I, GLSL_TYPE_INT },
- { "rg8i", GL_RG8I, GLSL_TYPE_INT },
- { "r32i", GL_R32I, GLSL_TYPE_INT },
- { "r16i", GL_R16I, GLSL_TYPE_INT },
- { "r8i", GL_R8I, GLSL_TYPE_INT },
- { "rgba16", GL_RGBA16, GLSL_TYPE_FLOAT },
- { "rgb10_a2", GL_RGB10_A2, GLSL_TYPE_FLOAT },
- { "rgba8", GL_RGBA8, GLSL_TYPE_FLOAT },
- { "rg16", GL_RG16, GLSL_TYPE_FLOAT },
- { "rg8", GL_RG8, GLSL_TYPE_FLOAT },
- { "r16", GL_R16, GLSL_TYPE_FLOAT },
- { "r8", GL_R8, GLSL_TYPE_FLOAT },
- { "rgba16_snorm", GL_RGBA16_SNORM, GLSL_TYPE_FLOAT },
- { "rgba8_snorm", GL_RGBA8_SNORM, GLSL_TYPE_FLOAT },
- { "rg16_snorm", GL_RG16_SNORM, GLSL_TYPE_FLOAT },
- { "rg8_snorm", GL_RG8_SNORM, GLSL_TYPE_FLOAT },
- { "r16_snorm", GL_R16_SNORM, GLSL_TYPE_FLOAT },
- { "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT }
+ { "rgba32f", GL_RGBA32F, GLSL_TYPE_FLOAT, 130, 310 },
+ { "rgba16f", GL_RGBA16F, GLSL_TYPE_FLOAT, 130, 310 },
+ { "rg32f", GL_RG32F, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rg16f", GL_RG16F, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r11f_g11f_b10f", GL_R11F_G11F_B10F, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r32f", GL_R32F, GLSL_TYPE_FLOAT, 130, 310 },
+ { "r16f", GL_R16F, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgba32ui", GL_RGBA32UI, GLSL_TYPE_UINT, 130, 310 },
+ { "rgba16ui", GL_RGBA16UI, GLSL_TYPE_UINT, 130, 310 },
+ { "rgb10_a2ui", GL_RGB10_A2UI, GLSL_TYPE_UINT, 130, 0 },
+ { "rgba8ui", GL_RGBA8UI, GLSL_TYPE_UINT, 130, 310 },
+ { "rg32ui", GL_RG32UI, GLSL_TYPE_UINT, 130, 0 },
+ { "rg16ui", GL_RG16UI, GLSL_TYPE_UINT, 130, 0 },
+ { "rg8ui", GL_RG8UI, GLSL_TYPE_UINT, 130, 0 },
+ { "r32ui", GL_R32UI, GLSL_TYPE_UINT, 130, 310 },
+ { "r16ui", GL_R16UI, GLSL_TYPE_UINT, 130, 0 },
+ { "r8ui", GL_R8UI, GLSL_TYPE_UINT, 130, 0 },
+ { "rgba32i", GL_RGBA32I, GLSL_TYPE_INT, 130, 310 },
+ { "rgba16i", GL_RGBA16I, GLSL_TYPE_INT, 130, 310 },
+ { "rgba8i", GL_RGBA8I, GLSL_TYPE_INT, 130, 310 },
+ { "rg32i", GL_RG32I, GLSL_TYPE_INT, 130, 0 },
+ { "rg16i", GL_RG16I, GLSL_TYPE_INT, 130, 0 },
+ { "rg8i", GL_RG8I, GLSL_TYPE_INT, 130, 0 },
+ { "r32i", GL_R32I, GLSL_TYPE_INT, 130, 310 },
+ { "r16i", GL_R16I, GLSL_TYPE_INT, 130, 0 },
+ { "r8i", GL_R8I, GLSL_TYPE_INT, 130, 0 },
+ { "rgba16", GL_RGBA16, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgb10_a2", GL_RGB10_A2, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgba8", GL_RGBA8, GLSL_TYPE_FLOAT, 130, 310 },
+ { "rg16", GL_RG16, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rg8", GL_RG8, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r16", GL_R16, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r8", GL_R8, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgba16_snorm", GL_RGBA16_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgba8_snorm", GL_RGBA8_SNORM, GLSL_TYPE_FLOAT, 130, 310 },
+ { "rg16_snorm", GL_RG16_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rg8_snorm", GL_RG8_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r16_snorm", GL_R16_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT, 130, 0 }
};
for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
- if (match_layout_qualifier($1, map[i].name, state) == 0) {
+ if (state->is_version(map[i].required_glsl,
+ map[i].required_essl) &&
+ match_layout_qualifier($1, map[i].name, state) == 0) {
$$.flags.q.explicit_image_format = 1;
$$.image_format = map[i].format;
$$.image_base_type = map[i].base_type;
if (!$$.flags.i &&
match_layout_qualifier($1, "early_fragment_tests", state) == 0) {
+ /* From section 4.4.1.3 of the GLSL 4.50 specification
+ * (Fragment Shader Inputs):
+ *
+ * "Fragment shaders also allow the following layout
+ * qualifier on in only (not with variable declarations)
+ * layout-qualifier-id
+ * early_fragment_tests
+ * [...]"
+ */
+ if (state->stage != MESA_SHADER_FRAGMENT) {
+ _mesa_glsl_error(& @1, state,
+ "early_fragment_tests layout qualifier only "
+ "valid in fragment shaders");
+ }
+
$$.flags.q.early_fragment_tests = 1;
}
}
+ /* 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);
YYERROR;
}
}
- | any_identifier '=' integer_constant
+ | any_identifier '=' constant_expression
{
memset(& $$, 0, sizeof($$));
+ void *ctx = state;
+
+ if ($3->oper != ast_int_constant &&
+ $3->oper != ast_uint_constant &&
+ !state->has_enhanced_layouts()) {
+ _mesa_glsl_error(& @1, state,
+ "compile-time constant expressions require "
+ "GLSL 4.40 or ARB_enhanced_layouts");
+ }
if (match_layout_qualifier("location", $1, state) == 0) {
$$.flags.q.explicit_location = 1;
"GL_ARB_explicit_attrib_location layout "
"identifier `%s' used", $1);
}
-
- if ($3 >= 0) {
- $$.location = $3;
- } else {
- _mesa_glsl_error(& @3, state, "invalid location %d specified", $3);
- YYERROR;
- }
+ $$.location = $3;
}
if (match_layout_qualifier("index", $1, state) == 0) {
- $$.flags.q.explicit_index = 1;
-
- if ($3 >= 0) {
- $$.index = $3;
- } else {
- _mesa_glsl_error(& @3, state, "invalid index %d specified", $3);
+ if (state->es_shader && !state->EXT_blend_func_extended_enable) {
+ _mesa_glsl_error(& @3, state, "index layout qualifier requires EXT_blend_func_extended");
YYERROR;
}
+
+ $$.flags.q.explicit_index = 1;
+ $$.index = $3;
}
- if ((state->ARB_shading_language_420pack_enable ||
- state->ARB_shader_atomic_counters_enable) &&
+ if ((state->has_420pack_or_es31() ||
+ state->has_atomic_counters() ||
+ state->has_shader_storage_buffer_objects()) &&
match_layout_qualifier("binding", $1, state) == 0) {
$$.flags.q.explicit_binding = 1;
$$.binding = $3;
}
- if (state->ARB_shader_atomic_counters_enable &&
+ if (state->has_atomic_counters() &&
match_layout_qualifier("offset", $1, state) == 0) {
$$.flags.q.explicit_offset = 1;
$$.offset = $3;
if (match_layout_qualifier("max_vertices", $1, state) == 0) {
$$.flags.q.max_vertices = 1;
-
- if ($3 < 0) {
+ $$.max_vertices = new(ctx) ast_layout_expression(@1, $3);
+ if (!state->is_version(150, 0)) {
_mesa_glsl_error(& @3, state,
- "invalid max_vertices %d specified", $3);
- YYERROR;
- } else {
- $$.max_vertices = $3;
- if (!state->is_version(150, 0)) {
- _mesa_glsl_error(& @3, state,
- "#version 150 max_vertices qualifier "
- "specified", $3);
- }
+ "#version 150 max_vertices qualifier "
+ "specified", $3);
}
}
if (match_layout_qualifier("stream", $1, state) == 0 &&
state->check_explicit_attrib_stream_allowed(& @3)) {
$$.flags.q.stream = 1;
-
- if ($3 < 0) {
- _mesa_glsl_error(& @3, state,
- "invalid stream %d specified", $3);
- YYERROR;
- } else {
- $$.flags.q.explicit_stream = 1;
- $$.stream = $3;
- }
+ $$.flags.q.explicit_stream = 1;
+ $$.stream = $3;
}
}
for (int i = 0; i < 3; i++) {
if (match_layout_qualifier(local_size_qualifiers[i], $1,
state) == 0) {
- if ($3 <= 0) {
- _mesa_glsl_error(& @3, state,
- "invalid %s of %d specified",
- local_size_qualifiers[i], $3);
- YYERROR;
- } else if (!state->is_version(430, 0) &&
- !state->ARB_compute_shader_enable) {
+ if (!state->has_compute_shader()) {
_mesa_glsl_error(& @3, state,
"%s qualifier requires GLSL 4.30 or "
- "ARB_compute_shader",
+ "GLSL ES 3.10 or ARB_compute_shader",
local_size_qualifiers[i]);
YYERROR;
} else {
$$.flags.q.local_size |= (1 << i);
- $$.local_size[i] = $3;
+ $$.local_size[i] = new(ctx) ast_layout_expression(@1, $3);
}
break;
}
if (match_layout_qualifier("invocations", $1, state) == 0) {
$$.flags.q.invocations = 1;
-
- if ($3 <= 0) {
- _mesa_glsl_error(& @3, state,
- "invalid invocations %d specified", $3);
- YYERROR;
- } else if ($3 > MAX_GEOMETRY_SHADER_INVOCATIONS) {
+ $$.invocations = new(ctx) ast_layout_expression(@1, $3);
+ if (!state->is_version(400, 0) &&
+ !state->ARB_gpu_shader5_enable) {
_mesa_glsl_error(& @3, state,
- "invocations (%d) exceeds "
- "GL_MAX_GEOMETRY_SHADER_INVOCATIONS", $3);
- YYERROR;
- } else {
- $$.invocations = $3;
- if (!state->is_version(400, 0) &&
- !state->ARB_gpu_shader5_enable) {
- _mesa_glsl_error(& @3, state,
- "GL_ARB_gpu_shader5 invocations "
- "qualifier specified", $3);
- }
+ "GL_ARB_gpu_shader5 invocations "
+ "qualifier specified", $3);
+ }
+ }
+
+ /* Layout qualifiers for tessellation control shaders. */
+ if (match_layout_qualifier("vertices", $1, state) == 0) {
+ $$.flags.q.vertices = 1;
+ $$.vertices = new(ctx) ast_layout_expression(@1, $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");
}
}
memset(& $$, 0, sizeof($$));
$$.flags.q.packed = 1;
}
+ | SHARED
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.shared = 1;
+ }
+ ;
+
+subroutine_qualifier:
+ SUBROUTINE
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.subroutine = 1;
+ }
+ | SUBROUTINE '(' subroutine_type_list ')'
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.subroutine_def = 1;
+ $$.subroutine_list = $3;
+ }
+ ;
+
+subroutine_type_list:
+ any_identifier
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($1, NULL, NULL);
+ decl->set_location(@1);
+
+ $$ = new(ctx) ast_subroutine_list();
+ $$->declarations.push_tail(&decl->link);
+ }
+ | subroutine_type_list ',' any_identifier
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($3, NULL, NULL);
+ decl->set_location(@3);
+
+ $$ = $1;
+ $$->declarations.push_tail(&decl->link);
+ }
;
interpolation_qualifier:
| storage_qualifier
| interpolation_qualifier
| layout_qualifier
+ | memory_qualifier
+ | subroutine_qualifier
| precision_qualifier
{
memset(&$$, 0, sizeof($$));
if ($2.flags.q.invariant)
_mesa_glsl_error(&@1, state, "duplicate \"invariant\" qualifier");
- if (!state->ARB_shading_language_420pack_enable && $2.flags.q.precise)
+ if (!state->has_420pack_or_es31() && $2.flags.q.precise)
_mesa_glsl_error(&@1, state,
"\"invariant\" must come after \"precise\"");
if ($2.has_interpolation())
_mesa_glsl_error(&@1, state, "duplicate interpolation qualifier");
- if (!state->ARB_shading_language_420pack_enable &&
+ if (!state->has_420pack_or_es31() &&
($2.flags.q.precise || $2.flags.q.invariant)) {
_mesa_glsl_error(&@1, state, "interpolation qualifiers must come "
"after \"precise\" or \"invariant\"");
* precise qualifiers since these are useful in ARB_separate_shader_objects.
* There is no clear spec guidance on this either.
*/
- if (!state->ARB_shading_language_420pack_enable && $2.has_layout())
+ if (!state->has_420pack_or_es31() && $2.has_layout())
_mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
$$ = $1;
$$.merge_qualifier(&@1, state, $2);
}
+ | subroutine_qualifier type_qualifier
+ {
+ $$ = $1;
+ $$.merge_qualifier(&@1, state, $2);
+ }
| auxiliary_storage_qualifier type_qualifier
{
if ($2.has_auxiliary_storage()) {
"duplicate auxiliary storage qualifier (centroid or sample)");
}
- if (!state->ARB_shading_language_420pack_enable &&
+ if (!state->has_420pack_or_es31() &&
($2.flags.q.precise || $2.flags.q.invariant ||
$2.has_interpolation() || $2.has_layout())) {
_mesa_glsl_error(&@1, state, "auxiliary storage qualifiers must come "
if ($2.has_storage())
_mesa_glsl_error(&@1, state, "duplicate storage qualifier");
- if (!state->ARB_shading_language_420pack_enable &&
+ if (!state->has_420pack_or_es31() &&
($2.flags.q.precise || $2.flags.q.invariant || $2.has_interpolation() ||
$2.has_layout() || $2.has_auxiliary_storage())) {
_mesa_glsl_error(&@1, state, "storage qualifiers must come after "
if ($2.precision != ast_precision_none)
_mesa_glsl_error(&@1, state, "duplicate precision qualifier");
- if (!state->ARB_shading_language_420pack_enable && $2.flags.i != 0)
+ if (!(state->has_420pack_or_es31()) &&
+ $2.flags.i != 0)
_mesa_glsl_error(&@1, state, "precision qualifiers must come last");
$$ = $2;
$$.precision = $1;
}
+ | memory_qualifier type_qualifier
+ {
+ $$ = $1;
+ $$.merge_qualifier(&@1, state, $2);
+ }
;
auxiliary_storage_qualifier:
memset(& $$, 0, sizeof($$));
$$.flags.q.sample = 1;
}
- /* TODO: "patch" also goes here someday. */
+ | PATCH
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.patch = 1;
+ }
storage_qualifier:
CONST_TOK
memset(& $$, 0, sizeof($$));
$$.flags.q.uniform = 1;
}
- | COHERENT
+ | BUFFER
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.buffer = 1;
+ }
+ | SHARED
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.shared_storage = 1;
+ }
+ ;
+
+memory_qualifier:
+ COHERENT
{
memset(& $$, 0, sizeof($$));
$$.flags.q.coherent = 1;
'[' ']'
{
void *ctx = state;
- $$ = new(ctx) ast_array_specifier(@1);
+ $$ = new(ctx) ast_array_specifier(@1, new(ctx) ast_expression(
+ ast_unsized_array_dim, NULL,
+ NULL, NULL));
$$->set_location_range(@1, @2);
}
| '[' constant_expression ']'
}
| array_specifier '[' ']'
{
+ void *ctx = state;
$$ = $1;
- if (!state->ARB_arrays_of_arrays_enable) {
- _mesa_glsl_error(& @1, state,
- "GL_ARB_arrays_of_arrays "
- "required for defining arrays of arrays");
- } else {
- _mesa_glsl_error(& @1, state,
- "only the outermost array dimension can "
- "be unsized");
+ if (state->check_arrays_of_arrays_allowed(& @1)) {
+ $$->add_dimension(new(ctx) ast_expression(ast_unsized_array_dim, NULL,
+ NULL, NULL));
}
}
| array_specifier '[' constant_expression ']'
{
$$ = $1;
- if (!state->ARB_arrays_of_arrays_enable) {
- _mesa_glsl_error(& @1, state,
- "GL_ARB_arrays_of_arrays "
- "required for defining arrays of arrays");
+ if (state->check_arrays_of_arrays_allowed(& @1)) {
+ $$->add_dimension($3);
}
-
- $$->add_dimension($3);
}
;
{
$$ = $1;
}
- | layout_qualifier basic_interface_block
+ | layout_qualifier interface_block
{
- ast_interface_block *block = $2;
+ ast_interface_block *block = (ast_interface_block *) $2;
+
+ if (!state->has_420pack_or_es31() && block->layout.has_layout() &&
+ !block->layout.is_default_qualifier) {
+ _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
+ YYERROR;
+ }
+
if (!block->layout.merge_qualifier(& @1, state, $1)) {
YYERROR;
}
- foreach_list_typed (ast_declarator_list, member, link, &block->declarations) {
- ast_type_qualifier& qualifier = member->type->qualifier;
- if (qualifier.flags.q.stream && qualifier.stream != block->layout.stream) {
- _mesa_glsl_error(& @1, state,
- "stream layout qualifier on "
- "interface block member does not match "
- "the interface block (%d vs %d)",
- qualifier.stream, block->layout.stream);
- YYERROR;
- }
+ block->layout.is_default_qualifier = false;
+
+ $$ = block;
+ }
+ | memory_qualifier interface_block
+ {
+ ast_interface_block *block = (ast_interface_block *)$2;
+
+ if (!block->layout.flags.q.buffer) {
+ _mesa_glsl_error(& @1, state,
+ "memory qualifiers can only be used in the "
+ "declaration of shader storage blocks");
+ }
+ if (!block->layout.merge_qualifier(& @1, state, $1)) {
+ YYERROR;
}
$$ = block;
}
block->block_name = $2;
block->declarations.push_degenerate_list_at_head(& $4->link);
- if ($1.flags.q.uniform) {
- if (!state->has_uniform_buffer_objects()) {
- _mesa_glsl_error(& @1, state,
- "#version 140 / GL_ARB_uniform_buffer_object "
- "required for defining uniform blocks");
- } else if (state->ARB_uniform_buffer_object_warn) {
- _mesa_glsl_warning(& @1, state,
- "#version 140 / GL_ARB_uniform_buffer_object "
- "required for defining uniform blocks");
- }
- } else {
- if (state->es_shader || state->language_version < 150) {
- _mesa_glsl_error(& @1, state,
- "#version 150 required for using "
- "interface blocks");
- }
- }
-
- /* From the GLSL 1.50.11 spec, section 4.3.7 ("Interface Blocks"):
- * "It is illegal to have an input block in a vertex shader
- * or an output block in a fragment shader"
- */
- if ((state->stage == MESA_SHADER_VERTEX) && $1.flags.q.in) {
- _mesa_glsl_error(& @1, state,
- "`in' interface block is not allowed for "
- "a vertex shader");
- } else if ((state->stage == MESA_SHADER_FRAGMENT) && $1.flags.q.out) {
- _mesa_glsl_error(& @1, state,
- "`out' interface block is not allowed for "
- "a fragment shader");
- }
-
- /* Since block arrays require names, and both features are added in
- * the same language versions, we don't have to explicitly
- * version-check both things.
- */
- if (block->instance_name != NULL) {
- state->check_version(150, 300, & @1, "interface blocks with "
- "an instance name are not allowed");
- }
-
- uint64_t interface_type_mask;
- struct ast_type_qualifier temp_type_qualifier;
+ _mesa_ast_process_interface_block(& @1, state, block, $1);
- /* Get a bitmask containing only the in/out/uniform flags, allowing us
- * to ignore other irrelevant flags like interpolation qualifiers.
- */
- temp_type_qualifier.flags.i = 0;
- temp_type_qualifier.flags.q.uniform = true;
- temp_type_qualifier.flags.q.in = true;
- temp_type_qualifier.flags.q.out = true;
- interface_type_mask = temp_type_qualifier.flags.i;
-
- /* Get the block's interface qualifier. The interface_qualifier
- * production rule guarantees that only one bit will be set (and
- * it will be in/out/uniform).
- */
- uint64_t block_interface_qualifier = $1.flags.i;
-
- block->layout.flags.i |= block_interface_qualifier;
-
- if (state->stage == MESA_SHADER_GEOMETRY &&
- state->has_explicit_attrib_stream()) {
- /* Assign global layout's stream value. */
- block->layout.flags.q.stream = 1;
- block->layout.flags.q.explicit_stream = 0;
- block->layout.stream = state->out_qualifier->stream;
- }
+ $$ = block;
+ }
+ | buffer_interface_qualifier NEW_IDENTIFIER '{' member_list '}' buffer_instance_name_opt ';'
+ {
+ ast_interface_block *const block = $6;
- foreach_list_typed (ast_declarator_list, member, link, &block->declarations) {
- ast_type_qualifier& qualifier = member->type->qualifier;
- if ((qualifier.flags.i & interface_type_mask) == 0) {
- /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks):
- * "If no optional qualifier is used in a member declaration, the
- * qualifier of the variable is just in, out, or uniform as declared
- * by interface-qualifier."
- */
- qualifier.flags.i |= block_interface_qualifier;
- } else if ((qualifier.flags.i & interface_type_mask) !=
- block_interface_qualifier) {
- /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks):
- * "If optional qualifiers are used, they can include interpolation
- * and storage qualifiers and they must declare an input, output,
- * or uniform variable consistent with the interface qualifier of
- * the block."
- */
- _mesa_glsl_error(& @1, state,
- "uniform/in/out qualifier on "
- "interface block member does not match "
- "the interface block");
- }
+ block->block_name = $2;
+ block->declarations.push_degenerate_list_at_head(& $4->link);
- /* From GLSL ES 3.0, chapter 4.3.7 "Interface Blocks":
- *
- * "GLSL ES 3.0 does not support interface blocks for shader inputs or
- * outputs."
- *
- * And from GLSL ES 3.0, chapter 4.6.1 "The invariant qualifier":.
- *
- * "Only variables output from a shader can be candidates for
- * invariance."
- *
- * From GLSL 4.40 and GLSL 1.50, section "Interface Blocks":
- *
- * "If optional qualifiers are used, they can include interpolation
- * qualifiers, auxiliary storage qualifiers, and storage qualifiers
- * and they must declare an input, output, or uniform member
- * consistent with the interface qualifier of the block"
- */
- if (qualifier.flags.q.invariant)
- _mesa_glsl_error(&@1, state,
- "invariant qualifiers cannot be used "
- "with interface blocks members");
- }
+ _mesa_ast_process_interface_block(& @1, state, block, $1);
$$ = block;
}
}
;
+buffer_interface_qualifier:
+ BUFFER
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.buffer = 1;
+ }
+ ;
+
instance_name_opt:
/* empty */
{
}
;
+buffer_instance_name_opt:
+ /* empty */
+ {
+ $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier,
+ NULL, NULL);
+ }
+ | NEW_IDENTIFIER
+ {
+ $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier,
+ $1, NULL);
+ $$->set_location(@1);
+ }
+ | NEW_IDENTIFIER array_specifier
+ {
+ $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier,
+ $1, $2);
+ $$->set_location_range(@1, @2);
+ }
+ ;
+
member_list:
member_declaration
{
$$ = NULL;
}
+ | layout_qualifier BUFFER ';'
+ {
+ if (!state->default_shader_storage_qualifier->merge_qualifier(& @1, state, $1)) {
+ YYERROR;
+ }
+
+ /* From the GLSL 4.50 spec, section 4.4.5:
+ *
+ * "It is a compile-time error to specify the binding identifier for
+ * the global scope or for block member declarations."
+ */
+ if (state->default_shader_storage_qualifier->flags.q.explicit_binding) {
+ _mesa_glsl_error(& @1, state,
+ "binding qualifier cannot be set for default layout");
+ }
+
+ $$ = NULL;
+ }
+
| layout_qualifier IN_TOK ';'
{
$$ = NULL;
| 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) {
/* 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;
}