Module: Mesa Branch: main Commit: 11282598e69602564960674ba378e577bdbff63d URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=11282598e69602564960674ba378e577bdbff63d
Author: Konstantin Seurer <konstantin.seu...@gmail.com> Date: Fri Jul 21 11:56:43 2023 +0200 radv: Add radv_nir_lower_hit_attrib_derefs_tests Tests hit attrib lowering for various variable/type configurations. Reviewed-by: Friedrich Vock <friedrich.v...@gmx.de> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24271> --- src/amd/vulkan/meson.build | 31 +++ .../radv_nir_lower_hit_attrib_derefs_tests.cpp | 236 +++++++++++++++++++++ 2 files changed, 267 insertions(+) diff --git a/src/amd/vulkan/meson.build b/src/amd/vulkan/meson.build index 36f664d35a9..27f3277785f 100644 --- a/src/amd/vulkan/meson.build +++ b/src/amd/vulkan/meson.build @@ -277,3 +277,34 @@ _dev_icd = custom_target( ) devenv.append('VK_ICD_FILENAMES', _dev_icd.full_path()) + +if with_tests + test( + 'radv_tests', + executable( + 'radv_tests', + files( + 'nir/radv_nir_lower_hit_attrib_derefs.c', + 'tests/radv_nir_lower_hit_attrib_derefs_tests.cpp', + ), + cpp_args : [cpp_msvc_compat_args], + gnu_symbol_visibility : 'hidden', + include_directories : [ + inc_include, + inc_src, + inc_mapi, + inc_mesa, + inc_gallium, + inc_gallium_aux, + inc_amd, + inc_amd_common, + inc_compiler, + inc_util, + include_directories('.'), + ], + dependencies : [dep_thread, idep_gtest, idep_nir, idep_mesautil], + ), + suite : ['compiler', 'nir'], + protocol : 'gtest', + ) +endif diff --git a/src/amd/vulkan/tests/radv_nir_lower_hit_attrib_derefs_tests.cpp b/src/amd/vulkan/tests/radv_nir_lower_hit_attrib_derefs_tests.cpp new file mode 100644 index 00000000000..a974cab56b6 --- /dev/null +++ b/src/amd/vulkan/tests/radv_nir_lower_hit_attrib_derefs_tests.cpp @@ -0,0 +1,236 @@ +/* + * Copyright © 2023 Valve Corporation + * SPDX-License-Identifier: MIT + */ + +#include "nir/radv_nir.h" +#include "tests/nir_test.h" +#include "radv_constants.h" + +class radv_nir_lower_hit_attrib_derefs_test : public nir_test { +protected: + radv_nir_lower_hit_attrib_derefs_test(): nir_test("radv_nir_lower_hit_attrib_derefs_test") + { + b->shader->info.stage = MESA_SHADER_INTERSECTION; + } + + void validate(uint32_t used_bits[RADV_MAX_HIT_ATTRIB_DWORDS], uint32_t used_dwords, bool constant_fold); +}; + +void +radv_nir_lower_hit_attrib_derefs_test::validate(uint32_t used_bits[RADV_MAX_HIT_ATTRIB_DWORDS], uint32_t used_dwords, + bool constant_fold) +{ + EXPECT_TRUE(radv_nir_lower_hit_attrib_derefs(b->shader)); + nir_validate_shader(b->shader, "After radv_nir_lower_hit_attrib_derefs"); + + srand(918763498); + + uint32_t values[RADV_MAX_HIT_ATTRIB_DWORDS]; + for (uint32_t i = 0; i < ARRAY_SIZE(values); i++) + values[i] = ((uint32_t)rand() ^ ((uint32_t)rand() << 1)) & used_bits[i]; + + nir_function_impl *impl = nir_shader_get_entrypoint(b->shader); + + if (constant_fold) { + nir_foreach_block (block, impl) { + nir_foreach_instr_safe (instr, block) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + if (intr->intrinsic != nir_intrinsic_load_hit_attrib_amd) + continue; + + b->cursor = nir_after_instr(instr); + nir_def *value = nir_imm_int(b, values[nir_intrinsic_base(intr)]); + nir_def_rewrite_uses(&intr->def, value); + } + } + NIR_PASS(_, b->shader, nir_opt_constant_folding); + } + + NIR_PASS(_, b->shader, nir_opt_dce); + + uint32_t stored_dwords = 0; + nir_foreach_block (block, impl) { + nir_foreach_instr_safe (instr, block) { + /* Make sure that all ray_hit_attrib variables have been lowered. */ + if (instr->type == nir_instr_type_deref) { + EXPECT_FALSE(nir_deref_mode_is(nir_instr_as_deref(instr), nir_var_ray_hit_attrib)); + } + + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + if (intr->intrinsic != nir_intrinsic_store_hit_attrib_amd) + continue; + + uint32_t base = nir_intrinsic_base(intr); + EXPECT_LT(base, RADV_MAX_HIT_ATTRIB_DWORDS); + stored_dwords |= BITFIELD_BIT(base); + + bool is_const = nir_src_is_const(intr->src[0]); + EXPECT_TRUE(is_const || !constant_fold); + if (!is_const) + continue; + + uint32_t src = nir_src_as_uint(intr->src[0]); + EXPECT_EQ(src, values[base] & used_bits[base]); + } + } + + EXPECT_EQ(stored_dwords, used_dwords); +} + +TEST_F(radv_nir_lower_hit_attrib_derefs_test, types) +{ + nir_variable *vec3_var = nir_variable_create(b->shader, nir_var_ray_hit_attrib, glsl_vec_type(3), "vec3"); + nir_variable *uint64_var = nir_variable_create(b->shader, nir_var_ray_hit_attrib, glsl_uint64_t_type(), "uint64_t"); + nir_variable *uint16_var = nir_variable_create(b->shader, nir_var_ray_hit_attrib, glsl_uint16_t_type(), "uint16_t"); + nir_variable *uint8_var = nir_variable_create(b->shader, nir_var_ray_hit_attrib, glsl_uint8_t_type(), "uint8_t"); + nir_variable *bool_var = nir_variable_create(b->shader, nir_var_ray_hit_attrib, glsl_bool_type(), "bool"); + + nir_variable *vars[5] = { + vec3_var, uint64_var, uint16_var, uint8_var, bool_var, + }; + + for (uint32_t i = 0; i < ARRAY_SIZE(vars); i++) { + nir_def *load = nir_load_var(b, vars[i]); + nir_store_var(b, vars[i], load, (1 << load->num_components) - 1); + } + + uint32_t masks[RADV_MAX_HIT_ATTRIB_DWORDS] = { + /* vec3 */ + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF, + /* padding */ + 0, + /* uint64_t */ + 0xFFFFFFFF, + 0xFFFFFFFF, + /* uint16_t uint8_t */ + 0xFFFFFFFF, + /* bool */ + 1, + }; + validate(masks, 0b11110111, true); +} + +TEST_F(radv_nir_lower_hit_attrib_derefs_test, array) +{ + nir_variable *array_var = + nir_variable_create(b->shader, nir_var_ray_hit_attrib, + glsl_array_type(glsl_uint_type(), RADV_MAX_HIT_ATTRIB_DWORDS, 0), "uint32_t[]"); + + for (uint32_t i = 0; i < RADV_MAX_HIT_ATTRIB_DWORDS; i++) { + nir_def *load = nir_load_array_var_imm(b, array_var, i); + nir_store_array_var_imm(b, array_var, i, load, 0x1); + } + + uint32_t masks[RADV_MAX_HIT_ATTRIB_DWORDS] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + }; + validate(masks, 0xFF, true); +} + +TEST_F(radv_nir_lower_hit_attrib_derefs_test, dynamic_array) +{ + nir_variable *array_var = + nir_variable_create(b->shader, nir_var_ray_hit_attrib, + glsl_array_type(glsl_uint_type(), RADV_MAX_HIT_ATTRIB_DWORDS, 0), "uint32_t[]"); + + nir_def *index = nir_load_local_invocation_index(b); + nir_def *load = nir_load_array_var(b, array_var, index); + nir_store_array_var(b, array_var, index, load, 0x1); + + uint32_t masks[RADV_MAX_HIT_ATTRIB_DWORDS] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + }; + validate(masks, 0xFF, false); +} + +TEST_F(radv_nir_lower_hit_attrib_derefs_test, struct) +{ + glsl_struct_field fields[5] = { + glsl_struct_field(glsl_vec_type(3), "vec3"), glsl_struct_field(glsl_uint64_t_type(), "uint64_t"), + glsl_struct_field(glsl_uint16_t_type(), "uint16_t"), glsl_struct_field(glsl_uint8_t_type(), "uint8_t"), + glsl_struct_field(glsl_bool_type(), "bool"), + }; + + const glsl_type *var_type = glsl_struct_type(fields, ARRAY_SIZE(fields), "hit_attrib_struct", false); + nir_variable *struct_var = nir_variable_create(b->shader, nir_var_ray_hit_attrib, var_type, "hit_attrib_struct"); + + nir_deref_instr *var_deref = nir_build_deref_var(b, struct_var); + + for (uint32_t i = 0; i < ARRAY_SIZE(fields); i++) { + nir_deref_instr *member_deref = nir_build_deref_struct(b, var_deref, i); + nir_def *load = nir_load_deref(b, member_deref); + nir_store_deref(b, member_deref, load, (1 << load->num_components) - 1); + } + + uint32_t masks[RADV_MAX_HIT_ATTRIB_DWORDS] = { + /* vec3 */ + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF, + /* padding */ + 0, + /* uint64_t */ + 0xFFFFFFFF, + 0xFFFFFFFF, + /* uint16_t uint8_t */ + 0xFFFFFFFF, + /* bool */ + 1, + }; + validate(masks, 0b11110111, true); +} + +TEST_F(radv_nir_lower_hit_attrib_derefs_test, array_inside_struct) +{ + glsl_struct_field field = + glsl_struct_field(glsl_array_type(glsl_uint_type(), RADV_MAX_HIT_ATTRIB_DWORDS, 0), "array"); + + const glsl_type *var_type = glsl_struct_type(&field, 1, "hit_attrib_struct", false); + nir_variable *struct_var = nir_variable_create(b->shader, nir_var_ray_hit_attrib, var_type, "hit_attrib_struct"); + + nir_deref_instr *var_deref = nir_build_deref_var(b, struct_var); + nir_deref_instr *member_deref = nir_build_deref_struct(b, var_deref, 0); + + for (uint32_t i = 0; i < RADV_MAX_HIT_ATTRIB_DWORDS; i++) { + nir_deref_instr *element_deref = nir_build_deref_array_imm(b, member_deref, i); + nir_def *load = nir_load_deref(b, element_deref); + nir_store_deref(b, element_deref, load, (1 << load->num_components) - 1); + } + + uint32_t masks[RADV_MAX_HIT_ATTRIB_DWORDS] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + }; + validate(masks, 0xFF, true); +} + +TEST_F(radv_nir_lower_hit_attrib_derefs_test, struct_inside_array) +{ + glsl_struct_field field = glsl_struct_field(glsl_uint_type(), "array"); + const glsl_type *struct_type = glsl_struct_type(&field, 1, "hit_attrib_struct", false); + nir_variable *array_var = + nir_variable_create(b->shader, nir_var_ray_hit_attrib, + glsl_array_type(struct_type, RADV_MAX_HIT_ATTRIB_DWORDS, 0), "hit_attrib_struct[]"); + + nir_deref_instr *var_deref = nir_build_deref_var(b, array_var); + for (uint32_t i = 0; i < RADV_MAX_HIT_ATTRIB_DWORDS; i++) { + nir_deref_instr *element_deref = nir_build_deref_array_imm(b, var_deref, i); + nir_deref_instr *member_deref = nir_build_deref_struct(b, element_deref, 0); + + nir_def *load = nir_load_deref(b, member_deref); + nir_store_deref(b, member_deref, load, (1 << load->num_components) - 1); + } + + uint32_t masks[RADV_MAX_HIT_ATTRIB_DWORDS] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + }; + validate(masks, 0xFF, true); +}