i965: Lift some restrictions on dma_buf EGLImages
[mesa.git] / src / mesa / drivers / dri / i965 / test_fs_saturate_propagation.cpp
1 /*
2 * Copyright © 2015 Intel Corporation
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 DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <gtest/gtest.h>
25 #include "brw_fs.h"
26 #include "brw_cfg.h"
27 #include "program/program.h"
28
29 class saturate_propagation_test : public ::testing::Test {
30 virtual void SetUp();
31
32 public:
33 struct brw_context *brw;
34 struct gl_context *ctx;
35 struct brw_wm_prog_data *prog_data;
36 struct gl_shader_program *shader_prog;
37 struct brw_fragment_program *fp;
38 fs_visitor *v;
39 };
40
41 class saturate_propagation_fs_visitor : public fs_visitor
42 {
43 public:
44 saturate_propagation_fs_visitor(struct brw_context *brw,
45 struct brw_wm_prog_data *prog_data,
46 struct gl_shader_program *shader_prog)
47 : fs_visitor(brw, NULL, NULL, prog_data, shader_prog, NULL, 8) {}
48 };
49
50
51 void saturate_propagation_test::SetUp()
52 {
53 brw = (struct brw_context *)calloc(1, sizeof(*brw));
54 ctx = &brw->ctx;
55
56 fp = ralloc(NULL, struct brw_fragment_program);
57 prog_data = ralloc(NULL, struct brw_wm_prog_data);
58 shader_prog = ralloc(NULL, struct gl_shader_program);
59
60 v = new saturate_propagation_fs_visitor(brw, prog_data, shader_prog);
61
62 _mesa_init_fragment_program(ctx, &fp->program, GL_FRAGMENT_SHADER, 0);
63
64 brw->gen = 4;
65 }
66
67 static fs_inst *
68 instruction(bblock_t *block, int num)
69 {
70 fs_inst *inst = (fs_inst *)block->start();
71 for (int i = 0; i < num; i++) {
72 inst = (fs_inst *)inst->next;
73 }
74 return inst;
75 }
76
77 static bool
78 saturate_propagation(fs_visitor *v)
79 {
80 const bool print = false;
81
82 if (print) {
83 fprintf(stderr, "= Before =\n");
84 v->cfg->dump(v);
85 }
86
87 bool ret = v->opt_saturate_propagation();
88
89 if (print) {
90 fprintf(stderr, "\n= After =\n");
91 v->cfg->dump(v);
92 }
93
94 return ret;
95 }
96
97 TEST_F(saturate_propagation_test, basic)
98 {
99 fs_reg dst0 = v->vgrf(glsl_type::float_type);
100 fs_reg dst1 = v->vgrf(glsl_type::float_type);
101 fs_reg src0 = v->vgrf(glsl_type::float_type);
102 fs_reg src1 = v->vgrf(glsl_type::float_type);
103 v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
104 v->emit(BRW_OPCODE_MOV, dst1, dst0)
105 ->saturate = true;
106
107 /* = Before =
108 *
109 * 0: add(8) dst0 src0 src1
110 * 1: mov.sat(8) dst1 dst0
111 *
112 * = After =
113 * 0: add.sat(8) dst0 src0 src1
114 * 1: mov(8) dst1 dst0
115 */
116
117 v->calculate_cfg();
118 bblock_t *block0 = v->cfg->blocks[0];
119
120 EXPECT_EQ(0, block0->start_ip);
121 EXPECT_EQ(1, block0->end_ip);
122
123 EXPECT_TRUE(saturate_propagation(v));
124 EXPECT_EQ(0, block0->start_ip);
125 EXPECT_EQ(1, block0->end_ip);
126 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
127 EXPECT_TRUE(instruction(block0, 0)->saturate);
128 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
129 EXPECT_FALSE(instruction(block0, 1)->saturate);
130 }
131
132 TEST_F(saturate_propagation_test, other_non_saturated_use)
133 {
134 fs_reg dst0 = v->vgrf(glsl_type::float_type);
135 fs_reg dst1 = v->vgrf(glsl_type::float_type);
136 fs_reg dst2 = v->vgrf(glsl_type::float_type);
137 fs_reg src0 = v->vgrf(glsl_type::float_type);
138 fs_reg src1 = v->vgrf(glsl_type::float_type);
139 v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
140 v->emit(BRW_OPCODE_MOV, dst1, dst0)
141 ->saturate = true;
142 v->emit(BRW_OPCODE_ADD, dst2, dst0, src0);
143
144 /* = Before =
145 *
146 * 0: add(8) dst0 src0 src1
147 * 1: mov.sat(8) dst1 dst0
148 * 2: add(8) dst2 dst0 src0
149 *
150 * = After =
151 * (no changes)
152 */
153
154 v->calculate_cfg();
155 bblock_t *block0 = v->cfg->blocks[0];
156
157 EXPECT_EQ(0, block0->start_ip);
158 EXPECT_EQ(2, block0->end_ip);
159
160 EXPECT_FALSE(saturate_propagation(v));
161 EXPECT_EQ(0, block0->start_ip);
162 EXPECT_EQ(2, block0->end_ip);
163 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
164 EXPECT_FALSE(instruction(block0, 0)->saturate);
165 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
166 EXPECT_TRUE(instruction(block0, 1)->saturate);
167 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 2)->opcode);
168 }
169
170 TEST_F(saturate_propagation_test, predicated_instruction)
171 {
172 fs_reg dst0 = v->vgrf(glsl_type::float_type);
173 fs_reg dst1 = v->vgrf(glsl_type::float_type);
174 fs_reg src0 = v->vgrf(glsl_type::float_type);
175 fs_reg src1 = v->vgrf(glsl_type::float_type);
176 v->emit(BRW_OPCODE_ADD, dst0, src0, src1)
177 ->predicate = BRW_PREDICATE_NORMAL;
178 v->emit(BRW_OPCODE_MOV, dst1, dst0)
179 ->saturate = true;
180
181 /* = Before =
182 *
183 * 0: (+f0) add(8) dst0 src0 src1
184 * 1: mov.sat(8) dst1 dst0
185 *
186 * = After =
187 * (no changes)
188 */
189
190 v->calculate_cfg();
191 bblock_t *block0 = v->cfg->blocks[0];
192
193 EXPECT_EQ(0, block0->start_ip);
194 EXPECT_EQ(1, block0->end_ip);
195
196 EXPECT_FALSE(saturate_propagation(v));
197 EXPECT_EQ(0, block0->start_ip);
198 EXPECT_EQ(1, block0->end_ip);
199 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
200 EXPECT_FALSE(instruction(block0, 0)->saturate);
201 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
202 EXPECT_TRUE(instruction(block0, 1)->saturate);
203 }
204
205 TEST_F(saturate_propagation_test, neg_mov_sat)
206 {
207 fs_reg dst0 = v->vgrf(glsl_type::float_type);
208 fs_reg dst1 = v->vgrf(glsl_type::float_type);
209 fs_reg src0 = v->vgrf(glsl_type::float_type);
210 fs_reg src1 = v->vgrf(glsl_type::float_type);
211 v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
212 dst0.negate = true;
213 v->emit(BRW_OPCODE_MOV, dst1, dst0)
214 ->saturate = true;
215
216 /* = Before =
217 *
218 * 0: add(8) dst0 src0 src1
219 * 1: mov.sat(8) dst1 -dst0
220 *
221 * = After =
222 * (no changes)
223 */
224
225 v->calculate_cfg();
226 bblock_t *block0 = v->cfg->blocks[0];
227
228 EXPECT_EQ(0, block0->start_ip);
229 EXPECT_EQ(1, block0->end_ip);
230
231 EXPECT_FALSE(saturate_propagation(v));
232 EXPECT_EQ(0, block0->start_ip);
233 EXPECT_EQ(1, block0->end_ip);
234 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
235 EXPECT_FALSE(instruction(block0, 0)->saturate);
236 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
237 EXPECT_TRUE(instruction(block0, 1)->saturate);
238 }
239
240 TEST_F(saturate_propagation_test, abs_mov_sat)
241 {
242 fs_reg dst0 = v->vgrf(glsl_type::float_type);
243 fs_reg dst1 = v->vgrf(glsl_type::float_type);
244 fs_reg src0 = v->vgrf(glsl_type::float_type);
245 fs_reg src1 = v->vgrf(glsl_type::float_type);
246 v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
247 dst0.abs = true;
248 v->emit(BRW_OPCODE_MOV, dst1, dst0)
249 ->saturate = true;
250
251 /* = Before =
252 *
253 * 0: add(8) dst0 src0 src1
254 * 1: mov.sat(8) dst1 (abs)dst0
255 *
256 * = After =
257 * (no changes)
258 */
259
260 v->calculate_cfg();
261 bblock_t *block0 = v->cfg->blocks[0];
262
263 EXPECT_EQ(0, block0->start_ip);
264 EXPECT_EQ(1, block0->end_ip);
265
266 EXPECT_FALSE(saturate_propagation(v));
267 EXPECT_EQ(0, block0->start_ip);
268 EXPECT_EQ(1, block0->end_ip);
269 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
270 EXPECT_FALSE(instruction(block0, 0)->saturate);
271 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
272 EXPECT_TRUE(instruction(block0, 1)->saturate);
273 }
274
275 TEST_F(saturate_propagation_test, producer_saturates)
276 {
277 fs_reg dst0 = v->vgrf(glsl_type::float_type);
278 fs_reg dst1 = v->vgrf(glsl_type::float_type);
279 fs_reg dst2 = v->vgrf(glsl_type::float_type);
280 fs_reg src0 = v->vgrf(glsl_type::float_type);
281 fs_reg src1 = v->vgrf(glsl_type::float_type);
282 v->emit(BRW_OPCODE_ADD, dst0, src0, src1)
283 ->saturate = true;
284 v->emit(BRW_OPCODE_MOV, dst1, dst0)
285 ->saturate = true;
286 v->emit(BRW_OPCODE_MOV, dst2, dst0);
287
288 /* = Before =
289 *
290 * 0: add.sat(8) dst0 src0 src1
291 * 1: mov.sat(8) dst1 dst0
292 * 2: mov(8) dst2 dst0
293 *
294 * = After =
295 * 0: add.sat(8) dst0 src0 src1
296 * 1: mov(8) dst1 dst0
297 * 2: mov(8) dst2 dst0
298 */
299
300 v->calculate_cfg();
301 bblock_t *block0 = v->cfg->blocks[0];
302
303 EXPECT_EQ(0, block0->start_ip);
304 EXPECT_EQ(2, block0->end_ip);
305
306 EXPECT_TRUE(saturate_propagation(v));
307 EXPECT_EQ(0, block0->start_ip);
308 EXPECT_EQ(2, block0->end_ip);
309 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
310 EXPECT_TRUE(instruction(block0, 0)->saturate);
311 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
312 EXPECT_FALSE(instruction(block0, 1)->saturate);
313 }
314
315 TEST_F(saturate_propagation_test, intervening_saturating_copy)
316 {
317 fs_reg dst0 = v->vgrf(glsl_type::float_type);
318 fs_reg dst1 = v->vgrf(glsl_type::float_type);
319 fs_reg dst2 = v->vgrf(glsl_type::float_type);
320 fs_reg src0 = v->vgrf(glsl_type::float_type);
321 fs_reg src1 = v->vgrf(glsl_type::float_type);
322 v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
323 v->emit(BRW_OPCODE_MOV, dst1, dst0)
324 ->saturate = true;
325 v->emit(BRW_OPCODE_MOV, dst2, dst0)
326 ->saturate = true;
327
328 /* = Before =
329 *
330 * 0: add(8) dst0 src0 src1
331 * 1: mov.sat(8) dst1 dst0
332 * 2: mov.sat(8) dst2 dst0
333 *
334 * = After =
335 * 0: add.sat(8) dst0 src0 src1
336 * 1: mov(8) dst1 dst0
337 * 2: mov(8) dst2 dst0
338 */
339
340 v->calculate_cfg();
341 bblock_t *block0 = v->cfg->blocks[0];
342
343 EXPECT_EQ(0, block0->start_ip);
344 EXPECT_EQ(2, block0->end_ip);
345
346 EXPECT_TRUE(saturate_propagation(v));
347 EXPECT_EQ(0, block0->start_ip);
348 EXPECT_EQ(2, block0->end_ip);
349 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
350 EXPECT_TRUE(instruction(block0, 0)->saturate);
351 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
352 EXPECT_FALSE(instruction(block0, 1)->saturate);
353 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
354 EXPECT_FALSE(instruction(block0, 2)->saturate);
355 }
356
357 TEST_F(saturate_propagation_test, intervening_dest_write)
358 {
359 fs_reg dst0 = v->vgrf(glsl_type::vec4_type);
360 fs_reg dst1 = v->vgrf(glsl_type::float_type);
361 fs_reg src0 = v->vgrf(glsl_type::float_type);
362 fs_reg src1 = v->vgrf(glsl_type::float_type);
363 fs_reg src2 = v->vgrf(glsl_type::vec2_type);
364 v->emit(BRW_OPCODE_ADD, offset(dst0, 2), src0, src1);
365 v->emit(SHADER_OPCODE_TEX, dst0, src2)
366 ->regs_written = 4;
367 v->emit(BRW_OPCODE_MOV, dst1, offset(dst0, 2))
368 ->saturate = true;
369
370 /* = Before =
371 *
372 * 0: add(8) dst0+2 src0 src1
373 * 1: tex(8) rlen 4 dst0+0 src2
374 * 2: mov.sat(8) dst1 dst0+2
375 *
376 * = After =
377 * (no changes)
378 */
379
380 v->calculate_cfg();
381 bblock_t *block0 = v->cfg->blocks[0];
382
383 EXPECT_EQ(0, block0->start_ip);
384 EXPECT_EQ(2, block0->end_ip);
385
386 EXPECT_FALSE(saturate_propagation(v));
387 EXPECT_EQ(0, block0->start_ip);
388 EXPECT_EQ(2, block0->end_ip);
389 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
390 EXPECT_FALSE(instruction(block0, 0)->saturate);
391 EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
392 EXPECT_FALSE(instruction(block0, 0)->saturate);
393 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
394 EXPECT_TRUE(instruction(block0, 2)->saturate);
395 }
396
397 TEST_F(saturate_propagation_test, mul_neg_mov_sat_mov_sat)
398 {
399 fs_reg dst0 = v->vgrf(glsl_type::float_type);
400 fs_reg dst1 = v->vgrf(glsl_type::float_type);
401 fs_reg dst2 = v->vgrf(glsl_type::float_type);
402 fs_reg src0 = v->vgrf(glsl_type::float_type);
403 fs_reg src1 = v->vgrf(glsl_type::float_type);
404 v->emit(BRW_OPCODE_MUL, dst0, src0, src1);
405 dst0.negate = true;
406 v->emit(BRW_OPCODE_MOV, dst1, dst0)
407 ->saturate = true;
408 dst0.negate = false;
409 v->emit(BRW_OPCODE_MOV, dst2, dst0)
410 ->saturate = true;
411
412 /* = Before =
413 *
414 * 0: mul(8) dst0 src0 src1
415 * 1: mov.sat(8) dst1 -dst0
416 * 2: mov.sat(8) dst2 dst0
417 *
418 * = After =
419 * (no changes)
420 */
421
422 v->calculate_cfg();
423 bblock_t *block0 = v->cfg->blocks[0];
424
425 EXPECT_EQ(0, block0->start_ip);
426 EXPECT_EQ(2, block0->end_ip);
427
428 EXPECT_FALSE(saturate_propagation(v));
429 EXPECT_EQ(0, block0->start_ip);
430 EXPECT_EQ(2, block0->end_ip);
431 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
432 EXPECT_FALSE(instruction(block0, 0)->saturate);
433 EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
434 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
435 EXPECT_TRUE(instruction(block0, 1)->saturate);
436 EXPECT_TRUE(instruction(block0, 1)->src[0].negate);
437 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
438 EXPECT_TRUE(instruction(block0, 2)->saturate);
439 }