X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fglsl%2Fast_function.cpp;h=cbff9d8b452ba9fab7afda1f8cc6ab12fe03af3b;hb=c5be9c126d6ca9380cd381a5eb22554e4bb71a64;hp=605ab8c297e96c2b46df08cea10615d6a737016b;hpb=23d294bb60be41e3876179e7b763a275902d1efd;p=mesa.git diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 605ab8c297e..cbff9d8b452 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -41,8 +41,7 @@ process_parameters(exec_list *instructions, exec_list *actual_parameters, { unsigned count = 0; - foreach_list (n, parameters) { - ast_node *const ast = exec_node_data(ast_node, n, link); + foreach_list_typed(ast_node, ast, link, parameters) { ir_rvalue *result = ast->hir(instructions, state); ir_constant *const constant = result->constant_expression_value(); @@ -82,9 +81,7 @@ prototype_string(const glsl_type *return_type, const char *name, ralloc_asprintf_append(&str, "%s(", name); const char *comma = ""; - foreach_list(node, parameters) { - const ir_variable *const param = (ir_variable *) node; - + foreach_in_list(const ir_variable, param, parameters) { ralloc_asprintf_append(&str, "%s%s", comma, param->type->name); comma = ", "; } @@ -93,6 +90,57 @@ prototype_string(const glsl_type *return_type, const char *name, return str; } +static bool +verify_image_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state, + const ir_variable *formal, const ir_variable *actual) +{ + /** + * From the ARB_shader_image_load_store specification: + * + * "The values of image variables qualified with coherent, + * volatile, restrict, readonly, or writeonly may not be passed + * to functions whose formal parameters lack such + * qualifiers. [...] It is legal to have additional qualifiers + * on a formal parameter, but not to have fewer." + */ + if (actual->data.image_coherent && !formal->data.image_coherent) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`coherent' qualifier", formal->name); + return false; + } + + if (actual->data.image_volatile && !formal->data.image_volatile) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`volatile' qualifier", formal->name); + return false; + } + + if (actual->data.image_restrict && !formal->data.image_restrict) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`restrict' qualifier", formal->name); + return false; + } + + if (actual->data.image_read_only && !formal->data.image_read_only) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`readonly' qualifier", formal->name); + return false; + } + + if (actual->data.image_write_only && !formal->data.image_write_only) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`writeonly' qualifier", formal->name); + return false; + } + + return true; +} + /** * Verify that 'out' and 'inout' actual parameters are lvalues. Also, verify * that 'const_in' formal parameters (an extension in our IR) correspond to @@ -107,12 +155,11 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, exec_node *actual_ir_node = actual_ir_parameters.head; exec_node *actual_ast_node = actual_ast_parameters.head; - foreach_list(formal_node, &sig->parameters) { + foreach_in_list(const ir_variable, formal, &sig->parameters) { /* The lists must be the same length. */ assert(!actual_ir_node->is_tail_sentinel()); assert(!actual_ast_node->is_tail_sentinel()); - const ir_variable *const formal = (ir_variable *) formal_node; const ir_rvalue *const actual = (ir_rvalue *) actual_ir_node; const ast_expression *const actual_ast = exec_node_data(ast_expression, actual_ast_node, link); @@ -131,6 +178,24 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, return false; } + /* Verify that shader_in parameters are shader inputs */ + if (formal->data.must_be_shader_input) { + ir_variable *var = actual->variable_referenced(); + if (var && var->data.mode != ir_var_shader_in) { + _mesa_glsl_error(&loc, state, + "parameter `%s` must be a shader input", + formal->name); + return false; + } + + if (actual->ir_type == ir_type_swizzle) { + _mesa_glsl_error(&loc, state, + "parameter `%s` must not be swizzled", + formal->name); + return false; + } + } + /* Verify that 'out' and 'inout' actual parameters are lvalues. */ if (formal->data.mode == ir_var_function_out || formal->data.mode == ir_var_function_inout) { @@ -180,6 +245,13 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, } } + if (formal->type->is_image() && + actual->variable_referenced()) { + if (!verify_image_parameter(&loc, state, formal, + actual->variable_referenced())) + return false; + } + actual_ir_node = actual_ir_node->next; actual_ast_node = actual_ast_node->next; } @@ -293,15 +365,10 @@ generate_call(exec_list *instructions, ir_function_signature *sig, * call takes place. Since we haven't emitted the call yet, we'll place * the post-call conversions in a temporary exec_list, and emit them later. */ - exec_list_iterator actual_iter = actual_parameters->iterator(); - exec_list_iterator formal_iter = sig->parameters.iterator(); - - while (actual_iter.has_next()) { - ir_rvalue *actual = (ir_rvalue *) actual_iter.get(); - ir_variable *formal = (ir_variable *) formal_iter.get(); - - assert(actual != NULL); - assert(formal != NULL); + foreach_two_lists(formal_node, &sig->parameters, + actual_node, actual_parameters) { + ir_rvalue *actual = (ir_rvalue *) actual_node; + ir_variable *formal = (ir_variable *) formal_node; if (formal->type->is_numeric() || formal->type->is_boolean()) { switch (formal->data.mode) { @@ -323,9 +390,6 @@ generate_call(exec_list *instructions, ir_function_signature *sig, break; } } - - actual_iter.next(); - formal_iter.next(); } /* If the function call is a constant expression, don't generate any @@ -344,14 +408,17 @@ generate_call(exec_list *instructions, ir_function_signature *sig, ir_dereference_variable *deref = NULL; if (!sig->return_type->is_void()) { /* Create a new temporary to hold the return value. */ + char *const name = ir_variable::temporaries_allocate_names + ? ralloc_asprintf(ctx, "%s_retval", sig->function_name()) + : NULL; + ir_variable *var; - var = new(ctx) ir_variable(sig->return_type, - ralloc_asprintf(ctx, "%s_retval", - sig->function_name()), - ir_var_temporary); + var = new(ctx) ir_variable(sig->return_type, name, ir_var_temporary); instructions->push_tail(var); + ralloc_free(name); + deref = new(ctx) ir_dereference_variable(var); } ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters); @@ -386,20 +453,21 @@ match_function_by_name(const char *name, goto done; /* no match */ if (f != NULL) { + /* In desktop GL, the presence of a user-defined signature hides any + * built-in signatures, so we must ignore them. In contrast, in ES2 + * user-defined signatures add new overloads, so we must consider them. + */ + bool allow_builtins = state->es_shader || !f->has_user_signature(); + /* Look for a match in the local shader. If exact, we're done. */ bool is_exact = false; sig = local_sig = f->matching_signature(state, actual_parameters, - &is_exact); + allow_builtins, &is_exact); if (is_exact) goto done; - if (!state->es_shader && f->has_user_signature()) { - /* In desktop GL, the presence of a user-defined signature hides any - * built-in signatures, so we must ignore them. In contrast, in ES2 - * user-defined signatures add new overloads, so we must proceed. - */ + if (!allow_builtins) goto done; - } } /* Local shader has no exact candidates; check the built-ins. */ @@ -428,9 +496,7 @@ print_function_prototypes(_mesa_glsl_parse_state *state, YYLTYPE *loc, if (f == NULL) return; - foreach_list (node, &f->signatures) { - ir_function_signature *sig = (ir_function_signature *) node; - + foreach_in_list(ir_function_signature, sig, &f->signatures) { if (sig->is_builtin() && !sig->is_builtin_available(state)) continue; @@ -450,17 +516,24 @@ no_matching_function_error(const char *name, exec_list *actual_parameters, _mesa_glsl_parse_state *state) { - char *str = prototype_string(NULL, name, actual_parameters); - _mesa_glsl_error(loc, state, - "no matching function for call to `%s'; candidates are:", - str); - ralloc_free(str); + gl_shader *sh = _mesa_glsl_get_builtin_function_shader(); - print_function_prototypes(state, loc, state->symbols->get_function(name)); + if (state->symbols->get_function(name) == NULL + && (!state->uses_builtin_functions + || sh->symbols->get_function(name) == NULL)) { + _mesa_glsl_error(loc, state, "no function with name '%s'", name); + } else { + char *str = prototype_string(NULL, name, actual_parameters); + _mesa_glsl_error(loc, state, + "no matching function for call to `%s'; candidates are:", + str); + ralloc_free(str); + + print_function_prototypes(state, loc, state->symbols->get_function(name)); - if (state->uses_builtin_functions) { - gl_shader *sh = _mesa_glsl_get_builtin_function_shader(); - print_function_prototypes(state, loc, sh->symbols->get_function(name)); + if (state->uses_builtin_functions) { + print_function_prototypes(state, loc, sh->symbols->get_function(name)); + } } } @@ -633,8 +706,7 @@ process_vec_mat_constructor(exec_list *instructions, bool all_parameters_are_constant = true; /* Type cast each parameter and, if possible, fold constants. */ - foreach_list_safe(n, &actual_parameters) { - ir_rvalue *ir = (ir_rvalue *) n; + foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) { ir_rvalue *result = ir; /* Apply implicit conversions (not the scalar constructor rules!). See @@ -644,7 +716,7 @@ process_vec_mat_constructor(exec_list *instructions, glsl_type::get_instance(GLSL_TYPE_FLOAT, ir->type->vector_elements, ir->type->matrix_columns); - if (result->type->can_implicitly_convert_to(desired_type)) { + if (result->type->can_implicitly_convert_to(desired_type, state)) { /* Even though convert_component() implements the constructor * conversion rules (not the implicit conversion rules), its safe * to use it here because we already checked that the implicit @@ -692,12 +764,22 @@ process_vec_mat_constructor(exec_list *instructions, instructions->push_tail(var); int i = 0; - foreach_list(node, &actual_parameters) { - ir_rvalue *rhs = (ir_rvalue *) node; - ir_rvalue *lhs = new(ctx) ir_dereference_array(var, - new(ctx) ir_constant(i)); - ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL); + foreach_in_list(ir_rvalue, rhs, &actual_parameters) { + ir_instruction *assignment = NULL; + + if (var->type->is_matrix()) { + ir_rvalue *lhs = new(ctx) ir_dereference_array(var, + new(ctx) ir_constant(i)); + assignment = new(ctx) ir_assignment(lhs, rhs, NULL); + } else { + /* use writemask rather than index for vector */ + assert(var->type->is_vector()); + assert(i < 4); + ir_dereference *lhs = new(ctx) ir_dereference_variable(var); + assignment = new(ctx) ir_assignment(lhs, rhs, NULL, (unsigned)(1 << i)); + } + instructions->push_tail(assignment); i++; @@ -762,8 +844,7 @@ process_array_constructor(exec_list *instructions, bool all_parameters_are_constant = true; /* Type cast each parameter and, if possible, fold constants. */ - foreach_list_safe(n, &actual_parameters) { - ir_rvalue *ir = (ir_rvalue *) n; + foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) { ir_rvalue *result = ir; /* Apply implicit conversions (not the scalar constructor rules!). See @@ -773,7 +854,7 @@ process_array_constructor(exec_list *instructions, glsl_type::get_instance(GLSL_TYPE_FLOAT, ir->type->vector_elements, ir->type->matrix_columns); - if (result->type->can_implicitly_convert_to(desired_type)) { + if (result->type->can_implicitly_convert_to(desired_type, state)) { /* Even though convert_component() implements the constructor * conversion rules (not the implicit conversion rules), its safe * to use it here because we already checked that the implicit @@ -813,8 +894,7 @@ process_array_constructor(exec_list *instructions, instructions->push_tail(var); int i = 0; - foreach_list(node, &actual_parameters) { - ir_rvalue *rhs = (ir_rvalue *) node; + foreach_in_list(ir_rvalue, rhs, &actual_parameters) { ir_rvalue *lhs = new(ctx) ir_dereference_array(var, new(ctx) ir_constant(i)); @@ -835,8 +915,8 @@ static ir_constant * constant_record_constructor(const glsl_type *constructor_type, exec_list *parameters, void *mem_ctx) { - foreach_list(node, parameters) { - ir_constant *constant = ((ir_instruction *) node)->as_constant(); + foreach_in_list(ir_instruction, node, parameters) { + ir_constant *constant = node->as_constant(); if (constant == NULL) return NULL; node->replace_with(constant); @@ -910,8 +990,7 @@ emit_inline_vector_constructor(const glsl_type *type, memset(&data, 0, sizeof(data)); - foreach_list(node, parameters) { - ir_rvalue *param = (ir_rvalue *) node; + foreach_in_list(ir_rvalue, param, parameters) { unsigned rhs_components = param->type->components(); /* Do not try to assign more components to the vector than it has! @@ -968,8 +1047,7 @@ emit_inline_vector_constructor(const glsl_type *type, } base_component = 0; - foreach_list(node, parameters) { - ir_rvalue *param = (ir_rvalue *) node; + foreach_in_list(ir_rvalue, param, parameters) { unsigned rhs_components = param->type->components(); /* Do not try to assign more components to the vector than it has! @@ -1255,8 +1333,7 @@ emit_inline_matrix_constructor(const glsl_type *type, unsigned col_idx = 0; unsigned row_idx = 0; - foreach_list (node, parameters) { - ir_rvalue *const rhs = (ir_rvalue *) node; + foreach_in_list(ir_rvalue, rhs, parameters) { const unsigned components_remaining_this_column = rows - row_idx; unsigned rhs_components = rhs->type->components(); unsigned rhs_base = 0; @@ -1501,9 +1578,8 @@ ast_function_expression::hir(exec_list *instructions, unsigned nonmatrix_parameters = 0; exec_list actual_parameters; - foreach_list (n, &this->expressions) { - ast_node *ast = exec_node_data(ast_node, n, link); - ir_rvalue *result = ast->hir(instructions, state)->as_rvalue(); + foreach_list_typed(ast_node, ast, link, &this->expressions) { + ir_rvalue *result = ast->hir(instructions, state); /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec: * @@ -1582,9 +1658,7 @@ ast_function_expression::hir(exec_list *instructions, * need to break them up into a series of column vectors. */ if (constructor_type->base_type != GLSL_TYPE_FLOAT) { - foreach_list_safe(n, &actual_parameters) { - ir_rvalue *matrix = (ir_rvalue *) n; - + foreach_in_list_safe(ir_rvalue, matrix, &actual_parameters) { if (!matrix->type->is_matrix()) continue; @@ -1608,9 +1682,7 @@ ast_function_expression::hir(exec_list *instructions, bool all_parameters_are_constant = true; /* Type cast each parameter and, if possible, fold constants.*/ - foreach_list_safe(n, &actual_parameters) { - ir_rvalue *ir = (ir_rvalue *) n; - + foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) { const glsl_type *desired_type = glsl_type::get_instance(constructor_type->base_type, ir->type->vector_elements, @@ -1688,14 +1760,12 @@ ast_aggregate_initializer::hir(exec_list *instructions, { void *ctx = state; YYLTYPE loc = this->get_location(); - const char *name; if (!this->constructor_type) { _mesa_glsl_error(&loc, state, "type of C-style initializer unknown"); return ir_rvalue::error_value(ctx); } - const glsl_type *const constructor_type = - this->constructor_type->glsl_type(&name, state); + const glsl_type *const constructor_type = this->constructor_type; if (!state->ARB_shading_language_420pack_enable) { _mesa_glsl_error(&loc, state, "C-style initialization requires the " @@ -1703,12 +1773,12 @@ ast_aggregate_initializer::hir(exec_list *instructions, return ir_rvalue::error_value(ctx); } - if (this->constructor_type->is_array) { + if (constructor_type->is_array()) { return process_array_constructor(instructions, constructor_type, &loc, &this->expressions, state); } - if (this->constructor_type->structure) { + if (constructor_type->is_record()) { return process_record_constructor(instructions, constructor_type, &loc, &this->expressions, state); }