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