1 /*
2 * Copyright (C) 2022 Collabora, Ltd.
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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include "bi_builder.h"
25 #include "bi_test.h"
26 #include "va_compiler.h"
27 #include "valhall_enums.h"
28
29 #include <gtest/gtest.h>
30
31 #define CASE(test, expected) \
32 do { \
33 bi_builder *A = bit_builder(mem_ctx); \
34 bi_builder *B = bit_builder(mem_ctx); \
35 { \
36 bi_builder *b = A; \
37 A->shader->stage = MESA_SHADER_FRAGMENT; \
38 test; \
39 } \
40 va_merge_flow(A->shader); \
41 { \
42 bi_builder *b = B; \
43 B->shader->stage = MESA_SHADER_FRAGMENT; \
44 expected; \
45 } \
46 ASSERT_SHADER_EQUAL(A->shader, B->shader); \
47 } while (0)
48
49 #define NEGCASE(test) CASE(test, test)
50
51 #define flow(f) bi_nop(b)->flow = VA_FLOW_##f
52
53 class MergeFlow : public testing::Test {
54 protected:
MergeFlow()55 MergeFlow()
56 {
57 mem_ctx = ralloc_context(NULL);
58 atest = bi_fau(BIR_FAU_ATEST_PARAM, false);
59 }
60
~MergeFlow()61 ~MergeFlow()
62 {
63 ralloc_free(mem_ctx);
64 }
65
66 void *mem_ctx;
67 bi_instr *I;
68 bi_index atest;
69 };
70
TEST_F(MergeFlow,End)71 TEST_F(MergeFlow, End)
72 {
73 CASE(
74 {
75 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
76 bi_blend_to(b, bi_register(0), bi_register(4), bi_register(5),
77 bi_register(6), bi_register(7), bi_register(8),
78 BI_REGISTER_FORMAT_AUTO, 4, 4);
79 flow(END);
80 },
81 {
82 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
83 I = bi_blend_to(b, bi_register(0), bi_register(4), bi_register(5),
84 bi_register(6), bi_register(7), bi_register(8),
85 BI_REGISTER_FORMAT_AUTO, 4, 4);
86 I->flow = VA_FLOW_END;
87 });
88 }
89
TEST_F(MergeFlow,Reconverge)90 TEST_F(MergeFlow, Reconverge)
91 {
92 CASE(
93 {
94 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
95 bi_blend_to(b, bi_register(0), bi_register(4), bi_register(5),
96 bi_register(6), bi_register(7), bi_register(8),
97 BI_REGISTER_FORMAT_AUTO, 4, 4);
98 flow(RECONVERGE);
99 },
100 {
101 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
102 I = bi_blend_to(b, bi_register(0), bi_register(4), bi_register(5),
103 bi_register(6), bi_register(7), bi_register(8),
104 BI_REGISTER_FORMAT_AUTO, 4, 4);
105 I->flow = VA_FLOW_RECONVERGE;
106 });
107 }
108
TEST_F(MergeFlow,TrivialWait)109 TEST_F(MergeFlow, TrivialWait)
110 {
111 CASE(
112 {
113 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
114 flow(WAIT0126);
115 bi_atest_to(b, bi_register(0), bi_register(4), bi_register(5), atest);
116 },
117 {
118 I = bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
119 I->flow = VA_FLOW_WAIT0126;
120 bi_atest_to(b, bi_register(0), bi_register(4), bi_register(5), atest);
121 });
122 }
123
TEST_F(MergeFlow,LoadThenUnrelatedThenUse)124 TEST_F(MergeFlow, LoadThenUnrelatedThenUse)
125 {
126 CASE(
127 {
128 bi_ld_attr_imm_to(b, bi_register(16), bi_register(60), bi_register(61),
129 BI_REGISTER_FORMAT_F32, BI_VECSIZE_V4, 1);
130 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
131 flow(WAIT0);
132 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(19));
133 flow(END);
134 },
135 {
136 bi_ld_attr_imm_to(b, bi_register(16), bi_register(60), bi_register(61),
137 BI_REGISTER_FORMAT_F32, BI_VECSIZE_V4, 1);
138 I = bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
139 I->flow = VA_FLOW_WAIT0;
140 I = bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(19));
141 I->flow = VA_FLOW_END;
142 });
143 }
144
TEST_F(MergeFlow,TrivialDiscard)145 TEST_F(MergeFlow, TrivialDiscard)
146 {
147 CASE(
148 {
149 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
150 bi_clper_i32_to(b, bi_register(0), bi_register(4), bi_register(8),
151 BI_INACTIVE_RESULT_ZERO, BI_LANE_OP_NONE,
152 BI_SUBGROUP_SUBGROUP4);
153 flow(DISCARD);
154 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
155 flow(END);
156 },
157 {
158 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
159 I = bi_clper_i32_to(b, bi_register(0), bi_register(4), bi_register(8),
160 BI_INACTIVE_RESULT_ZERO, BI_LANE_OP_NONE,
161 BI_SUBGROUP_SUBGROUP4);
162 I->flow = VA_FLOW_DISCARD;
163 I = bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
164 I->flow = VA_FLOW_END;
165 });
166 }
167
TEST_F(MergeFlow,TrivialDiscardAtTheStart)168 TEST_F(MergeFlow, TrivialDiscardAtTheStart)
169 {
170 CASE(
171 {
172 flow(DISCARD);
173 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
174 },
175 {
176 I = bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
177 I->flow = VA_FLOW_DISCARD;
178 });
179 }
180
TEST_F(MergeFlow,MoveDiscardPastWait)181 TEST_F(MergeFlow, MoveDiscardPastWait)
182 {
183 CASE(
184 {
185 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
186 bi_clper_i32_to(b, bi_register(0), bi_register(4), bi_register(8),
187 BI_INACTIVE_RESULT_ZERO, BI_LANE_OP_NONE,
188 BI_SUBGROUP_SUBGROUP4);
189 flow(DISCARD);
190 flow(WAIT0);
191 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
192 },
193 {
194 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
195 I = bi_clper_i32_to(b, bi_register(0), bi_register(4), bi_register(8),
196 BI_INACTIVE_RESULT_ZERO, BI_LANE_OP_NONE,
197 BI_SUBGROUP_SUBGROUP4);
198 I->flow = VA_FLOW_WAIT0;
199 I = bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
200 I->flow = VA_FLOW_DISCARD;
201 });
202 }
203
TEST_F(MergeFlow,OccludedWaitsAndDiscard)204 TEST_F(MergeFlow, OccludedWaitsAndDiscard)
205 {
206 CASE(
207 {
208 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
209 bi_clper_i32_to(b, bi_register(0), bi_register(4), bi_register(8),
210 BI_INACTIVE_RESULT_ZERO, BI_LANE_OP_NONE,
211 BI_SUBGROUP_SUBGROUP4);
212 flow(WAIT0);
213 flow(DISCARD);
214 flow(WAIT2);
215 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
216 },
217 {
218 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
219 I = bi_clper_i32_to(b, bi_register(0), bi_register(4), bi_register(8),
220 BI_INACTIVE_RESULT_ZERO, BI_LANE_OP_NONE,
221 BI_SUBGROUP_SUBGROUP4);
222 I->flow = VA_FLOW_WAIT02;
223 I = bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
224 I->flow = VA_FLOW_DISCARD;
225 });
226 }
227
TEST_F(MergeFlow,DeleteUselessWaits)228 TEST_F(MergeFlow, DeleteUselessWaits)
229 {
230 CASE(
231 {
232 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
233 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
234 flow(WAIT0);
235 flow(WAIT2);
236 flow(END);
237 },
238 {
239 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
240 I = bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
241 I->flow = VA_FLOW_END;
242 });
243 }
244
TEST_F(MergeFlow,BlockFullOfUselessWaits)245 TEST_F(MergeFlow, BlockFullOfUselessWaits)
246 {
247 CASE(
248 {
249 flow(WAIT0);
250 flow(WAIT2);
251 flow(DISCARD);
252 flow(END);
253 },
254 { flow(END); });
255 }
256
TEST_F(MergeFlow,WaitWithMessage)257 TEST_F(MergeFlow, WaitWithMessage)
258 {
259 CASE(
260 {
261 bi_ld_attr_imm_to(b, bi_register(16), bi_register(60), bi_register(61),
262 BI_REGISTER_FORMAT_F32, BI_VECSIZE_V4, 1);
263 flow(WAIT0);
264 },
265 {
266 I = bi_ld_attr_imm_to(b, bi_register(16), bi_register(60),
267 bi_register(61), BI_REGISTER_FORMAT_F32,
268 BI_VECSIZE_V4, 1);
269 I->flow = VA_FLOW_WAIT0;
270 });
271 }
272
TEST_F(MergeFlow,CantMoveWaitPastMessage)273 TEST_F(MergeFlow, CantMoveWaitPastMessage)
274 {
275 NEGCASE({
276 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
277 I =
278 bi_ld_attr_imm_to(b, bi_register(16), bi_register(60), bi_register(61),
279 BI_REGISTER_FORMAT_F32, BI_VECSIZE_V4, 1);
280
281 /* Pretend it's blocked for some reason. This doesn't actually happen
282 * with the current algorithm, but it's good to handle the special
283 * cases correctly in case we change later on.
284 */
285 I->flow = VA_FLOW_DISCARD;
286 flow(WAIT0);
287 });
288 }
289
TEST_F(MergeFlow,DeletePointlessDiscard)290 TEST_F(MergeFlow, DeletePointlessDiscard)
291 {
292 CASE(
293 {
294 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
295 bi_tex_single_to(
296 b, bi_register(0), bi_register(4), bi_register(8), bi_register(12),
297 false, BI_DIMENSION_2D, BI_REGISTER_FORMAT_F32, false, false,
298 BI_VA_LOD_MODE_COMPUTED_LOD, false, BI_WRITE_MASK_RGBA, 4);
299 flow(DISCARD);
300 flow(WAIT0);
301 flow(WAIT0126);
302 bi_atest_to(b, bi_register(0), bi_register(4), bi_register(5), atest);
303 flow(WAIT);
304 bi_blend_to(b, bi_register(0), bi_register(4), bi_register(5),
305 bi_register(6), bi_register(7), bi_register(8),
306 BI_REGISTER_FORMAT_AUTO, 4, 4);
307 flow(END);
308 },
309 {
310 bi_fadd_f32_to(b, bi_register(0), bi_register(0), bi_register(0));
311 I = bi_tex_single_to(
312 b, bi_register(0), bi_register(4), bi_register(8), bi_register(12),
313 false, BI_DIMENSION_2D, BI_REGISTER_FORMAT_F32, false, false,
314 BI_VA_LOD_MODE_COMPUTED_LOD, false, BI_WRITE_MASK_RGBA, 4);
315 I->flow = VA_FLOW_WAIT0126;
316 I = bi_atest_to(b, bi_register(0), bi_register(4), bi_register(5),
317 atest);
318 I->flow = VA_FLOW_WAIT;
319 I = bi_blend_to(b, bi_register(0), bi_register(4), bi_register(5),
320 bi_register(6), bi_register(7), bi_register(8),
321 BI_REGISTER_FORMAT_AUTO, 4, 4);
322 I->flow = VA_FLOW_END;
323 });
324 }
325
TEST_F(MergeFlow,PreserveTerminalBarriers)326 TEST_F(MergeFlow, PreserveTerminalBarriers)
327 {
328 CASE(
329 {
330 bi_barrier(b);
331 flow(WAIT);
332 flow(END);
333 },
334 {
335 bi_barrier(b)->flow = VA_FLOW_WAIT;
336 flow(END);
337 });
338 }
339