1 /*
2 * Copyright © 2019 Red Hat, Inc
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, sublicense,
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 next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * 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 NONINFRINGEMENT. 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
24 #include <gtest/gtest.h>
25
26 #include "nir.h"
27 #include "nir_builder.h"
28 #include "nir_serialize.h"
29
30 namespace {
31
32 class nir_serialize_test : public ::testing::TestWithParam<int> {
33 protected:
34 nir_serialize_test();
35 ~nir_serialize_test();
36
37 void serialize();
38 nir_alu_instr *get_last_alu(nir_shader *);
39 void ASSERT_SWIZZLE_EQ(nir_alu_instr *, nir_alu_instr *, unsigned count, unsigned src);
40
41 nir_builder *b, _b;
42 nir_shader *dup;
43 const nir_shader_compiler_options options;
44 };
45
nir_serialize_test()46 nir_serialize_test::nir_serialize_test()
47 : dup(NULL), options()
48 {
49 glsl_type_singleton_init_or_ref();
50
51 _b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, &options, "serialize test");
52 b = &_b;
53 }
54
~nir_serialize_test()55 nir_serialize_test::~nir_serialize_test()
56 {
57 if (HasFailure()) {
58 printf("\nShader from the failed test\n\n");
59 printf("original Shader:\n");
60 nir_print_shader(b->shader, stdout);
61 printf("serialized Shader:\n");
62 nir_print_shader(dup, stdout);
63 }
64
65 ralloc_free(b->shader);
66
67 glsl_type_singleton_decref();
68 }
69
70 void
serialize()71 nir_serialize_test::serialize() {
72 struct blob blob;
73 struct blob_reader reader;
74
75 blob_init(&blob);
76
77 nir_serialize(&blob, b->shader, false);
78 blob_reader_init(&reader, blob.data, blob.size);
79 nir_shader *cloned = nir_deserialize(b->shader, &options, &reader);
80 blob_finish(&blob);
81
82 dup = cloned;
83
84 nir_validate_shader(b->shader, "original");
85 nir_validate_shader(b->shader, "cloned");
86 }
87
88 nir_alu_instr *
get_last_alu(nir_shader * nir)89 nir_serialize_test::get_last_alu(nir_shader *nir)
90 {
91 nir_function_impl *impl = nir_shader_get_entrypoint(nir);
92 return nir_instr_as_alu(nir_block_last_instr(nir_impl_last_block(impl)));
93 }
94
95 void
ASSERT_SWIZZLE_EQ(nir_alu_instr * a,nir_alu_instr * b,unsigned c,unsigned s)96 nir_serialize_test::ASSERT_SWIZZLE_EQ(nir_alu_instr *a, nir_alu_instr *b, unsigned c, unsigned s)
97 {
98 ASSERT_EQ(memcmp(a->src[s].swizzle, b->src[s].swizzle, c), 0);
99 }
100
101 class nir_serialize_all_test : public nir_serialize_test {};
102 class nir_serialize_all_but_one_test : public nir_serialize_test {};
103
104 } // namespace
105
106 #if NIR_MAX_VEC_COMPONENTS == 16
107 #define COMPONENTS 2, 3, 4, 8, 16
108 #else
109 #define COMPONENTS 2, 3, 4
110 #endif
111
112
113 INSTANTIATE_TEST_CASE_P(
114 nir_serialize_all_test,
115 nir_serialize_all_test,
116 ::testing::Values(1, COMPONENTS)
117 );
118
119 INSTANTIATE_TEST_CASE_P(
120 nir_serialize_all_but_one_test,
121 nir_serialize_all_but_one_test,
122 ::testing::Values(COMPONENTS)
123 );
124
TEST_P(nir_serialize_all_test,alu_single_value_src_swizzle)125 TEST_P(nir_serialize_all_test, alu_single_value_src_swizzle)
126 {
127 nir_ssa_def *zero = nir_imm_zero(b, GetParam(), 32);
128 nir_ssa_def *fmax = nir_fmax(b, zero, zero);
129
130 nir_alu_instr *fmax_alu = nir_instr_as_alu(fmax->parent_instr);
131
132 memset(fmax_alu->src[0].swizzle, GetParam() - 1, NIR_MAX_VEC_COMPONENTS);
133 memset(fmax_alu->src[1].swizzle, GetParam() - 1, NIR_MAX_VEC_COMPONENTS);
134
135 serialize();
136
137 nir_alu_instr *fmax_alu_dup = get_last_alu(dup);
138
139 ASSERT_SWIZZLE_EQ(fmax_alu, fmax_alu_dup, GetParam(), 0);
140 ASSERT_SWIZZLE_EQ(fmax_alu, fmax_alu_dup, GetParam(), 1);
141 }
142
TEST_P(nir_serialize_all_test,alu_vec)143 TEST_P(nir_serialize_all_test, alu_vec)
144 {
145 nir_ssa_def *undef = nir_ssa_undef(b, GetParam(), 32);
146 nir_ssa_def *undefs[] = {
147 undef, undef, undef, undef,
148 undef, undef, undef, undef,
149 undef, undef, undef, undef,
150 undef, undef, undef, undef,
151 };
152
153 nir_ssa_def *vec = nir_vec(b, undefs, GetParam());
154 nir_alu_instr *vec_alu = nir_instr_as_alu(vec->parent_instr);
155 for (int i = 0; i < GetParam(); i++)
156 vec_alu->src[i].swizzle[0] = (GetParam() - 1) - i;
157
158 serialize();
159
160 nir_alu_instr *vec_alu_dup = get_last_alu(dup);
161
162 ASSERT_SWIZZLE_EQ(vec_alu, vec_alu_dup, 1, 0);
163 }
164
TEST_P(nir_serialize_all_test,alu_two_components_full_swizzle)165 TEST_P(nir_serialize_all_test, alu_two_components_full_swizzle)
166 {
167 nir_ssa_def *undef = nir_ssa_undef(b, 2, 32);
168 nir_ssa_def *fma = nir_ffma(b, undef, undef, undef);
169 nir_alu_instr *fma_alu = nir_instr_as_alu(fma->parent_instr);
170
171 fma->num_components = GetParam();
172 fma_alu->dest.write_mask = (1 << GetParam()) - 1;
173
174 memset(fma_alu->src[0].swizzle, 1, GetParam());
175 memset(fma_alu->src[1].swizzle, 1, GetParam());
176 memset(fma_alu->src[2].swizzle, 1, GetParam());
177
178 serialize();
179
180 nir_alu_instr *fma_alu_dup = get_last_alu(dup);
181
182 ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, GetParam(), 0);
183 ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, GetParam(), 1);
184 ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, GetParam(), 2);
185 }
186
TEST_P(nir_serialize_all_but_one_test,alu_two_components_reg_two_swizzle)187 TEST_P(nir_serialize_all_but_one_test, alu_two_components_reg_two_swizzle)
188 {
189 nir_ssa_def *undef = nir_ssa_undef(b, 2, 32);
190 nir_ssa_def *fma = nir_ffma(b, undef, undef, undef);
191 nir_alu_instr *fma_alu = nir_instr_as_alu(fma->parent_instr);
192
193 memset(fma_alu->src[0].swizzle, 1, GetParam());
194 memset(fma_alu->src[1].swizzle, 1, GetParam());
195 memset(fma_alu->src[2].swizzle, 1, GetParam());
196
197 ASSERT_TRUE(nir_convert_from_ssa(b->shader, false));
198
199 fma_alu = get_last_alu(b->shader);
200 ASSERT_FALSE(fma_alu->dest.dest.is_ssa);
201 fma_alu->dest.dest.reg.reg->num_components = GetParam();
202 fma_alu->dest.write_mask = 1 | (1 << (GetParam() - 1));
203
204 serialize();
205
206 nir_alu_instr *fma_alu_dup = get_last_alu(dup);
207
208 ASSERT_EQ(fma_alu->src[0].swizzle[0], fma_alu_dup->src[0].swizzle[0]);
209 ASSERT_EQ(fma_alu->src[0].swizzle[GetParam() - 1], fma_alu_dup->src[0].swizzle[GetParam() - 1]);
210 ASSERT_EQ(fma_alu->src[1].swizzle[0], fma_alu_dup->src[1].swizzle[0]);
211 ASSERT_EQ(fma_alu->src[1].swizzle[GetParam() - 1], fma_alu_dup->src[1].swizzle[GetParam() - 1]);
212 ASSERT_EQ(fma_alu->src[2].swizzle[0], fma_alu_dup->src[2].swizzle[0]);
213 ASSERT_EQ(fma_alu->src[2].swizzle[GetParam() - 1], fma_alu_dup->src[2].swizzle[GetParam() - 1]);
214 }
215
TEST_P(nir_serialize_all_but_one_test,alu_full_width_reg_two_swizzle)216 TEST_P(nir_serialize_all_but_one_test, alu_full_width_reg_two_swizzle)
217 {
218 nir_ssa_def *undef = nir_ssa_undef(b, GetParam(), 32);
219 nir_ssa_def *fma = nir_ffma(b, undef, undef, undef);
220 nir_alu_instr *fma_alu = nir_instr_as_alu(fma->parent_instr);
221
222 memset(fma_alu->src[0].swizzle, GetParam() - 1, GetParam());
223 memset(fma_alu->src[1].swizzle, GetParam() - 1, GetParam());
224 memset(fma_alu->src[2].swizzle, GetParam() - 1, GetParam());
225
226 ASSERT_TRUE(nir_convert_from_ssa(b->shader, false));
227
228 fma_alu = get_last_alu(b->shader);
229 ASSERT_FALSE(fma_alu->dest.dest.is_ssa);
230 fma_alu->dest.write_mask = 1 | (1 << (GetParam() - 1));
231
232 serialize();
233
234 nir_alu_instr *fma_alu_dup = get_last_alu(dup);
235
236 ASSERT_EQ(fma_alu->src[0].swizzle[0], fma_alu_dup->src[0].swizzle[0]);
237 ASSERT_EQ(fma_alu->src[0].swizzle[GetParam() - 1], fma_alu_dup->src[0].swizzle[GetParam() - 1]);
238 ASSERT_EQ(fma_alu->src[1].swizzle[0], fma_alu_dup->src[1].swizzle[0]);
239 ASSERT_EQ(fma_alu->src[1].swizzle[GetParam() - 1], fma_alu_dup->src[1].swizzle[GetParam() - 1]);
240 ASSERT_EQ(fma_alu->src[2].swizzle[0], fma_alu_dup->src[2].swizzle[0]);
241 ASSERT_EQ(fma_alu->src[2].swizzle[GetParam() - 1], fma_alu_dup->src[2].swizzle[GetParam() - 1]);
242 }
243
TEST_P(nir_serialize_all_but_one_test,alu_two_component_reg_full_src)244 TEST_P(nir_serialize_all_but_one_test, alu_two_component_reg_full_src)
245 {
246 nir_ssa_def *undef = nir_ssa_undef(b, GetParam(), 32);
247 nir_ssa_def *fma = nir_ffma(b, undef, undef, undef);
248 nir_alu_instr *fma_alu = nir_instr_as_alu(fma->parent_instr);
249
250 memset(fma_alu->src[0].swizzle, 1, GetParam());
251 memset(fma_alu->src[1].swizzle, 1, GetParam());
252 memset(fma_alu->src[2].swizzle, 1, GetParam());
253
254 ASSERT_TRUE(nir_convert_from_ssa(b->shader, false));
255
256 fma_alu = get_last_alu(b->shader);
257 ASSERT_FALSE(fma_alu->dest.dest.is_ssa);
258 fma_alu->dest.dest.reg.reg->num_components = 2;
259 fma_alu->dest.write_mask = 0x3;
260
261 serialize();
262
263 nir_alu_instr *fma_alu_dup = get_last_alu(dup);
264
265 ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, 2, 0);
266 ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, 2, 1);
267 ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, 2, 2);
268 }
269
TEST_P(nir_serialize_all_but_one_test,single_channel)270 TEST_P(nir_serialize_all_but_one_test, single_channel)
271 {
272 nir_ssa_def *zero = nir_ssa_undef(b, GetParam(), 32);
273 nir_ssa_def *vec = nir_channel(b, zero, GetParam() - 1);
274 nir_alu_instr *vec_alu = nir_instr_as_alu(vec->parent_instr);
275
276 serialize();
277
278 nir_alu_instr *vec_alu_dup = get_last_alu(dup);
279
280 ASSERT_SWIZZLE_EQ(vec_alu, vec_alu_dup, 1, 0);
281 }
282