diff options
Diffstat (limited to 'mesalib/src/glsl/ast_to_hir.cpp')
-rw-r--r-- | mesalib/src/glsl/ast_to_hir.cpp | 362 |
1 files changed, 331 insertions, 31 deletions
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 598da92f8..04b16c8aa 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -72,6 +72,8 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) state->toplevel_ir = instructions; + state->gs_input_prim_type_specified = false; + /* Section 4.2 of the GLSL 1.20 specification states: * "The built-in functions are scoped in a scope outside the global scope * users declare global variables in. That is, a shader's global scope, @@ -1771,12 +1773,6 @@ process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size, } } } - } else if (state->es_shader) { - /* Section 10.17 of the GLSL ES 1.00 specification states that unsized - * array declarations have been removed from the language. - */ - _mesa_glsl_error(loc, state, "unsized array declarations are not " - "allowed in GLSL ES 1.00"); } const glsl_type *array_type = glsl_type::get_array_instance(base, length); @@ -1936,6 +1932,8 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, bool ubo_qualifiers_valid, bool is_parameter) { + STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i)); + if (qual->flags.q.invariant) { if (var->used) { _mesa_glsl_error(loc, state, @@ -1963,6 +1961,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, _mesa_glsl_shader_target_name(state->target)); } + /* Section 6.1.1 (Function Calling Conventions) of the GLSL 1.10 spec says: + * + * "However, the const qualifier cannot be used with out or inout." + * + * The same section of the GLSL 4.40 spec further clarifies this saying: + * + * "The const qualifier cannot be used with out or inout, or a + * compile-time error results." + */ + if (is_parameter && qual->flags.q.constant && qual->flags.q.out) { + _mesa_glsl_error(loc, state, + "`const' may not be applied to `out' or `inout' " + "function parameters"); + } + /* If there is no qualifier that changes the mode of the variable, leave * the setting alone. */ @@ -2055,13 +2068,24 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, else var->interpolation = INTERP_QUALIFIER_NONE; - if (var->interpolation != INTERP_QUALIFIER_NONE && - !(state->target == vertex_shader && var->mode == ir_var_shader_out) && - !(state->target == fragment_shader && var->mode == ir_var_shader_in)) { - _mesa_glsl_error(loc, state, - "interpolation qualifier `%s' can only be applied to " - "vertex shader outputs and fragment shader inputs", - var->interpolation_string()); + if (var->interpolation != INTERP_QUALIFIER_NONE) { + ir_variable_mode mode = (ir_variable_mode) var->mode; + + if (mode != ir_var_shader_in && mode != ir_var_shader_out) { + _mesa_glsl_error(loc, state, + "interpolation qualifier `%s' can only be applied to " + "shader inputs or outputs.", + var->interpolation_string()); + + } + + if ((state->target == vertex_shader && mode == ir_var_shader_in) || + (state->target == fragment_shader && mode == ir_var_shader_out)) { + _mesa_glsl_error(loc, state, + "interpolation qualifier `%s' cannot be applied to " + "vertex shader inputs or fragment shader outputs", + var->interpolation_string()); + } } var->pixel_center_integer = qual->flags.q.pixel_center_integer; @@ -2317,7 +2341,8 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl, earlier->type = var->type; delete var; var = NULL; - } else if (state->ARB_fragment_coord_conventions_enable + } else if ((state->ARB_fragment_coord_conventions_enable || + state->is_version(150, 0)) && strcmp(var->name, "gl_FragCoord") == 0 && earlier->type == var->type && earlier->mode == var->mode) { @@ -2519,6 +2544,81 @@ 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) +{ + unsigned num_vertices = 0; + if (state->gs_input_prim_type_specified) { + num_vertices = vertices_per_prim(state->gs_input_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->length == 0) { + /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec says: + * + * All geometry shader input unsized array declarations will be + * sized by an earlier input layout qualifier, when present, as per + * the following table. + * + * Followed by a table mapping each allowed input layout qualifier to + * the corresponding input length. + */ + if (num_vertices != 0) + var->type = glsl_type::get_array_instance(var->type->fields.array, + num_vertices); + } else { + /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec + * includes the following examples of compile-time errors: + * + * // code sequence within one shader... + * in vec4 Color1[]; // size unknown + * ...Color1.length()...// illegal, length() unknown + * in vec4 Color2[2]; // size is 2 + * ...Color1.length()...// illegal, Color1 still has no size + * in vec4 Color3[3]; // illegal, input sizes are inconsistent + * layout(lines) in; // legal, input size is 2, matching + * in vec4 Color4[3]; // illegal, contradicts layout + * ... + * + * To detect the case illustrated by Color3, we verify that the size of + * an explicitly-sized array matches the size of any previously declared + * explicitly-sized array. To detect the case illustrated by Color4, we + * verify that the size of an explicitly-sized array is consistent with + * any previously declared input layout. + */ + 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) { + _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); + } else { + state->gs_input_size = var->type->length; + } + } +} + ir_rvalue * ast_declarator_list::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) @@ -2605,6 +2705,11 @@ ast_declarator_list::hir(exec_list *instructions, * name of a known structure type. This is both invalid and weird. * Emit an error. * + * - The program text contained something like 'mediump float;' + * when the programmer probably meant 'precision mediump + * float;' Emit a warning with a description of what they + * probably meant to do. + * * Note that if decl_type is NULL and there is a structure involved, * there must have been some sort of error with the structure. In this * case we assume that an error was already generated on this line of @@ -2613,20 +2718,33 @@ ast_declarator_list::hir(exec_list *instructions, */ assert(this->type->specifier->structure == NULL || decl_type != NULL || state->error); - if (this->type->specifier->structure == NULL) { - if (decl_type != NULL) { - _mesa_glsl_warning(&loc, state, "empty declaration"); - } else { - _mesa_glsl_error(&loc, state, - "invalid type `%s' in empty declaration", - type_name); - } - } - if (this->type->qualifier.precision != ast_precision_none && - this->type->specifier->structure != NULL) { - _mesa_glsl_error(&loc, state, "precision qualifiers can't be applied " - "to structures"); + if (decl_type == NULL) { + _mesa_glsl_error(&loc, state, + "invalid type `%s' in empty declaration", + type_name); + } else if (this->type->qualifier.precision != ast_precision_none) { + if (this->type->specifier->structure != NULL) { + _mesa_glsl_error(&loc, state, + "precision qualifiers can't be applied " + "to structures"); + } else { + static const char *const precision_names[] = { + "highp", + "highp", + "mediump", + "lowp" + }; + + _mesa_glsl_warning(&loc, state, + "empty declaration with precision qualifier, " + "to set the default precision, use " + "`precision %s %s;'", + precision_names[this->type->qualifier.precision], + type_name); + } + } else { + _mesa_glsl_warning(&loc, state, "empty declaration"); } } @@ -2662,6 +2780,26 @@ ast_declarator_list::hir(exec_list *instructions, var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto); + /* The 'varying in' and 'varying out' qualifiers can only be used with + * ARB_geometry_shader4 and EXT_geometry_shader4, which we don't support + * yet. + */ + if (this->type->qualifier.flags.q.varying) { + if (this->type->qualifier.flags.q.in) { + _mesa_glsl_error(& loc, state, + "`varying in' qualifier in declaration of " + "`%s' only valid for geometry shaders using " + "ARB_geometry_shader4 or EXT_geometry_shader4", + decl->identifier); + } else if (this->type->qualifier.flags.q.out) { + _mesa_glsl_error(& loc, state, + "`varying out' qualifier in declaration of " + "`%s' only valid for geometry shaders using " + "ARB_geometry_shader4 or EXT_geometry_shader4", + decl->identifier); + } + } + /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification; * * "Global variables can only use the qualifiers const, @@ -2796,7 +2934,22 @@ ast_declarator_list::hir(exec_list *instructions, "cannot have array type")) { error_emitted = true; } - } + } else if (state->target == geometry_shader) { + /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: + * + * Geometry shader input variables get the per-vertex values + * written out by vertex shader output variables of the same + * names. Since a geometry shader operates on a set of + * vertices, each input varying variable (or input block, see + * interface blocks below) needs to be declared as an array. + */ + if (!var->type->is_array()) { + _mesa_glsl_error(&loc, state, + "geometry shader inputs must be arrays"); + } + + handle_geometry_shader_input_decl(state, loc, var); + } } /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES, @@ -2906,7 +3059,7 @@ ast_declarator_list::hir(exec_list *instructions, } break; default: - assert(0); + break; } } @@ -3015,6 +3168,33 @@ ast_declarator_list::hir(exec_list *instructions, decl->identifier); } + if (state->es_shader) { + const glsl_type *const t = (earlier == NULL) + ? var->type : earlier->type; + + if (t->is_array() && t->length == 0) + /* Section 10.17 of the GLSL ES 1.00 specification states that + * unsized array declarations have been removed from the language. + * Arrays that are sized using an initializer are still explicitly + * sized. However, GLSL ES 1.00 does not allow array + * initializers. That is only allowed in GLSL ES 3.00. + * + * Section 4.1.9 (Arrays) of the GLSL ES 3.00 spec says: + * + * "An array type can also be formed without specifying a size + * if the definition includes an initializer: + * + * float x[] = float[2] (1.0, 2.0); // declares an array of size 2 + * float y[] = float[] (1.0, 2.0, 3.0); // declares an array of size 3 + * + * float a[5]; + * float b[] = a;" + */ + _mesa_glsl_error(& loc, state, + "unsized array declarations are not allowed in " + "GLSL ES"); + } + /* If the declaration is not a redeclaration, there are a few additional * semantic checks that must be applied. In addition, variable that was * created for the declaration should be added to the IR stream. @@ -3323,6 +3503,18 @@ ast_function::hir(exec_list *instructions, "function `%s' return type has qualifiers", name); } + /* Section 6.1 (Function Definitions) of the GLSL 1.20 spec says: + * + * "Arrays are allowed as arguments and as the return type. In both + * cases, the array must be explicitly sized." + */ + if (return_type->is_array() && return_type->length == 0) { + YYLTYPE loc = this->get_location(); + _mesa_glsl_error(& loc, state, + "function `%s' return type array must be explicitly " + "sized", name); + } + /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: * * "[Sampler types] can only be declared as function parameters @@ -4362,6 +4554,19 @@ ast_interface_block::hir(exec_list *instructions, */ assert(declared_variables.is_empty()); + /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: + * + * Geometry shader input variables get the per-vertex values written + * out by vertex shader output variables of the same names. Since a + * geometry shader operates on a set of vertices, each input varying + * variable (or input block, see interface blocks below) needs to be + * declared as an array. + */ + if (state->target == geometry_shader && !this->is_array && + var_mode == ir_var_shader_in) { + _mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays"); + } + /* Page 39 (page 45 of the PDF) of section 4.3.7 in the GLSL ES 3.00 spec * says: * @@ -4372,7 +4577,34 @@ ast_interface_block::hir(exec_list *instructions, if (this->instance_name) { ir_variable *var; - if (this->array_size != NULL) { + if (this->is_array) { + /* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says: + * + * For uniform blocks declared an array, each individual array + * element corresponds to a separate buffer object backing one + * instance of the block. As the array size indicates the number + * of buffer objects needed, uniform block array declarations + * must specify an array size. + * + * And a few paragraphs later: + * + * Geometry shader input blocks must be declared as arrays and + * follow the array declaration and linking rules for all + * geometry shader inputs. All other input and output block + * arrays must specify an array size. + * + * The upshot of this is that the only circumstance where an + * interface array size *doesn't* need to be specified is on a + * geometry shader input. + */ + if (this->array_size == NULL && + (state->target != geometry_shader || !this->layout.flags.q.in)) { + _mesa_glsl_error(&loc, state, + "only geometry shader inputs may be unsized " + "instance block arrays"); + + } + const glsl_type *block_array_type = process_array_type(&loc, block_type, this->array_size, state); @@ -4386,13 +4618,15 @@ ast_interface_block::hir(exec_list *instructions, } var->interface_type = block_type; + if (state->target == geometry_shader && var_mode == ir_var_shader_in) + handle_geometry_shader_input_decl(state, loc, var); state->symbols->add_variable(var); instructions->push_tail(var); } else { /* In order to have an array size, the block must also be declared with * an instane name. */ - assert(this->array_size == NULL); + assert(!this->is_array); for (unsigned i = 0; i < num_variables; i++) { ir_variable *var = @@ -4416,6 +4650,72 @@ ast_interface_block::hir(exec_list *instructions, return NULL; } + +ir_rvalue * +ast_gs_input_layout::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + YYLTYPE loc = this->get_location(); + + /* If any geometry input layout declaration preceded this one, make sure it + * was consistent with this one. + */ + if (state->gs_input_prim_type_specified && + state->gs_input_prim_type != this->prim_type) { + _mesa_glsl_error(&loc, state, + "geometry shader input layout does not match" + " previous declaration"); + return NULL; + } + + /* If any shader inputs occurred before this declaration and specified an + * array size, make sure the size they specified is consistent with the + * primitive type. + */ + unsigned num_vertices = vertices_per_prim(this->prim_type); + if (state->gs_input_size != 0 && state->gs_input_size != num_vertices) { + _mesa_glsl_error(&loc, state, + "this geometry shader input layout implies %u vertices" + " per primitive, but a previous input is declared" + " with size %u", num_vertices, state->gs_input_size); + return NULL; + } + + 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. + */ + foreach_list (node, instructions) { + ir_variable *var = ((ir_instruction *) node)->as_variable(); + if (var == NULL || var->mode != ir_var_shader_in) + continue; + + /* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an + * array; skip it. + */ + if (!var->type->is_array()) + continue; + + if (var->type->length == 0) { + if (var->max_array_access >= num_vertices) { + _mesa_glsl_error(&loc, state, + "this geometry shader input layout implies %u" + " vertices, but an access to element %u of input" + " `%s' already exists", num_vertices, + var->max_array_access, var->name); + } else { + var->type = glsl_type::get_array_instance(var->type->fields.array, + num_vertices); + } + } + } + + return NULL; +} + + static void detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, exec_list *instructions) |