mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 22:00:13 +01:00
nir/deref: Handle SSBO array bindings specially
Instead of just checking for the variables to match, check that the entire deref up to the interface type matches. Tested-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Reviewed-by: M Henning <drawoc@darkrefraction.com> Reviewed-by: Rhys Perry <pendingchaos02@gmail.com> Cc: mesa-stable@lists.freedesktop.org Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16894>
This commit is contained in:
parent
a5b1274275
commit
8492e78f9d
2 changed files with 261 additions and 1 deletions
|
|
@ -562,6 +562,17 @@ compare_deref_paths(nir_deref_path *a_path, nir_deref_path *b_path,
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_interface_struct_deref(const nir_deref_instr *deref)
|
||||
{
|
||||
if (deref->deref_type == nir_deref_type_struct) {
|
||||
assert(glsl_type_is_struct_or_ifc(nir_deref_instr_parent(deref)->type));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nir_deref_compare_result
|
||||
nir_compare_deref_paths(nir_deref_path *a_path,
|
||||
nir_deref_path *b_path)
|
||||
|
|
@ -572,6 +583,7 @@ nir_compare_deref_paths(nir_deref_path *a_path,
|
|||
if (a_path->path[0]->deref_type != b_path->path[0]->deref_type)
|
||||
return nir_derefs_may_alias_bit;
|
||||
|
||||
unsigned path_idx = 1;
|
||||
if (a_path->path[0]->deref_type == nir_deref_type_var) {
|
||||
const nir_variable *a_var = a_path->path[0]->var;
|
||||
const nir_variable *b_var = b_path->path[0]->var;
|
||||
|
|
@ -585,6 +597,27 @@ nir_compare_deref_paths(nir_deref_path *a_path,
|
|||
assert(a_var->data.mode == b_var->data.mode);
|
||||
|
||||
switch (a_var->data.mode) {
|
||||
case nir_var_mem_ssbo: {
|
||||
nir_deref_compare_result binding_compare;
|
||||
if (a_var == b_var) {
|
||||
binding_compare = compare_deref_paths(a_path, b_path, &path_idx,
|
||||
is_interface_struct_deref);
|
||||
} else {
|
||||
binding_compare = nir_derefs_do_not_alias;
|
||||
}
|
||||
|
||||
if (binding_compare & nir_derefs_equal_bit)
|
||||
break;
|
||||
|
||||
/* If the binding derefs can't alias and at least one is RESTRICT,
|
||||
* then we know they can't alias.
|
||||
*/
|
||||
if (!(binding_compare & nir_derefs_may_alias_bit))
|
||||
return nir_derefs_do_not_alias;
|
||||
|
||||
return nir_derefs_may_alias_bit;
|
||||
}
|
||||
|
||||
case nir_var_mem_shared:
|
||||
if (a_var == b_var)
|
||||
break;
|
||||
|
|
@ -629,7 +662,6 @@ nir_compare_deref_paths(nir_deref_path *a_path,
|
|||
return nir_derefs_may_alias_bit;
|
||||
}
|
||||
|
||||
unsigned path_idx = 1;
|
||||
return compare_deref_paths(a_path, b_path, &path_idx, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1327,6 +1327,234 @@ TEST_F(nir_copy_prop_vars_test, store_load_indirect_array_deref)
|
|||
EXPECT_EQ(first->src[1].ssa, second->src[1].ssa);
|
||||
}
|
||||
|
||||
TEST_F(nir_copy_prop_vars_test, restrict_ssbo_bindings)
|
||||
{
|
||||
glsl_struct_field field = glsl_struct_field();
|
||||
field.type = glsl_int_type();
|
||||
field.name = "x";
|
||||
const glsl_type *ifc_type =
|
||||
glsl_type::get_interface_instance(&field, 1,
|
||||
GLSL_INTERFACE_PACKING_STD430,
|
||||
false /* row_major */, "b");
|
||||
nir_variable *ssbo0 = create_var(nir_var_mem_ssbo, ifc_type, "ssbo0");
|
||||
nir_variable *ssbo1 = create_var(nir_var_mem_ssbo, ifc_type, "ssbo1");
|
||||
ssbo0->data.access = ssbo1->data.access = ACCESS_RESTRICT;
|
||||
nir_variable *out = create_var(nir_var_mem_ssbo, ifc_type, "out");
|
||||
out->data.access = ACCESS_RESTRICT;
|
||||
|
||||
nir_deref_instr *ssbo0_x =
|
||||
nir_build_deref_struct(b, nir_build_deref_var(b, ssbo0), 0);
|
||||
nir_store_deref(b, ssbo0_x, nir_imm_int(b, 20), 1);
|
||||
|
||||
nir_deref_instr *ssbo1_x =
|
||||
nir_build_deref_struct(b, nir_build_deref_var(b, ssbo1), 0);
|
||||
nir_store_deref(b, ssbo1_x, nir_imm_int(b, 30), 1);
|
||||
|
||||
/* Load ssbo0.x and store it in out.x. This load should be dropped */
|
||||
nir_deref_instr *out_x =
|
||||
nir_build_deref_struct(b, nir_build_deref_var(b, out), 0);
|
||||
nir_store_deref(b, out_x, nir_load_deref(b, ssbo0_x), 1);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
|
||||
bool progress = nir_opt_copy_prop_vars(b->shader);
|
||||
EXPECT_TRUE(progress);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 0);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
|
||||
/* Store to b0.x propagated to out. */
|
||||
nir_intrinsic_instr *first = get_intrinsic(nir_intrinsic_store_deref, 0);
|
||||
nir_intrinsic_instr *third = get_intrinsic(nir_intrinsic_store_deref, 2);
|
||||
ASSERT_TRUE(first->src[1].is_ssa);
|
||||
ASSERT_TRUE(third->src[1].is_ssa);
|
||||
EXPECT_EQ(first->src[1].ssa, third->src[1].ssa);
|
||||
}
|
||||
|
||||
TEST_F(nir_copy_prop_vars_test, aliasing_ssbo_bindings)
|
||||
{
|
||||
glsl_struct_field field = glsl_struct_field();
|
||||
field.type = glsl_int_type();
|
||||
field.name = "x";
|
||||
const glsl_type *ifc_type =
|
||||
glsl_type::get_interface_instance(&field, 1,
|
||||
GLSL_INTERFACE_PACKING_STD430,
|
||||
false /* row_major */, "b");
|
||||
nir_variable *ssbo0 = create_var(nir_var_mem_ssbo, ifc_type, "ssbo0");
|
||||
nir_variable *ssbo1 = create_var(nir_var_mem_ssbo, ifc_type, "ssbo1");
|
||||
nir_variable *out = create_var(nir_var_mem_ssbo, ifc_type, "out");
|
||||
out->data.access = ACCESS_RESTRICT;
|
||||
|
||||
nir_deref_instr *ssbo0_x =
|
||||
nir_build_deref_struct(b, nir_build_deref_var(b, ssbo0), 0);
|
||||
nir_store_deref(b, ssbo0_x, nir_imm_int(b, 20), 1);
|
||||
|
||||
nir_deref_instr *ssbo1_x =
|
||||
nir_build_deref_struct(b, nir_build_deref_var(b, ssbo1), 0);
|
||||
nir_store_deref(b, ssbo1_x, nir_imm_int(b, 30), 1);
|
||||
|
||||
/* Load ssbo0.x and store it in out.x. This load should not be dropped */
|
||||
nir_deref_instr *out_x =
|
||||
nir_build_deref_struct(b, nir_build_deref_var(b, out), 0);
|
||||
nir_store_deref(b, out_x, nir_load_deref(b, ssbo0_x), 1);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
|
||||
bool progress = nir_opt_copy_prop_vars(b->shader);
|
||||
EXPECT_FALSE(progress);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
}
|
||||
|
||||
TEST_F(nir_copy_prop_vars_test, ssbo_array_binding_indirect)
|
||||
{
|
||||
glsl_struct_field field = glsl_struct_field();
|
||||
field.type = glsl_int_type();
|
||||
field.name = "x";
|
||||
const glsl_type *ifc_type =
|
||||
glsl_type::get_interface_instance(&field, 1,
|
||||
GLSL_INTERFACE_PACKING_STD430,
|
||||
false /* row_major */, "b");
|
||||
const glsl_type *arr_ifc_type = glsl_type::get_array_instance(ifc_type, 2);
|
||||
nir_variable *ssbo_arr = create_var(nir_var_mem_ssbo, arr_ifc_type,
|
||||
"ssbo_arr");
|
||||
ssbo_arr->data.access = ACCESS_RESTRICT;
|
||||
nir_variable *out = create_var(nir_var_mem_ssbo, ifc_type, "out");
|
||||
out->data.access = ACCESS_RESTRICT;
|
||||
|
||||
nir_ssa_def *i = nir_load_local_invocation_index(b);
|
||||
|
||||
nir_deref_instr *ssbo_0 =
|
||||
nir_build_deref_array_imm(b, nir_build_deref_var(b, ssbo_arr), 0);
|
||||
nir_deref_instr *ssbo_0_x = nir_build_deref_struct(b, ssbo_0, 0);
|
||||
nir_store_deref(b, ssbo_0_x, nir_imm_int(b, 20), 1);
|
||||
|
||||
nir_deref_instr *ssbo_i =
|
||||
nir_build_deref_array(b, nir_build_deref_var(b, ssbo_arr),
|
||||
nir_load_local_invocation_index(b));
|
||||
nir_deref_instr *ssbo_i_x = nir_build_deref_struct(b, ssbo_i, 0);
|
||||
nir_store_deref(b, ssbo_i_x, nir_imm_int(b, 30), 1);
|
||||
|
||||
/* Load ssbo_arr[0].x and store it in out.x. This load should not be dropped */
|
||||
nir_deref_instr *out_x =
|
||||
nir_build_deref_struct(b, nir_build_deref_var(b, out), 0);
|
||||
nir_store_deref(b, out_x, nir_load_deref(b, ssbo_0_x), 1);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
|
||||
bool progress = nir_opt_copy_prop_vars(b->shader);
|
||||
EXPECT_FALSE(progress);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
}
|
||||
|
||||
TEST_F(nir_copy_prop_vars_test, restrict_ssbo_array_binding)
|
||||
{
|
||||
glsl_struct_field field = glsl_struct_field();
|
||||
field.type = glsl_int_type();
|
||||
field.name = "x";
|
||||
const glsl_type *ifc_type =
|
||||
glsl_type::get_interface_instance(&field, 1,
|
||||
GLSL_INTERFACE_PACKING_STD430,
|
||||
false /* row_major */, "b");
|
||||
const glsl_type *arr_ifc_type = glsl_type::get_array_instance(ifc_type, 2);
|
||||
nir_variable *ssbo_arr = create_var(nir_var_mem_ssbo, arr_ifc_type,
|
||||
"ssbo_arr");
|
||||
ssbo_arr->data.access = ACCESS_RESTRICT;
|
||||
nir_variable *out = create_var(nir_var_mem_ssbo, ifc_type, "out");
|
||||
out->data.access = ACCESS_RESTRICT;
|
||||
|
||||
nir_ssa_def *i = nir_load_local_invocation_index(b);
|
||||
|
||||
nir_deref_instr *ssbo_0 =
|
||||
nir_build_deref_array_imm(b, nir_build_deref_var(b, ssbo_arr), 0);
|
||||
nir_deref_instr *ssbo_0_x = nir_build_deref_struct(b, ssbo_0, 0);
|
||||
nir_store_deref(b, ssbo_0_x, nir_imm_int(b, 20), 1);
|
||||
|
||||
nir_deref_instr *ssbo_1 =
|
||||
nir_build_deref_array_imm(b, nir_build_deref_var(b, ssbo_arr), 1);
|
||||
nir_deref_instr *ssbo_1_x = nir_build_deref_struct(b, ssbo_1, 0);
|
||||
nir_store_deref(b, ssbo_1_x, nir_imm_int(b, 30), 1);
|
||||
|
||||
/* Load ssbo_arr[0].x and store it in out.x. This load should be dropped */
|
||||
nir_deref_instr *out_x =
|
||||
nir_build_deref_struct(b, nir_build_deref_var(b, out), 0);
|
||||
nir_store_deref(b, out_x, nir_load_deref(b, ssbo_0_x), 1);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
|
||||
bool progress = nir_opt_copy_prop_vars(b->shader);
|
||||
EXPECT_TRUE(progress);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 0);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
|
||||
/* Store to b0.x propagated to out. */
|
||||
nir_intrinsic_instr *first = get_intrinsic(nir_intrinsic_store_deref, 0);
|
||||
nir_intrinsic_instr *third = get_intrinsic(nir_intrinsic_store_deref, 2);
|
||||
ASSERT_TRUE(first->src[1].is_ssa);
|
||||
ASSERT_TRUE(third->src[1].is_ssa);
|
||||
EXPECT_EQ(first->src[1].ssa, third->src[1].ssa);
|
||||
}
|
||||
|
||||
TEST_F(nir_copy_prop_vars_test, aliasing_ssbo_array_binding)
|
||||
{
|
||||
glsl_struct_field field = glsl_struct_field();
|
||||
field.type = glsl_int_type();
|
||||
field.name = "x";
|
||||
const glsl_type *ifc_type =
|
||||
glsl_type::get_interface_instance(&field, 1,
|
||||
GLSL_INTERFACE_PACKING_STD430,
|
||||
false /* row_major */, "b");
|
||||
const glsl_type *arr_ifc_type = glsl_type::get_array_instance(ifc_type, 2);
|
||||
nir_variable *ssbo_arr = create_var(nir_var_mem_ssbo, arr_ifc_type,
|
||||
"ssbo_arr");
|
||||
nir_variable *out = create_var(nir_var_mem_ssbo, ifc_type, "out");
|
||||
out->data.access = ACCESS_RESTRICT;
|
||||
|
||||
nir_ssa_def *i = nir_load_local_invocation_index(b);
|
||||
|
||||
nir_deref_instr *ssbo_0 =
|
||||
nir_build_deref_array_imm(b, nir_build_deref_var(b, ssbo_arr), 0);
|
||||
nir_deref_instr *ssbo_0_x = nir_build_deref_struct(b, ssbo_0, 0);
|
||||
nir_store_deref(b, ssbo_0_x, nir_imm_int(b, 20), 1);
|
||||
|
||||
nir_deref_instr *ssbo_1 =
|
||||
nir_build_deref_array_imm(b, nir_build_deref_var(b, ssbo_arr), 1);
|
||||
nir_deref_instr *ssbo_1_x = nir_build_deref_struct(b, ssbo_1, 0);
|
||||
nir_store_deref(b, ssbo_1_x, nir_imm_int(b, 30), 1);
|
||||
|
||||
/* Load ssbo_arr[0].x and store it in out.x. This load should not be dropped */
|
||||
nir_deref_instr *out_x =
|
||||
nir_build_deref_struct(b, nir_build_deref_var(b, out), 0);
|
||||
nir_store_deref(b, out_x, nir_load_deref(b, ssbo_0_x), 1);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
|
||||
bool progress = nir_opt_copy_prop_vars(b->shader);
|
||||
EXPECT_FALSE(progress);
|
||||
|
||||
nir_validate_shader(b->shader, NULL);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
|
||||
ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3);
|
||||
}
|
||||
|
||||
TEST_F(nir_dead_write_vars_test, no_dead_writes_in_block)
|
||||
{
|
||||
nir_variable **v = create_many_int(nir_var_mem_global, "v", 2);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue