X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fast_to_hir.cpp;h=a15ee9c057237bc3c37b2fc8c8ba25b5d676bd71;hb=0779f37e1589b0ba4f1443a889f34dd83607c117;hp=a57ce5058e1775d9138ab2556515a906c47ccb8c;hpb=5ecffe5a3a41cac5fe28d8136095a0c2acf385a8;p=mesa.git diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index a57ce5058e1..a15ee9c0572 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -49,7 +49,6 @@ * parser (and lexer) sources. */ -#include "main/core.h" /* for struct gl_extensions */ #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ast.h" @@ -113,8 +112,8 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) * applications depend on this behavior, and it matches what nearly all * other drivers do. */ - foreach_list_safe(node, instructions) { - ir_variable *const var = ((ir_instruction *) node)->as_variable(); + foreach_in_list_safe(ir_instruction, node, instructions) { + ir_variable *const var = node->as_variable(); if (var == NULL) continue; @@ -164,6 +163,31 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) } +static ir_expression_operation +get_conversion_operation(const glsl_type *to, const glsl_type *from, + struct _mesa_glsl_parse_state *state) +{ + switch (to->base_type) { + case GLSL_TYPE_FLOAT: + switch (from->base_type) { + case GLSL_TYPE_INT: return ir_unop_i2f; + case GLSL_TYPE_UINT: return ir_unop_u2f; + default: return (ir_expression_operation)0; + } + + case GLSL_TYPE_UINT: + if (!state->is_version(400, 0) && !state->ARB_gpu_shader5_enable) + return (ir_expression_operation)0; + switch (from->base_type) { + case GLSL_TYPE_INT: return ir_unop_i2u; + default: return (ir_expression_operation)0; + } + + default: return (ir_expression_operation)0; + } +} + + /** * If a conversion is available, convert one operand to a different type * @@ -185,9 +209,7 @@ apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, if (to->base_type == from->type->base_type) return true; - /* This conversion was added in GLSL 1.20. If the compilation mode is - * GLSL 1.10, the conversion is skipped. - */ + /* Prior to GLSL 1.20, there are no implicit conversions */ if (!state->is_version(120, 0)) return false; @@ -195,36 +217,25 @@ apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, * * "There are no implicit array or structure conversions. For * example, an array of int cannot be implicitly converted to an - * array of float. There are no implicit conversions between - * signed and unsigned integers." + * array of float. */ - /* FINISHME: The above comment is partially a lie. There is int/uint - * FINISHME: conversion for immediate constants. - */ - if (!to->is_float() || !from->type->is_numeric()) + if (!to->is_numeric() || !from->type->is_numeric()) return false; - /* Convert to a floating point type with the same number of components - * as the original type - i.e. int to float, not int to vec4. + /* We don't actually want the specific type `to`, we want a type + * with the same base type as `to`, but the same vector width as + * `from`. */ - to = glsl_type::get_instance(GLSL_TYPE_FLOAT, from->type->vector_elements, - from->type->matrix_columns); + to = glsl_type::get_instance(to->base_type, from->type->vector_elements, + from->type->matrix_columns); - switch (from->type->base_type) { - case GLSL_TYPE_INT: - from = new(ctx) ir_expression(ir_unop_i2f, to, from, NULL); - break; - case GLSL_TYPE_UINT: - from = new(ctx) ir_expression(ir_unop_u2f, to, from, NULL); - break; - case GLSL_TYPE_BOOL: - from = new(ctx) ir_expression(ir_unop_b2f, to, from, NULL); - break; - default: - assert(0); + ir_expression_operation op = get_conversion_operation(to, from->type, state); + if (op) { + from = new(ctx) ir_expression(op, to, from, NULL); + return true; + } else { + return false; } - - return true; } @@ -2170,6 +2181,41 @@ validate_explicit_location(const struct ast_type_qualifier *qual, { bool fail = false; + /* Checks for GL_ARB_explicit_uniform_location. */ + if (qual->flags.q.uniform) { + if (!state->check_explicit_uniform_location_allowed(loc, var)) + return; + + const struct gl_context *const ctx = state->ctx; + unsigned max_loc = qual->location + var->type->uniform_locations() - 1; + + /* ARB_explicit_uniform_location specification states: + * + * "The explicitly defined locations and the generated locations + * must be in the range of 0 to MAX_UNIFORM_LOCATIONS minus one." + * + * "Valid locations for default-block uniform variable locations + * are in the range of 0 to the implementation-defined maximum + * number of uniform locations." + */ + if (qual->location < 0) { + _mesa_glsl_error(loc, state, + "explicit location < 0 for uniform %s", var->name); + return; + } + + if (max_loc >= ctx->Const.MaxUserAssignableUniformLocations) { + _mesa_glsl_error(loc, state, "location(s) consumed by uniform %s " + ">= MAX_UNIFORM_LOCATIONS (%u)", var->name, + ctx->Const.MaxUserAssignableUniformLocations); + return; + } + + var->data.explicit_location = true; + var->data.location = qual->location; + return; + } + /* Between GL_ARB_explicit_attrib_location an * GL_ARB_separate_shader_objects, the inputs and outputs of any shader * stage can be assigned explicit locations. The checking here associates @@ -2415,6 +2461,11 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (qual->flags.q.sample) var->data.sample = 1; + if (state->stage == MESA_SHADER_GEOMETRY && + qual->flags.q.out && qual->flags.q.stream) { + var->data.stream = qual->stream; + } + if (qual->flags.q.attribute && state->stage != MESA_SHADER_VERTEX) { var->type = glsl_type::error_type; _mesa_glsl_error(loc, state, @@ -2423,6 +2474,13 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, _mesa_shader_stage_to_string(state->stage)); } + /* Disallow layout qualifiers which may only appear on layout declarations. */ + if (qual->flags.q.prim_type) { + _mesa_glsl_error(loc, state, + "Primitive type may only be specified on GS input or output " + "layout declaration, not on variables."); + } + /* 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." @@ -2637,6 +2695,36 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, const bool uses_deprecated_qualifier = qual->flags.q.attribute || qual->flags.q.varying; + + /* Validate auxiliary storage qualifiers */ + + /* From section 4.3.4 of the GLSL 1.30 spec: + * "It is an error to use centroid in in a vertex shader." + * + * From section 4.3.4 of the GLSL ES 3.00 spec: + * "It is an error to use centroid in or interpolation qualifiers in + * a vertex shader input." + */ + + /* Section 4.3.6 of the GLSL 1.30 specification states: + * "It is an error to use centroid out in a fragment shader." + * + * The GL_ARB_shading_language_420pack extension specification states: + * "It is an error to use auxiliary storage qualifiers or interpolation + * qualifiers on an output in a fragment shader." + */ + if (qual->flags.q.sample && (!is_varying_var(var, state->stage) || uses_deprecated_qualifier)) { + _mesa_glsl_error(loc, state, + "sample qualifier may only be used on `in` or `out` " + "variables between shader stages"); + } + if (qual->flags.q.centroid && !is_varying_var(var, state->stage)) { + _mesa_glsl_error(loc, state, + "centroid qualifier may only be used with `in', " + "`out' or `varying' variables between shader stages"); + } + + /* Is the 'layout' keyword used with parameters that allow relaxed checking. * Many implementations of GL_ARB_fragment_coord_conventions_enable and some * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable @@ -3187,6 +3275,15 @@ ast_declarator_list::hir(exec_list *instructions, _mesa_glsl_error(& loc, state, "undeclared variable `%s' cannot be marked " "precise", decl->identifier); + } else if (state->current_function != NULL && + !state->symbols->name_declared_this_scope(decl->identifier)) { + /* Note: we have to check if we're in a function, since + * builtins are treated as having come from another scope. + */ + _mesa_glsl_error(& loc, state, + "variable `%s' from an outer scope may not be " + "redeclared `precise' in this scope", + earlier->name); } else if (earlier->data.used) { _mesa_glsl_error(& loc, state, "variable `%s' may not be redeclared " @@ -3585,45 +3682,6 @@ ast_declarator_list::hir(exec_list *instructions, } - /* From section 4.3.4 of the GLSL 1.30 spec: - * "It is an error to use centroid in in a vertex shader." - * - * From section 4.3.4 of the GLSL ES 3.00 spec: - * "It is an error to use centroid in or interpolation qualifiers in - * a vertex shader input." - */ - if (state->is_version(130, 300) - && this->type->qualifier.flags.q.centroid - && this->type->qualifier.flags.q.in - && state->stage == MESA_SHADER_VERTEX) { - - _mesa_glsl_error(&loc, state, - "'centroid in' cannot be used in a vertex shader"); - } - - if (state->stage == MESA_SHADER_VERTEX - && this->type->qualifier.flags.q.sample - && this->type->qualifier.flags.q.in) { - - _mesa_glsl_error(&loc, state, - "'sample in' cannot be used in a vertex shader"); - } - - /* Section 4.3.6 of the GLSL 1.30 specification states: - * "It is an error to use centroid out in a fragment shader." - * - * The GL_ARB_shading_language_420pack extension specification states: - * "It is an error to use auxiliary storage qualifiers or interpolation - * qualifiers on an output in a fragment shader." - */ - if (state->stage == MESA_SHADER_FRAGMENT && - this->type->qualifier.flags.q.out && - this->type->qualifier.has_auxiliary_storage()) { - _mesa_glsl_error(&loc, state, - "auxiliary storage qualifiers cannot be used on " - "fragment shader outputs"); - } - /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30. */ if (this->type->qualifier.precision != ast_precision_none) { @@ -4152,10 +4210,8 @@ ast_function_definition::hir(exec_list *instructions, * Add these to the symbol table. */ state->symbols->push_scope(); - foreach_list(n, &signature->parameters) { - ir_variable *const var = ((ir_instruction *) n)->as_variable(); - - assert(var != NULL); + foreach_in_list(ir_variable, var, &signature->parameters) { + assert(var->as_variable() != NULL); /* The only way a parameter would "exist" is if two parameters have * the same name. @@ -4457,6 +4513,12 @@ ast_switch_statement::hir(exec_list *instructions, instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var, is_break_val)); + state->switch_state.run_default = + new(ctx) ir_variable(glsl_type::bool_type, + "run_default_tmp", + ir_var_temporary); + instructions->push_tail(state->switch_state.run_default); + /* Cache test expression. */ test_to_hir(instructions, state); @@ -4511,8 +4573,71 @@ ir_rvalue * ast_case_statement_list::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { - foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases) - case_stmt->hir(instructions, state); + exec_list default_case, after_default, tmp; + + foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases) { + case_stmt->hir(&tmp, state); + + /* Default case. */ + if (state->switch_state.previous_default && default_case.is_empty()) { + default_case.append_list(&tmp); + continue; + } + + /* If default case found, append 'after_default' list. */ + if (!default_case.is_empty()) + after_default.append_list(&tmp); + else + instructions->append_list(&tmp); + } + + /* Handle the default case. This is done here because default might not be + * the last case. We need to add checks against following cases first to see + * if default should be chosen or not. + */ + if (!default_case.is_empty()) { + + /* Default case was the last one, no checks required. */ + if (after_default.is_empty()) { + instructions->append_list(&default_case); + return NULL; + } + + ir_rvalue *const true_val = new (state) ir_constant(true); + ir_dereference_variable *deref_run_default_var = + new(state) ir_dereference_variable(state->switch_state.run_default); + + /* Choose to run default case initially, following conditional + * assignments might change this. + */ + ir_assignment *const init_var = + new(state) ir_assignment(deref_run_default_var, true_val); + instructions->push_tail(init_var); + + foreach_in_list(ir_instruction, ir, &after_default) { + ir_assignment *assign = ir->as_assignment(); + + if (!assign) + continue; + + /* Clone the check between case label and init expression. */ + ir_expression *exp = (ir_expression*) assign->condition; + ir_expression *clone = exp->clone(state, NULL); + + ir_dereference_variable *deref_var = + new(state) ir_dereference_variable(state->switch_state.run_default); + ir_rvalue *const false_val = new (state) ir_constant(false); + + ir_assignment *const set_false = + new(state) ir_assignment(deref_var, false_val, clone); + + instructions->push_tail(set_false); + } + + /* Append default case and all cases after it. */ + instructions->append_list(&default_case); + instructions->append_list(&after_default); + } /* Case statements do not have r-values. */ return NULL; @@ -4611,9 +4736,51 @@ ast_case_label::hir(exec_list *instructions, ir_dereference_variable *deref_test_var = new(ctx) ir_dereference_variable(state->switch_state.test_var); - ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal, - label_const, - deref_test_var); + ir_expression *test_cond = new(ctx) ir_expression(ir_binop_all_equal, + label_const, + deref_test_var); + + /* + * From GLSL 4.40 specification section 6.2 ("Selection"): + * + * "The type of the init-expression value in a switch statement must + * be a scalar int or uint. The type of the constant-expression value + * in a case label also must be a scalar int or uint. When any pair + * of these values is tested for "equal value" and the types do not + * match, an implicit conversion will be done to convert the int to a + * uint (see section 4.1.10 “Implicit Conversions”) before the compare + * is done." + */ + if (label_const->type != state->switch_state.test_var->type) { + YYLTYPE loc = this->test_value->get_location(); + + const glsl_type *type_a = label_const->type; + const glsl_type *type_b = state->switch_state.test_var->type; + + /* Check if int->uint implicit conversion is supported. */ + bool integer_conversion_supported = + glsl_type::int_type->can_implicitly_convert_to(glsl_type::uint_type, + state); + + if ((!type_a->is_integer() || !type_b->is_integer()) || + !integer_conversion_supported) { + _mesa_glsl_error(&loc, state, "type mismatch with switch " + "init-expression and case label (%s != %s)", + type_a->name, type_b->name); + } else { + /* Conversion of the case label. */ + if (type_a->base_type == GLSL_TYPE_INT) { + if (!apply_implicit_conversion(glsl_type::uint_type, + test_cond->operands[0], state)) + _mesa_glsl_error(&loc, state, "implicit type conversion error"); + } else { + /* Conversion of the init-expression value. */ + if (!apply_implicit_conversion(glsl_type::uint_type, + test_cond->operands[1], state)) + _mesa_glsl_error(&loc, state, "implicit type conversion error"); + } + } + } ir_assignment *set_fallthru_on_test = new(ctx) ir_assignment(deref_fallthru_var, true_val, test_cond); @@ -4630,9 +4797,17 @@ ast_case_label::hir(exec_list *instructions, } state->switch_state.previous_default = this; + /* Set fallthru condition on 'run_default' bool. */ + ir_dereference_variable *deref_run_default = + new(ctx) ir_dereference_variable(state->switch_state.run_default); + ir_rvalue *const cond_true = new(ctx) ir_constant(true); + ir_expression *test_cond = new(ctx) ir_expression(ir_binop_all_equal, + cond_true, + deref_run_default); + /* Set falltrhu state. */ ir_assignment *set_fallthru = - new(ctx) ir_assignment(deref_fallthru_var, true_val); + new(ctx) ir_assignment(deref_fallthru_var, true_val, test_cond); instructions->push_tail(set_fallthru); } @@ -4909,9 +5084,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, * 'declarations' list in each of the elements. */ foreach_list_typed (ast_declarator_list, decl_list, link, declarations) { - foreach_list_const (decl_ptr, & decl_list->declarations) { - decl_count++; - } + decl_count += decl_list->declarations.length(); } /* Allocate storage for the fields and process the field @@ -5005,6 +5178,9 @@ ast_process_structure_or_interface_block(exec_list *instructions, fields[i].centroid = qual->flags.q.centroid ? 1 : 0; fields[i].sample = qual->flags.q.sample ? 1 : 0; + /* Only save explicitly defined streams in block's field */ + fields[i].stream = qual->flags.q.explicit_stream ? qual->stream : -1; + if (qual->flags.q.row_major || qual->flags.q.column_major) { if (!qual->flags.q.uniform) { _mesa_glsl_error(&loc, state, @@ -5020,6 +5196,13 @@ ast_process_structure_or_interface_block(exec_list *instructions, "with uniform interface blocks"); } + if ((qual->flags.q.uniform || !is_interface) && + qual->has_auxiliary_storage()) { + _mesa_glsl_error(&loc, state, + "auxiliary storage qualifiers cannot be used " + "in uniform blocks or structures."); + } + if (field_type->is_matrix() || (field_type->is_array() && field_type->fields.array->is_matrix())) { fields[i].row_major = block_row_major; @@ -5029,7 +5212,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, fields[i].row_major = false; } - i++; + i++; } } @@ -5069,7 +5252,7 @@ ast_struct_specifier::hir(exec_list *instructions, */ if (state->language_version != 110 && state->struct_specifier_depth != 0) _mesa_glsl_error(&loc, state, - "embedded structure declartions are not allowed"); + "embedded structure declarations are not allowed"); state->struct_specifier_depth++; @@ -5185,6 +5368,12 @@ ast_interface_block::hir(exec_list *instructions, bool block_row_major = this->layout.flags.q.row_major; exec_list declared_variables; glsl_struct_field *fields; + + /* Treat an interface block as one level of nesting, so that embedded struct + * specifiers will be disallowed. + */ + state->struct_specifier_depth++; + unsigned int num_variables = ast_process_structure_or_interface_block(&declared_variables, state, @@ -5196,6 +5385,8 @@ ast_interface_block::hir(exec_list *instructions, redeclaring_per_vertex, var_mode); + state->struct_specifier_depth--; + if (!redeclaring_per_vertex) validate_identifier(this->block_name, loc, state); @@ -5438,6 +5629,17 @@ ast_interface_block::hir(exec_list *instructions, var->data.sample = fields[i].sample; var->init_interface_type(block_type); + if (fields[i].stream != -1 && + ((unsigned)fields[i].stream) != this->layout.stream) { + _mesa_glsl_error(&loc, state, + "stream layout qualifier on " + "interface block member `%s' does not match " + "the interface block (%d vs %d)", + var->name, fields[i].stream, this->layout.stream); + } + + var->data.stream = this->layout.stream; + if (redeclaring_per_vertex) { ir_variable *earlier = get_variable_being_redeclared(var, loc, state, @@ -5492,8 +5694,8 @@ ast_interface_block::hir(exec_list *instructions, * thinking there are conflicting definitions of gl_PerVertex in the * shader. */ - foreach_list_safe(node, instructions) { - ir_variable *const var = ((ir_instruction *) node)->as_variable(); + foreach_in_list_safe(ir_instruction, node, instructions) { + ir_variable *const var = node->as_variable(); if (var != NULL && var->get_interface_type() == earlier_per_vertex && var->data.mode == var_mode) { @@ -5549,8 +5751,8 @@ ast_gs_input_layout::hir(exec_list *instructions, /* 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(); + foreach_in_list(ir_instruction, node, instructions) { + ir_variable *var = node->as_variable(); if (var == NULL || var->data.mode != ir_var_shader_in) continue; @@ -5667,8 +5869,8 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, YYLTYPE loc; memset(&loc, 0, sizeof(loc)); - foreach_list(node, instructions) { - ir_variable *var = ((ir_instruction *)node)->as_variable(); + foreach_in_list(ir_instruction, node, instructions) { + ir_variable *var = node->as_variable(); if (!var || !var->data.assigned) continue; @@ -5757,8 +5959,8 @@ remove_per_vertex_blocks(exec_list *instructions, /* Remove any ir_variable declarations that refer to the interface block * we're removing. */ - foreach_list_safe(node, instructions) { - ir_variable *const var = ((ir_instruction *) node)->as_variable(); + foreach_in_list_safe(ir_instruction, node, instructions) { + ir_variable *const var = node->as_variable(); if (var != NULL && var->get_interface_type() == per_vertex && var->data.mode == mode) { state->symbols->disable_variable(var->name);