1 /*
2 * Copyright (c) 2020 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Christian Gmeiner <[email protected]>
25 */
26
27 #include <gtest/gtest.h>
28
29 #include "nir.h"
30 #include "nir_builder.h"
31
32 extern "C" {
33 /* we really do not want to include etnaviv_nir.h as it makes it
34 * harder to get this test compiling. as we are only working with
35 * nir we do not need any etnaviv specifc stuff here. */
36
37 extern bool
38 etna_nir_lower_ubo_to_uniform(nir_shader *shader);
39 }
40
41 class nir_lower_ubo_test : public ::testing::Test {
42 protected:
43 nir_lower_ubo_test();
44 ~nir_lower_ubo_test();
45
46 nir_intrinsic_instr *intrinsic(nir_intrinsic_op op);
47 unsigned count_intrinsic(nir_intrinsic_op op);
48
49 nir_builder b;
50 };
51
nir_lower_ubo_test()52 nir_lower_ubo_test::nir_lower_ubo_test()
53 {
54 glsl_type_singleton_init_or_ref();
55
56 static const nir_shader_compiler_options options = { };
57 b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, &options, "ubo lowering tests");
58 }
59
~nir_lower_ubo_test()60 nir_lower_ubo_test::~nir_lower_ubo_test()
61 {
62 if (HasFailure()) {
63 printf("\nShader from the failed test:\n\n");
64 nir_print_shader(b.shader, stdout);
65 }
66
67 ralloc_free(b.shader);
68
69 glsl_type_singleton_decref();
70 }
71
72 nir_intrinsic_instr *
intrinsic(nir_intrinsic_op op)73 nir_lower_ubo_test::intrinsic(nir_intrinsic_op op)
74 {
75 nir_foreach_block(block, b.impl) {
76 nir_foreach_instr(instr, block) {
77 if (instr->type != nir_instr_type_intrinsic)
78 continue;
79
80 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
81 if (intr->intrinsic == op)
82 return intr;
83 }
84 }
85 return NULL;
86 }
87
88 unsigned
count_intrinsic(nir_intrinsic_op op)89 nir_lower_ubo_test::count_intrinsic(nir_intrinsic_op op)
90 {
91 unsigned count = 0;
92
93 nir_foreach_block(block, b.impl) {
94 nir_foreach_instr(instr, block) {
95 if (instr->type != nir_instr_type_intrinsic)
96 continue;
97
98 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
99 if (intr->intrinsic == op)
100 count++;
101 }
102 }
103 return count;
104 }
105
TEST_F(nir_lower_ubo_test,nothing_to_lower)106 TEST_F(nir_lower_ubo_test, nothing_to_lower)
107 {
108 nir_def *offset = nir_imm_int(&b, 4);
109
110 nir_load_uniform(&b, 1, 32, offset);
111
112 nir_validate_shader(b.shader, NULL);
113
114 ASSERT_FALSE(etna_nir_lower_ubo_to_uniform(b.shader));
115 nir_validate_shader(b.shader, NULL);
116
117 ASSERT_EQ(count_intrinsic(nir_intrinsic_load_ubo), 0);
118 ASSERT_EQ(count_intrinsic(nir_intrinsic_load_uniform), 1);
119 }
120
TEST_F(nir_lower_ubo_test,basic)121 TEST_F(nir_lower_ubo_test, basic)
122 {
123 nir_def *offset = nir_imm_int(&b, 4);
124 nir_load_uniform(&b, 1, 32, offset);
125
126 nir_lower_uniforms_to_ubo(b.shader, false, false);
127 nir_opt_constant_folding(b.shader);
128
129 ASSERT_TRUE(etna_nir_lower_ubo_to_uniform(b.shader));
130 nir_validate_shader(b.shader, NULL);
131 nir_opt_constant_folding(b.shader);
132
133 nir_intrinsic_instr *load_uniform = intrinsic(nir_intrinsic_load_uniform);
134 ASSERT_EQ(nir_src_as_uint(load_uniform->src[0]), 4);
135 ASSERT_EQ(intrinsic(nir_intrinsic_load_ubo), nullptr);
136 }
137
TEST_F(nir_lower_ubo_test,index_not_null)138 TEST_F(nir_lower_ubo_test, index_not_null)
139 {
140 nir_def *index = nir_imm_int(&b, 1);
141 nir_def *offset = nir_imm_int(&b, 4);
142
143 nir_load_ubo(&b, 1, 32, index, offset, .align_mul = 16, .align_offset = 0, .range_base = 0, .range = 8);
144
145 nir_validate_shader(b.shader, NULL);
146
147 ASSERT_FALSE(etna_nir_lower_ubo_to_uniform(b.shader));
148 ASSERT_EQ(count_intrinsic(nir_intrinsic_load_ubo), 1);
149 ASSERT_EQ(count_intrinsic(nir_intrinsic_load_uniform), 0);
150 }
151
TEST_F(nir_lower_ubo_test,indirect_index)152 TEST_F(nir_lower_ubo_test, indirect_index)
153 {
154 nir_def *one = nir_imm_int(&b, 1);
155 nir_def *index = nir_fadd(&b, one, one);
156 nir_def *offset = nir_imm_int(&b, 4);
157
158 nir_load_ubo(&b, 1, 32, index, offset, .align_mul = 16, .align_offset = 0, .range_base = 0, .range = 8);
159
160 nir_validate_shader(b.shader, NULL);
161
162 ASSERT_FALSE(etna_nir_lower_ubo_to_uniform(b.shader));
163 nir_validate_shader(b.shader, NULL);
164
165 ASSERT_EQ(count_intrinsic(nir_intrinsic_load_ubo), 1);
166 ASSERT_EQ(count_intrinsic(nir_intrinsic_load_uniform), 0);
167 }
168
TEST_F(nir_lower_ubo_test,indirect_offset)169 TEST_F(nir_lower_ubo_test, indirect_offset)
170 {
171 nir_def *one = nir_imm_int(&b, 1);
172 nir_def *index = nir_imm_int(&b, 0);
173 nir_def *offset = nir_fadd(&b, one, one);
174
175 nir_load_ubo(&b, 1, 32, index, offset, .align_mul = 16, .align_offset = 0, .range_base = 0, .range = 8);
176
177 nir_validate_shader(b.shader, NULL);
178
179 ASSERT_FALSE(etna_nir_lower_ubo_to_uniform(b.shader));
180 nir_validate_shader(b.shader, NULL);
181
182 ASSERT_EQ(count_intrinsic(nir_intrinsic_load_ubo), 1);
183 ASSERT_EQ(count_intrinsic(nir_intrinsic_load_uniform), 0);
184 }
185