1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2019 Red Hat, Inc
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <gtest/gtest.h>
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "nir.h"
27bf215546Sopenharmony_ci#include "nir_builder.h"
28bf215546Sopenharmony_ci#include "nir_serialize.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_cinamespace {
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ciclass nir_serialize_test : public ::testing::TestWithParam<int> {
33bf215546Sopenharmony_ciprotected:
34bf215546Sopenharmony_ci   nir_serialize_test();
35bf215546Sopenharmony_ci   ~nir_serialize_test();
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci   void serialize();
38bf215546Sopenharmony_ci   nir_alu_instr *get_last_alu(nir_shader *);
39bf215546Sopenharmony_ci   void ASSERT_SWIZZLE_EQ(nir_alu_instr *, nir_alu_instr *, unsigned count, unsigned src);
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci   nir_builder *b, _b;
42bf215546Sopenharmony_ci   nir_shader *dup;
43bf215546Sopenharmony_ci   const nir_shader_compiler_options options;
44bf215546Sopenharmony_ci};
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_cinir_serialize_test::nir_serialize_test()
47bf215546Sopenharmony_ci:  dup(NULL), options()
48bf215546Sopenharmony_ci{
49bf215546Sopenharmony_ci   glsl_type_singleton_init_or_ref();
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   _b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, &options, "serialize test");
52bf215546Sopenharmony_ci   b = &_b;
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_cinir_serialize_test::~nir_serialize_test()
56bf215546Sopenharmony_ci{
57bf215546Sopenharmony_ci   if (HasFailure()) {
58bf215546Sopenharmony_ci      printf("\nShader from the failed test\n\n");
59bf215546Sopenharmony_ci      printf("original Shader:\n");
60bf215546Sopenharmony_ci      nir_print_shader(b->shader, stdout);
61bf215546Sopenharmony_ci      printf("serialized Shader:\n");
62bf215546Sopenharmony_ci      nir_print_shader(dup, stdout);
63bf215546Sopenharmony_ci   }
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   ralloc_free(b->shader);
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   glsl_type_singleton_decref();
68bf215546Sopenharmony_ci}
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_civoid
71bf215546Sopenharmony_cinir_serialize_test::serialize() {
72bf215546Sopenharmony_ci   struct blob blob;
73bf215546Sopenharmony_ci   struct blob_reader reader;
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   blob_init(&blob);
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci   nir_serialize(&blob, b->shader, false);
78bf215546Sopenharmony_ci   blob_reader_init(&reader, blob.data, blob.size);
79bf215546Sopenharmony_ci   nir_shader *cloned = nir_deserialize(b->shader, &options, &reader);
80bf215546Sopenharmony_ci   blob_finish(&blob);
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   dup = cloned;
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   nir_validate_shader(b->shader, "original");
85bf215546Sopenharmony_ci   nir_validate_shader(b->shader, "cloned");
86bf215546Sopenharmony_ci}
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_cinir_alu_instr *
89bf215546Sopenharmony_cinir_serialize_test::get_last_alu(nir_shader *nir)
90bf215546Sopenharmony_ci{
91bf215546Sopenharmony_ci   nir_function_impl *impl = nir_shader_get_entrypoint(nir);
92bf215546Sopenharmony_ci   return nir_instr_as_alu(nir_block_last_instr(nir_impl_last_block(impl)));
93bf215546Sopenharmony_ci}
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_civoid
96bf215546Sopenharmony_cinir_serialize_test::ASSERT_SWIZZLE_EQ(nir_alu_instr *a, nir_alu_instr *b, unsigned c, unsigned s)
97bf215546Sopenharmony_ci{
98bf215546Sopenharmony_ci   ASSERT_EQ(memcmp(a->src[s].swizzle, b->src[s].swizzle, c), 0);
99bf215546Sopenharmony_ci}
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ciclass nir_serialize_all_test : public nir_serialize_test {};
102bf215546Sopenharmony_ciclass nir_serialize_all_but_one_test : public nir_serialize_test {};
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci} // namespace
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci#if NIR_MAX_VEC_COMPONENTS == 16
107bf215546Sopenharmony_ci#define COMPONENTS 2, 3, 4, 8, 16
108bf215546Sopenharmony_ci#else
109bf215546Sopenharmony_ci#define COMPONENTS 2, 3, 4
110bf215546Sopenharmony_ci#endif
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ciINSTANTIATE_TEST_CASE_P(
114bf215546Sopenharmony_ci   nir_serialize_all_test,
115bf215546Sopenharmony_ci   nir_serialize_all_test,
116bf215546Sopenharmony_ci   ::testing::Values(1, COMPONENTS)
117bf215546Sopenharmony_ci);
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ciINSTANTIATE_TEST_CASE_P(
120bf215546Sopenharmony_ci   nir_serialize_all_but_one_test,
121bf215546Sopenharmony_ci   nir_serialize_all_but_one_test,
122bf215546Sopenharmony_ci   ::testing::Values(COMPONENTS)
123bf215546Sopenharmony_ci);
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ciTEST_P(nir_serialize_all_test, alu_single_value_src_swizzle)
126bf215546Sopenharmony_ci{
127bf215546Sopenharmony_ci   nir_ssa_def *zero = nir_imm_zero(b, GetParam(), 32);
128bf215546Sopenharmony_ci   nir_ssa_def *fmax = nir_fmax(b, zero, zero);
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   nir_alu_instr *fmax_alu = nir_instr_as_alu(fmax->parent_instr);
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   memset(fmax_alu->src[0].swizzle, GetParam() - 1, NIR_MAX_VEC_COMPONENTS);
133bf215546Sopenharmony_ci   memset(fmax_alu->src[1].swizzle, GetParam() - 1, NIR_MAX_VEC_COMPONENTS);
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   serialize();
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci   nir_alu_instr *fmax_alu_dup = get_last_alu(dup);
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(fmax_alu, fmax_alu_dup, GetParam(), 0);
140bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(fmax_alu, fmax_alu_dup, GetParam(), 1);
141bf215546Sopenharmony_ci}
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ciTEST_P(nir_serialize_all_test, alu_vec)
144bf215546Sopenharmony_ci{
145bf215546Sopenharmony_ci   nir_ssa_def *undef = nir_ssa_undef(b, GetParam(), 32);
146bf215546Sopenharmony_ci   nir_ssa_def *undefs[] = {
147bf215546Sopenharmony_ci      undef, undef, undef, undef,
148bf215546Sopenharmony_ci      undef, undef, undef, undef,
149bf215546Sopenharmony_ci      undef, undef, undef, undef,
150bf215546Sopenharmony_ci      undef, undef, undef, undef,
151bf215546Sopenharmony_ci   };
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   nir_ssa_def *vec = nir_vec(b, undefs, GetParam());
154bf215546Sopenharmony_ci   nir_alu_instr *vec_alu = nir_instr_as_alu(vec->parent_instr);
155bf215546Sopenharmony_ci   for (int i = 0; i < GetParam(); i++)
156bf215546Sopenharmony_ci      vec_alu->src[i].swizzle[0] = (GetParam() - 1) - i;
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   serialize();
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci   nir_alu_instr *vec_alu_dup = get_last_alu(dup);
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(vec_alu, vec_alu_dup, 1, 0);
163bf215546Sopenharmony_ci}
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ciTEST_P(nir_serialize_all_test, alu_two_components_full_swizzle)
166bf215546Sopenharmony_ci{
167bf215546Sopenharmony_ci   nir_ssa_def *undef = nir_ssa_undef(b, 2, 32);
168bf215546Sopenharmony_ci   nir_ssa_def *fma = nir_ffma(b, undef, undef, undef);
169bf215546Sopenharmony_ci   nir_alu_instr *fma_alu = nir_instr_as_alu(fma->parent_instr);
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   fma->num_components = GetParam();
172bf215546Sopenharmony_ci   fma_alu->dest.write_mask = (1 << GetParam()) - 1;
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   memset(fma_alu->src[0].swizzle, 1, GetParam());
175bf215546Sopenharmony_ci   memset(fma_alu->src[1].swizzle, 1, GetParam());
176bf215546Sopenharmony_ci   memset(fma_alu->src[2].swizzle, 1, GetParam());
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   serialize();
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   nir_alu_instr *fma_alu_dup = get_last_alu(dup);
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, GetParam(), 0);
183bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, GetParam(), 1);
184bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, GetParam(), 2);
185bf215546Sopenharmony_ci}
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ciTEST_P(nir_serialize_all_but_one_test, alu_two_components_reg_two_swizzle)
188bf215546Sopenharmony_ci{
189bf215546Sopenharmony_ci   nir_ssa_def *undef = nir_ssa_undef(b, 2, 32);
190bf215546Sopenharmony_ci   nir_ssa_def *fma = nir_ffma(b, undef, undef, undef);
191bf215546Sopenharmony_ci   nir_alu_instr *fma_alu = nir_instr_as_alu(fma->parent_instr);
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci   memset(fma_alu->src[0].swizzle, 1, GetParam());
194bf215546Sopenharmony_ci   memset(fma_alu->src[1].swizzle, 1, GetParam());
195bf215546Sopenharmony_ci   memset(fma_alu->src[2].swizzle, 1, GetParam());
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   ASSERT_TRUE(nir_convert_from_ssa(b->shader, false));
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   fma_alu = get_last_alu(b->shader);
200bf215546Sopenharmony_ci   ASSERT_FALSE(fma_alu->dest.dest.is_ssa);
201bf215546Sopenharmony_ci   fma_alu->dest.dest.reg.reg->num_components = GetParam();
202bf215546Sopenharmony_ci   fma_alu->dest.write_mask = 1 | (1 << (GetParam() - 1));
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   serialize();
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   nir_alu_instr *fma_alu_dup = get_last_alu(dup);
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[0].swizzle[0], fma_alu_dup->src[0].swizzle[0]);
209bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[0].swizzle[GetParam() - 1], fma_alu_dup->src[0].swizzle[GetParam() - 1]);
210bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[1].swizzle[0], fma_alu_dup->src[1].swizzle[0]);
211bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[1].swizzle[GetParam() - 1], fma_alu_dup->src[1].swizzle[GetParam() - 1]);
212bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[2].swizzle[0], fma_alu_dup->src[2].swizzle[0]);
213bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[2].swizzle[GetParam() - 1], fma_alu_dup->src[2].swizzle[GetParam() - 1]);
214bf215546Sopenharmony_ci}
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ciTEST_P(nir_serialize_all_but_one_test, alu_full_width_reg_two_swizzle)
217bf215546Sopenharmony_ci{
218bf215546Sopenharmony_ci   nir_ssa_def *undef = nir_ssa_undef(b, GetParam(), 32);
219bf215546Sopenharmony_ci   nir_ssa_def *fma = nir_ffma(b, undef, undef, undef);
220bf215546Sopenharmony_ci   nir_alu_instr *fma_alu = nir_instr_as_alu(fma->parent_instr);
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   memset(fma_alu->src[0].swizzle, GetParam() - 1, GetParam());
223bf215546Sopenharmony_ci   memset(fma_alu->src[1].swizzle, GetParam() - 1, GetParam());
224bf215546Sopenharmony_ci   memset(fma_alu->src[2].swizzle, GetParam() - 1, GetParam());
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   ASSERT_TRUE(nir_convert_from_ssa(b->shader, false));
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   fma_alu = get_last_alu(b->shader);
229bf215546Sopenharmony_ci   ASSERT_FALSE(fma_alu->dest.dest.is_ssa);
230bf215546Sopenharmony_ci   fma_alu->dest.write_mask = 1 | (1 << (GetParam() - 1));
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   serialize();
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci   nir_alu_instr *fma_alu_dup = get_last_alu(dup);
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[0].swizzle[0], fma_alu_dup->src[0].swizzle[0]);
237bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[0].swizzle[GetParam() - 1], fma_alu_dup->src[0].swizzle[GetParam() - 1]);
238bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[1].swizzle[0], fma_alu_dup->src[1].swizzle[0]);
239bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[1].swizzle[GetParam() - 1], fma_alu_dup->src[1].swizzle[GetParam() - 1]);
240bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[2].swizzle[0], fma_alu_dup->src[2].swizzle[0]);
241bf215546Sopenharmony_ci   ASSERT_EQ(fma_alu->src[2].swizzle[GetParam() - 1], fma_alu_dup->src[2].swizzle[GetParam() - 1]);
242bf215546Sopenharmony_ci}
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ciTEST_P(nir_serialize_all_but_one_test, alu_two_component_reg_full_src)
245bf215546Sopenharmony_ci{
246bf215546Sopenharmony_ci   nir_ssa_def *undef = nir_ssa_undef(b, GetParam(), 32);
247bf215546Sopenharmony_ci   nir_ssa_def *fma = nir_ffma(b, undef, undef, undef);
248bf215546Sopenharmony_ci   nir_alu_instr *fma_alu = nir_instr_as_alu(fma->parent_instr);
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   memset(fma_alu->src[0].swizzle, 1, GetParam());
251bf215546Sopenharmony_ci   memset(fma_alu->src[1].swizzle, 1, GetParam());
252bf215546Sopenharmony_ci   memset(fma_alu->src[2].swizzle, 1, GetParam());
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   ASSERT_TRUE(nir_convert_from_ssa(b->shader, false));
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   fma_alu = get_last_alu(b->shader);
257bf215546Sopenharmony_ci   ASSERT_FALSE(fma_alu->dest.dest.is_ssa);
258bf215546Sopenharmony_ci   fma_alu->dest.dest.reg.reg->num_components = 2;
259bf215546Sopenharmony_ci   fma_alu->dest.write_mask = 0x3;
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci   serialize();
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   nir_alu_instr *fma_alu_dup = get_last_alu(dup);
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, 2, 0);
266bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, 2, 1);
267bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(fma_alu, fma_alu_dup, 2, 2);
268bf215546Sopenharmony_ci}
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ciTEST_P(nir_serialize_all_but_one_test, single_channel)
271bf215546Sopenharmony_ci{
272bf215546Sopenharmony_ci   nir_ssa_def *zero = nir_ssa_undef(b, GetParam(), 32);
273bf215546Sopenharmony_ci   nir_ssa_def *vec = nir_channel(b, zero, GetParam() - 1);
274bf215546Sopenharmony_ci   nir_alu_instr *vec_alu = nir_instr_as_alu(vec->parent_instr);
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci   serialize();
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   nir_alu_instr *vec_alu_dup = get_last_alu(dup);
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   ASSERT_SWIZZLE_EQ(vec_alu, vec_alu_dup, 1, 0);
281bf215546Sopenharmony_ci}
282