From 1837135f7ca7ab80df215c4b1364c817fb8c2e84 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Thu, 24 Dec 2020 13:11:26 +0100 Subject: etnaviv: nir: add ubo lowering pass Adds a pass to lower the load_ubo intrinsics for block 0 back to load_uniform intrinsic. Signed-off-by: Christian Gmeiner Part-of: --- src/gallium/drivers/etnaviv/Makefile.sources | 1 + src/gallium/drivers/etnaviv/etnaviv_nir.h | 3 + .../etnaviv/etnaviv_nir_lower_ubo_to_uniform.c | 79 ++++++++++ src/gallium/drivers/etnaviv/meson.build | 17 +++ .../drivers/etnaviv/tests/lower_ubo_tests.cpp | 166 +++++++++++++++++++++ 5 files changed, 266 insertions(+) create mode 100644 src/gallium/drivers/etnaviv/etnaviv_nir_lower_ubo_to_uniform.c create mode 100644 src/gallium/drivers/etnaviv/tests/lower_ubo_tests.cpp diff --git a/src/gallium/drivers/etnaviv/Makefile.sources b/src/gallium/drivers/etnaviv/Makefile.sources index 3fc86072c6f..2fc3150cfcd 100644 --- a/src/gallium/drivers/etnaviv/Makefile.sources +++ b/src/gallium/drivers/etnaviv/Makefile.sources @@ -39,6 +39,7 @@ C_SOURCES := \ etnaviv_format.c \ etnaviv_format.h \ etnaviv_internal.h \ + etnaviv_nir_lower_ubo_to_uniform.c \ etnaviv_nir.c \ etnaviv_nir.h \ etnaviv_perfmon.c \ diff --git a/src/gallium/drivers/etnaviv/etnaviv_nir.h b/src/gallium/drivers/etnaviv/etnaviv_nir.h index 44258a8711a..bf7bba2e6a5 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_nir.h +++ b/src/gallium/drivers/etnaviv/etnaviv_nir.h @@ -34,4 +34,7 @@ etna_lower_io(nir_shader *shader, struct etna_shader_variant *v); void etna_lower_alu(nir_shader *shader, bool has_new_transcendentals); +bool +etna_nir_lower_ubo_to_uniform(nir_shader *shader); + #endif diff --git a/src/gallium/drivers/etnaviv/etnaviv_nir_lower_ubo_to_uniform.c b/src/gallium/drivers/etnaviv/etnaviv_nir_lower_ubo_to_uniform.c new file mode 100644 index 00000000000..3b7db740240 --- /dev/null +++ b/src/gallium/drivers/etnaviv/etnaviv_nir_lower_ubo_to_uniform.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020 Etnaviv Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Christian Gmeiner + */ + +#include "etnaviv_nir.h" + +/* + * Pass to lower the load_ubo intrinsics for block 0 back to load_uniform intrinsics. + */ + +static bool +is_const_ubo(const nir_instr *instr, const void *_data) +{ + if (instr->type != nir_instr_type_intrinsic) + return false; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + if (intr->intrinsic != nir_intrinsic_load_ubo) + return false; + + if (!nir_src_is_const(intr->src[0]) || !nir_src_is_const(intr->src[1])) + return false; + + const uint32_t block = nir_src_as_uint(intr->src[0]); + if (block > 0) + return false; + + return true; +} + +static nir_ssa_def * +lower_ubo_to_uniform(nir_builder *b, nir_instr *instr, void *_data) +{ + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + b->cursor = nir_before_instr(instr); + + nir_ssa_def *ubo_offset = nir_ssa_for_src(b, intr->src[1], 1); + nir_ssa_def *uniform = + nir_load_uniform(b, intr->num_components, intr->dest.ssa.bit_size, ubo_offset, + .base = nir_intrinsic_range_base(intr) / 16, + .range = nir_intrinsic_range(intr) / 16, + .dest_type = nir_type_float32); + + nir_ssa_def_rewrite_uses(&intr->dest.ssa, nir_src_for_ssa(uniform)); + + return uniform; +} + +bool +etna_nir_lower_ubo_to_uniform(nir_shader *shader) +{ + return nir_shader_lower_instructions(shader, + is_const_ubo, + lower_ubo_to_uniform, + NULL); + +} diff --git a/src/gallium/drivers/etnaviv/meson.build b/src/gallium/drivers/etnaviv/meson.build index 94c64914570..f8dcba887f0 100644 --- a/src/gallium/drivers/etnaviv/meson.build +++ b/src/gallium/drivers/etnaviv/meson.build @@ -58,6 +58,7 @@ files_etnaviv = files( 'etnaviv_format.c', 'etnaviv_format.h', 'etnaviv_internal.h', + 'etnaviv_nir_lower_ubo_to_uniform.c', 'etnaviv_nir.c', 'etnaviv_nir.h', 'etnaviv_perfmon.c', @@ -130,3 +131,19 @@ driver_etnaviv = declare_dependency( link_with : [libetnaviv, libetnavivdrm], dependencies : idep_nir, ) + +if with_tests + test( + 'lower_ubo', + executable( + 'nir_lower_ubo_test', + files('tests/lower_ubo_tests.cpp'), + cpp_args : [cpp_msvc_compat_args], + gnu_symbol_visibility : 'hidden', + include_directories : [inc_include, inc_src, inc_gallium], + link_with : [libetnaviv], + dependencies : [idep_gtest, idep_nir], + ), + suite : ['compiler', 'etnaviv'], + ) +endif diff --git a/src/gallium/drivers/etnaviv/tests/lower_ubo_tests.cpp b/src/gallium/drivers/etnaviv/tests/lower_ubo_tests.cpp new file mode 100644 index 00000000000..4132b22eaad --- /dev/null +++ b/src/gallium/drivers/etnaviv/tests/lower_ubo_tests.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2020 Etnaviv Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Christian Gmeiner + */ + +#include + +#include "nir.h" +#include "nir_builder.h" + +extern "C" { + /* we really do not want to include etnaviv_nir.h as it makes it + * harder to get this test compiling. as we are only working with + * nir we do not need any etnaviv specifc stuff here. */ + + extern bool + etna_nir_lower_ubo_to_uniform(nir_shader *shader); +} + +class nir_lower_ubo_test : public ::testing::Test { +protected: + nir_lower_ubo_test(); + ~nir_lower_ubo_test(); + + unsigned count_intrinsic(nir_intrinsic_op op); + + nir_builder b; +}; + +nir_lower_ubo_test::nir_lower_ubo_test() +{ + glsl_type_singleton_init_or_ref(); + + static const nir_shader_compiler_options options = { }; + b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, &options, "ubo lowering tests"); +} + +nir_lower_ubo_test::~nir_lower_ubo_test() +{ + if (HasFailure()) { + printf("\nShader from the failed test:\n\n"); + nir_print_shader(b.shader, stdout); + } + + ralloc_free(b.shader); + + glsl_type_singleton_decref(); +} + +unsigned +nir_lower_ubo_test::count_intrinsic(nir_intrinsic_op op) +{ + unsigned count = 0; + + nir_foreach_block(block, b.impl) { + nir_foreach_instr(instr, block) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + if (intr->intrinsic == op) + count++; + } + } + return count; +} + +TEST_F(nir_lower_ubo_test, nothing_to_lower) +{ + nir_ssa_def *offset = nir_imm_int(&b, 4); + + nir_load_uniform(&b, 1, 32, offset); + + nir_validate_shader(b.shader, NULL); + + ASSERT_FALSE(etna_nir_lower_ubo_to_uniform(b.shader)); + nir_validate_shader(b.shader, NULL); + + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_ubo), 0); + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_uniform), 1); +} + +TEST_F(nir_lower_ubo_test, basic) +{ + nir_ssa_def *index = nir_imm_int(&b, 0); + nir_ssa_def *offset = nir_imm_int(&b, 4); + + nir_load_ubo(&b, 1, 32, index, offset, .align_mul = 16, .align_offset = 0, .range_base = 0, .range = 8); + + nir_validate_shader(b.shader, NULL); + + ASSERT_TRUE(etna_nir_lower_ubo_to_uniform(b.shader)); + nir_validate_shader(b.shader, NULL); + + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_ubo), 0); + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_uniform), 1); +} + +TEST_F(nir_lower_ubo_test, index_not_null) +{ + nir_ssa_def *index = nir_imm_int(&b, 1); + nir_ssa_def *offset = nir_imm_int(&b, 4); + + nir_load_ubo(&b, 1, 32, index, offset, .align_mul = 16, .align_offset = 0, .range_base = 0, .range = 8); + + nir_validate_shader(b.shader, NULL); + + ASSERT_FALSE(etna_nir_lower_ubo_to_uniform(b.shader)); + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_ubo), 1); + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_uniform), 0); +} + +TEST_F(nir_lower_ubo_test, indirect_index) +{ + nir_ssa_def *one = nir_imm_int(&b, 1); + nir_ssa_def *index = nir_fadd(&b, one, one); + nir_ssa_def *offset = nir_imm_int(&b, 4); + + nir_load_ubo(&b, 1, 32, index, offset, .align_mul = 16, .align_offset = 0, .range_base = 0, .range = 8); + + nir_validate_shader(b.shader, NULL); + + ASSERT_FALSE(etna_nir_lower_ubo_to_uniform(b.shader)); + nir_validate_shader(b.shader, NULL); + + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_ubo), 1); + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_uniform), 0); +} + +TEST_F(nir_lower_ubo_test, indirect_offset) +{ + nir_ssa_def *one = nir_imm_int(&b, 1); + nir_ssa_def *index = nir_imm_int(&b, 0); + nir_ssa_def *offset = nir_fadd(&b, one, one); + + nir_load_ubo(&b, 1, 32, index, offset, .align_mul = 16, .align_offset = 0, .range_base = 0, .range = 8); + + nir_validate_shader(b.shader, NULL); + + ASSERT_FALSE(etna_nir_lower_ubo_to_uniform(b.shader)); + nir_validate_shader(b.shader, NULL); + + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_ubo), 1); + ASSERT_EQ(count_intrinsic(nir_intrinsic_load_uniform), 0); +} -- cgit v1.2.3