glsl: apply implicit matching rules when linking

Previously when linking i.e. when compiler state was NULL. We just
assumed all implicit matching was avaliable.

Acked-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30752>
This commit is contained in:
Timothy Arceri 2024-08-20 09:43:59 +10:00
parent 018ebeca72
commit 8e4b14dcfd
11 changed files with 80 additions and 33 deletions

View file

@ -704,6 +704,8 @@ match_function_by_name(const char *name,
/* 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,
state->has_implicit_conversions(),
state->has_implicit_int_to_uint_conversion(),
allow_builtins, &is_exact);
if (is_exact)
return sig;
@ -755,6 +757,8 @@ match_subroutine_by_name(const char *name,
return NULL;
*var_r = var;
sig = found->matching_signature(state, actual_parameters,
state->has_implicit_conversions(),
state->has_implicit_int_to_uint_conversion(),
false, &is_exact);
return sig;
}
@ -1162,7 +1166,9 @@ implicitly_convert_component(ir_rvalue * &from, const glsl_base_type to,
from->type->vector_elements,
from->type->matrix_columns);
if (_mesa_glsl_can_implicitly_convert(from->type, desired_type, state)) {
if (_mesa_glsl_can_implicitly_convert(from->type, desired_type,
state->has_implicit_conversions(),
state->has_implicit_int_to_uint_conversion())) {
/* 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

View file

@ -6448,6 +6448,8 @@ ast_function::hir(exec_list *instructions,
continue;
tsig = fn->matching_signature(state, &sig->parameters,
state->has_implicit_conversions(),
state->has_implicit_int_to_uint_conversion(),
false);
if (!tsig) {
_mesa_glsl_error(& loc, state, "subroutine type mismatch '%s' - signatures do not match\n", decl->identifier);
@ -7152,7 +7154,9 @@ ast_case_label::hir(exec_list *instructions,
/* Check if int->uint implicit conversion is supported. */
bool integer_conversion_supported =
_mesa_glsl_can_implicitly_convert(&glsl_type_builtin_int, &glsl_type_builtin_uint, state);
_mesa_glsl_can_implicitly_convert(&glsl_type_builtin_int, &glsl_type_builtin_uint,
state->has_implicit_conversions(),
state->has_implicit_int_to_uint_conversion());
if ((!glsl_type_is_integer_32(type_a) || !glsl_type_is_integer_32(type_b)) ||
!integer_conversion_supported) {

View file

@ -1461,7 +1461,10 @@ builtin_builder::find(_mesa_glsl_parse_state *state,
return NULL;
ir_function_signature *sig =
f->matching_signature(state, actual_parameters, true);
f->matching_signature(state, actual_parameters,
state->has_implicit_conversions(),
state->has_implicit_int_to_uint_conversion(),
true);
if (sig == NULL)
return NULL;
@ -9051,7 +9054,7 @@ _mesa_get_main_function_signature(glsl_symbol_table *symbols)
* shaders) because that would have already been caught above.
*/
ir_function_signature *sig =
f->matching_signature(NULL, &void_parameters, false);
f->matching_signature(NULL, &void_parameters, false, false, false);
if ((sig != NULL) && sig->is_defined) {
return sig;
}

View file

@ -960,16 +960,14 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
bool
_mesa_glsl_can_implicitly_convert(const glsl_type *from, const glsl_type *desired,
_mesa_glsl_parse_state *state)
bool has_implicit_conversions,
bool has_implicit_int_to_uint_conversion)
{
if (from == desired)
return true;
/* GLSL 1.10 and ESSL do not allow implicit conversions. If there is no
* state, we're doing intra-stage function linking where these checks have
* already been done.
*/
if (state && !state->has_implicit_conversions())
/* GLSL 1.10 and ESSL do not allow implicit conversions. */
if (!has_implicit_conversions)
return false;
/* There is no conversion among matrix types. */
@ -991,8 +989,8 @@ _mesa_glsl_can_implicitly_convert(const glsl_type *from, const glsl_type *desire
* state-dependent checks have already happened though, so allow anything
* that's allowed in any shader version.
*/
if ((!state || state->has_implicit_int_to_uint_conversion()) &&
desired->base_type == GLSL_TYPE_UINT && from->base_type == GLSL_TYPE_INT)
if (has_implicit_int_to_uint_conversion &&
desired->base_type == GLSL_TYPE_UINT && from->base_type == GLSL_TYPE_INT)
return true;
/* No implicit conversions from double. */

View file

@ -1087,7 +1087,8 @@ extern bool _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
* \endverbatim
*/
extern bool _mesa_glsl_can_implicitly_convert(const glsl_type *from, const glsl_type *desired,
_mesa_glsl_parse_state *state);
bool has_implicit_conversions,
bool has_implicit_int_to_uint_conversion);
#endif /* __cplusplus */

View file

@ -1313,6 +1313,8 @@ public:
*/
ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
const exec_list *actual_param,
bool has_implicit_conversions,
bool has_implicit_int_to_uint_conversion,
bool allow_builtins,
bool *match_is_exact);
@ -1322,6 +1324,8 @@ public:
*/
ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
const exec_list *actual_param,
bool has_implicit_conversions,
bool has_implicit_int_to_uint_conversion,
bool allow_builtins);
/**

View file

@ -52,7 +52,8 @@ get_param_type(const ir_instruction *inst)
* \see matching_signature()
*/
static parameter_list_match_t
parameter_lists_match(_mesa_glsl_parse_state *state,
parameter_lists_match(bool has_implicit_conversions,
bool has_implicit_int_to_uint_conversion,
const exec_list *list_a, const exec_list *list_b)
{
const exec_node *node_a = list_a->get_head_raw();
@ -99,12 +100,16 @@ parameter_lists_match(_mesa_glsl_parse_state *state,
case ir_var_const_in:
case ir_var_function_in:
if (param->data.implicit_conversion_prohibited ||
!_mesa_glsl_can_implicitly_convert(actual_type, param->type, state))
!_mesa_glsl_can_implicitly_convert(actual_type, param->type,
has_implicit_conversions,
has_implicit_int_to_uint_conversion))
return PARAMETER_LIST_NO_MATCH;
break;
case ir_var_function_out:
if (!_mesa_glsl_can_implicitly_convert(param->type, actual_type, state))
if (!_mesa_glsl_can_implicitly_convert(param->type, actual_type,
has_implicit_conversions,
has_implicit_int_to_uint_conversion))
return PARAMETER_LIST_NO_MATCH;
break;
@ -305,16 +310,21 @@ choose_best_inexact_overload(_mesa_glsl_parse_state *state,
ir_function_signature *
ir_function::matching_signature(_mesa_glsl_parse_state *state,
const exec_list *actual_parameters,
bool has_implicit_conversions,
bool has_implicit_int_to_uint_conversion,
bool allow_builtins)
{
bool is_exact;
return matching_signature(state, actual_parameters, allow_builtins,
&is_exact);
return matching_signature(state, actual_parameters, has_implicit_conversions,
has_implicit_int_to_uint_conversion,
allow_builtins, &is_exact);
}
ir_function_signature *
ir_function::matching_signature(_mesa_glsl_parse_state *state,
const exec_list *actual_parameters,
bool has_implicit_conversions,
bool has_implicit_int_to_uint_conversion,
bool allow_builtins,
bool *is_exact)
{
@ -339,7 +349,9 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
!sig->is_builtin_available(state)))
continue;
switch (parameter_lists_match(state, & sig->parameters, actual_parameters)) {
switch (parameter_lists_match(has_implicit_conversions,
has_implicit_int_to_uint_conversion,
&sig->parameters, actual_parameters)) {
case PARAMETER_LIST_EXACT_MATCH:
*is_exact = true;
free(inexact_matches);

View file

@ -687,7 +687,10 @@ ir_reader::read_call(s_expression *expr)
}
ir_function_signature *callee =
f->matching_signature(state, &parameters, true);
f->matching_signature(state, &parameters,
state->has_implicit_conversions(),
state->has_implicit_int_to_uint_conversion(),
true);
if (callee == NULL) {
ir_read_error(expr, "couldn't find matching signature for function "
"%s", name->value());

View file

@ -32,20 +32,24 @@
static ir_function_signature *
find_matching_signature(const char *name, const exec_list *actual_parameters,
glsl_symbol_table *symbols);
glsl_symbol_table *symbols,
bool has_implicit_conversions,
bool has_implicit_int_to_uint_conversion);
namespace {
class call_link_visitor : public ir_hierarchical_visitor {
public:
call_link_visitor(gl_shader_program *prog, gl_linked_shader *linked,
gl_shader **shader_list, unsigned num_shaders)
gl_shader *main, gl_shader **shader_list,
unsigned num_shaders)
{
this->prog = prog;
this->shader_list = shader_list;
this->num_shaders = num_shaders;
this->success = true;
this->linked = linked;
this->main = main;
this->locals = _mesa_pointer_set_create(NULL);
}
@ -81,7 +85,9 @@ public:
* final linked shader. If it does, use it as the target of the call.
*/
ir_function_signature *sig =
find_matching_signature(name, &callee->parameters, linked->symbols);
find_matching_signature(name, &callee->parameters, linked->symbols,
main->has_implicit_conversions,
main->has_implicit_int_to_uint_conversion);
if (sig != NULL) {
ir->callee = sig;
return visit_continue;
@ -92,7 +98,9 @@ public:
*/
for (unsigned i = 0; i < num_shaders; i++) {
sig = find_matching_signature(name, &ir->actual_parameters,
shader_list[i]->symbols);
shader_list[i]->symbols,
shader_list[i]->has_implicit_conversions,
shader_list[i]->has_implicit_int_to_uint_conversion);
if (sig)
break;
}
@ -299,6 +307,8 @@ private:
*/
gl_linked_shader *linked;
gl_shader *main;
/**
* Table of variables local to the function.
*/
@ -312,13 +322,17 @@ private:
*/
ir_function_signature *
find_matching_signature(const char *name, const exec_list *actual_parameters,
glsl_symbol_table *symbols)
glsl_symbol_table *symbols,
bool has_implicit_conversions,
bool has_implicit_int_to_uint_conversion)
{
ir_function *const f = symbols->get_function(name);
if (f) {
ir_function_signature *sig =
f->matching_signature(NULL, actual_parameters, false);
f->matching_signature(NULL, actual_parameters,
has_implicit_conversions,
has_implicit_int_to_uint_conversion, false);
if (sig && (sig->is_defined || sig->is_intrinsic()))
return sig;
@ -329,11 +343,12 @@ find_matching_signature(const char *name, const exec_list *actual_parameters,
bool
link_function_calls(gl_shader_program *prog, gl_linked_shader *main,
gl_shader **shader_list, unsigned num_shaders)
link_function_calls(gl_shader_program *prog, gl_linked_shader *main_linked,
gl_shader *main, gl_shader **shader_list,
unsigned num_shaders)
{
call_link_visitor v(prog, main, shader_list, num_shaders);
call_link_visitor v(prog, main_linked, main, shader_list, num_shaders);
v.run(main->ir);
v.run(main_linked->ir);
return v.success;
}

View file

@ -1683,7 +1683,7 @@ link_intrastage_shaders(void *mem_ctx,
}
}
if (!link_function_calls(prog, linked, shader_list, num_shaders)) {
if (!link_function_calls(prog, linked, main, shader_list, num_shaders)) {
_mesa_delete_linked_shader(ctx, linked);
return NULL;
}

View file

@ -32,8 +32,9 @@ struct gl_shader;
struct gl_linked_shader;
extern bool
link_function_calls(gl_shader_program *prog, gl_linked_shader *main,
gl_shader **shader_list, unsigned num_shaders);
link_function_calls(gl_shader_program *prog, gl_linked_shader *main_linked,
gl_shader *main, gl_shader **shader_list,
unsigned num_shaders);
bool
validate_intrastage_arrays(struct gl_shader_program *prog,