r600/sfn: rework getting a vector and uniforms from the value pool
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_emittexinstruction.cpp
1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2018 Collabora LTD
4 *
5 * Author: Gert Wollny <gert.wollny@collabora.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #include "sfn_emittexinstruction.h"
28 #include "sfn_shader_base.h"
29 #include "sfn_instruction_fetch.h"
30
31 namespace r600 {
32
33 EmitTexInstruction::EmitTexInstruction(ShaderFromNirProcessor &processor):
34 EmitInstruction (processor)
35 {
36 }
37
38 bool EmitTexInstruction::do_emit(nir_instr* instr)
39 {
40 nir_tex_instr* ir = nir_instr_as_tex(instr);
41
42 TexInputs src;
43 if (!get_inputs(*ir, src))
44 return false;
45
46 if (ir->sampler_dim == GLSL_SAMPLER_DIM_CUBE) {
47 switch (ir->op) {
48 case nir_texop_tex:
49 return emit_cube_tex(ir, src);
50 case nir_texop_txf:
51 return emit_cube_txf(ir, src);
52 case nir_texop_txb:
53 return emit_cube_txb(ir, src);
54 case nir_texop_txl:
55 return emit_cube_txl(ir, src);
56 case nir_texop_txs:
57 return emit_tex_txs(ir, src, {0,1,2,3});
58 case nir_texop_txd:
59 return emit_cube_txd(ir, src);
60 case nir_texop_lod:
61 return emit_cube_lod(ir, src);
62 case nir_texop_tg4:
63 return emit_cube_tg4(ir, src);
64 case nir_texop_query_levels:
65 return emit_tex_txs(ir, src, {3,7,7,7});
66 default:
67 return false;
68 }
69 } else if (ir->sampler_dim == GLSL_SAMPLER_DIM_BUF) {
70 switch (ir->op) {
71 case nir_texop_txf:
72 return emit_buf_txf(ir, src);
73 case nir_texop_txs:
74 return emit_tex_txs(ir, src, {0,1,2,3});
75 default:
76 return false;
77 }
78 } else {
79 switch (ir->op) {
80 case nir_texop_tex:
81 return emit_tex_tex(ir, src);
82 case nir_texop_txf:
83 return emit_tex_txf(ir, src);
84 case nir_texop_txb:
85 return emit_tex_txb(ir, src);
86 case nir_texop_txl:
87 return emit_tex_txl(ir, src);
88 case nir_texop_txd:
89 return emit_tex_txd(ir, src);
90 case nir_texop_txs:
91 return emit_tex_txs(ir, src, {0,1,2,3});
92 case nir_texop_lod:
93 return emit_tex_lod(ir, src);
94 case nir_texop_tg4:
95 return emit_tex_tg4(ir, src);
96 case nir_texop_txf_ms:
97 return emit_tex_txf_ms(ir, src);
98 case nir_texop_query_levels:
99 return emit_tex_txs(ir, src, {3,7,7,7});
100 default:
101 return false;
102 }
103 }
104 }
105
106 bool EmitTexInstruction::emit_cube_txf(UNUSED nir_tex_instr* instr, UNUSED TexInputs &src)
107 {
108 return false;
109 }
110
111 bool EmitTexInstruction::emit_cube_txd(nir_tex_instr* instr, TexInputs& tex_src)
112 {
113
114 assert(instr->src[0].src.is_ssa);
115
116 r600::sfn_log << SfnLog::instr << "emit '"
117 << *reinterpret_cast<nir_instr*>(instr)
118 << "' (" << __func__ << ")\n";
119
120 auto tex_op = TexInstruction::sample_g;
121
122 std::array<PValue, 4> v;
123 for (int i = 0; i < 4; ++i)
124 v[i] = from_nir(instr->dest, i);
125
126 GPRVector cubed(v);
127 emit_cube_prep(tex_src.coord, cubed, instr->is_array);
128
129 std::array<PValue,4> dst_elms;
130 std::array<PValue,4> src_elms;
131
132 const uint16_t lookup[4] = {1, 0, 3, 2};
133 for (uint16_t i = 0; i < 4; ++i) {
134 dst_elms[i] = v[i];
135 src_elms[i] = cubed.reg_i(lookup[i]);
136 }
137
138 GPRVector empty_dst(0, {7,7,7,7});
139
140 if (instr->is_shadow) {
141 emit_instruction(new AluInstruction(op1_mov, src_elms[3], tex_src.comperator,
142 {alu_last_instr, alu_write}));
143 tex_op = TexInstruction::sample_c_g;
144 }
145
146
147 PValue half(new LiteralValue(0.5f));
148 for (int i = 0; i < 3; ++i) {
149 emit_instruction(new AluInstruction(op2_mul_ieee, tex_src.ddx.reg_i(i), {tex_src.ddx.reg_i(i), half},
150 {alu_last_instr, alu_write}));
151 }
152 for (int i = 0; i < 3; ++i) {
153 emit_instruction(new AluInstruction(op2_mul_ieee, tex_src.ddy.reg_i(i), {tex_src.ddy.reg_i(i), half},
154 {alu_last_instr, alu_write}));
155 }
156
157 auto sampler = get_samplerr_id(instr->sampler_index, tex_src.sampler_deref);
158 assert(!sampler.indirect);
159
160 TexInstruction *irgh = new TexInstruction(TexInstruction::set_gradient_h, empty_dst, tex_src.ddx,
161 sampler.id, sampler.id + R600_MAX_CONST_BUFFERS, tex_src.sampler_offset);
162 irgh->set_dest_swizzle({7,7,7,7});
163
164 TexInstruction *irgv = new TexInstruction(TexInstruction::set_gradient_v, empty_dst, tex_src.ddy,
165 sampler.id, sampler.id + R600_MAX_CONST_BUFFERS, tex_src.sampler_offset);
166 irgv->set_dest_swizzle({7,7,7,7});
167
168 GPRVector dst(dst_elms);
169 GPRVector src(src_elms);
170 TexInstruction *ir = new TexInstruction(tex_op, dst, src, instr->sampler_index,
171 sampler.id + R600_MAX_CONST_BUFFERS, tex_src.sampler_offset);
172
173 set_rect_coordinate_flags(instr, ir);
174 //set_offsets(ir, tex_src.offset);
175
176 emit_instruction(irgh);
177 emit_instruction(irgv);
178 emit_instruction(ir);
179 return true;
180 }
181
182
183 bool EmitTexInstruction::emit_cube_txl(nir_tex_instr* instr, TexInputs& tex_src)
184 {
185 assert(instr->src[0].src.is_ssa);
186
187 if (instr->is_shadow)
188 return false;
189
190 r600::sfn_log << SfnLog::instr << "emit '"
191 << *reinterpret_cast<nir_instr*>(instr)
192 << "' (" << __func__ << ")\n";
193
194 std::array<PValue, 4> v;
195 for (int i = 0; i < 4; ++i)
196 v[i] = from_nir(instr->dest, i);
197
198 GPRVector cubed(v);
199 emit_cube_prep(tex_src.coord, cubed, instr->is_array);
200
201 std::array<PValue,4> dst_elms;
202 std::array<PValue,4> src_elms;
203
204 const uint16_t lookup[4] = {1, 0, 3, 2};
205 for (uint16_t i = 0; i < 4; ++i) {
206 dst_elms[i] = v[i];
207 src_elms[i] = cubed.reg_i(lookup[i]);
208 }
209
210 auto *ir = new AluInstruction(op1_mov, src_elms[3], tex_src.lod,
211 {alu_last_instr, alu_write});
212 emit_instruction(ir);
213
214 GPRVector src(src_elms);
215 GPRVector dst(dst_elms);
216
217 auto sampler = get_samplerr_id(instr->sampler_index, tex_src.sampler_deref);
218 assert(!sampler.indirect);
219
220 auto tir = new TexInstruction(TexInstruction::sample_l, dst, src,
221 sampler.id,sampler.id + R600_MAX_CONST_BUFFERS,
222 tex_src.sampler_offset);
223
224 if (instr->is_array)
225 tir->set_flag(TexInstruction::z_unnormalized);
226
227 emit_instruction(tir);
228 return true;
229 }
230
231 bool EmitTexInstruction::emit_cube_lod(nir_tex_instr* instr, TexInputs& src)
232 {
233 auto tex_op = TexInstruction::get_tex_lod;
234
235 std::array<PValue, 4> v;
236 for (int i = 0; i < 4; ++i)
237 v[i] = from_nir(instr->dest, i);
238
239 GPRVector cubed(v);
240 emit_cube_prep(src.coord, cubed, instr->is_array);
241
242 auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
243 assert(!sampler.indirect);
244
245 auto dst = make_dest(*instr);
246 auto irt = new TexInstruction(tex_op, dst, cubed, sampler.id,
247 sampler.id + R600_MAX_CONST_BUFFERS,
248 src.sampler_offset);
249
250 emit_instruction(irt);
251 return true;
252
253 }
254
255
256 bool EmitTexInstruction::emit_cube_txb(nir_tex_instr* instr, TexInputs& tex_src)
257 {
258 assert(instr->src[0].src.is_ssa);
259
260 r600::sfn_log << SfnLog::instr << "emit '"
261 << *reinterpret_cast<nir_instr*>(instr)
262 << "' (" << __func__ << ")\n";
263
264 std::array<PValue, 4> v;
265 for (int i = 0; i < 4; ++i)
266 v[i] = from_nir(instr->dest, i);
267
268 GPRVector cubed(v);
269 emit_cube_prep(tex_src.coord, cubed, instr->is_array);
270
271 std::array<PValue,4> dst_elms;
272 std::array<PValue,4> src_elms;
273
274 const uint16_t lookup[4] = {1, 0, 3, 2};
275 for (uint16_t i = 0; i < 4; ++i) {
276 dst_elms[i] = v[i];
277 src_elms[i] = v[lookup[i]];
278 }
279
280 GPRVector src(src_elms);
281 GPRVector dst(dst_elms);
282
283 auto tex_op = TexInstruction::sample_lb;
284 if (!instr->is_shadow) {
285 emit_instruction(new AluInstruction(op1_mov, src_elms[3], tex_src.bias,
286 {alu_last_instr, alu_write}));
287 } else {
288 emit_instruction(new AluInstruction(op1_mov, src_elms[3], tex_src.comperator,
289 {alu_last_instr, alu_write}));
290 tex_op = TexInstruction::sample_c_lb;
291 }
292
293 auto sampler = get_samplerr_id(instr->sampler_index, tex_src.sampler_deref);
294 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
295
296 auto tir = new TexInstruction(tex_op, dst, src,
297 sampler.id,
298 sampler.id + R600_MAX_CONST_BUFFERS, tex_src.sampler_offset);
299 emit_instruction(tir);
300 return true;
301
302 }
303
304 bool EmitTexInstruction::emit_cube_tex(nir_tex_instr* instr, TexInputs& tex_src)
305 {
306 std::array<PValue, 4> v;
307 for (int i = 0; i < 4; ++i)
308 v[i] = from_nir(instr->dest, i);
309
310 auto tex_op = TexInstruction::sample;
311 GPRVector cubed(v);
312 emit_cube_prep(tex_src.coord, cubed, instr->is_array);
313
314 std::array<PValue,4> dst_elms;
315 std::array<PValue,4> src_elms;
316
317 const uint16_t lookup[4] = {1, 0, 3, 2};
318 for (uint16_t i = 0; i < 4; ++i) {
319 dst_elms[i] = v[i];
320 src_elms[i] = v[lookup[i]];
321 }
322
323 if (instr->is_shadow) {
324 emit_instruction(new AluInstruction(op1_mov, src_elms[3], tex_src.comperator,
325 {alu_last_instr, alu_write}));
326 tex_op = TexInstruction::sample_c;
327 }
328
329 GPRVector dst(dst_elms);
330 GPRVector src(src_elms);
331
332 auto sampler = get_samplerr_id(instr->sampler_index, tex_src.sampler_deref);
333 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
334
335 auto tir = new TexInstruction(tex_op, dst, src,
336 sampler.id,
337 sampler.id + R600_MAX_CONST_BUFFERS, tex_src.sampler_offset);
338 if (instr->is_array)
339 tir->set_flag(TexInstruction::z_unnormalized);
340
341 emit_instruction(tir);
342 return true;
343
344 }
345
346 bool EmitTexInstruction::emit_cube_prep(const GPRVector& coord, GPRVector& cubed, bool is_array)
347 {
348 AluInstruction *ir = nullptr;
349 const uint16_t src0_chan[4] = {2, 2, 0, 1};
350 const uint16_t src1_chan[4] = {1, 0, 2, 2};
351
352 for (int i = 0; i < 4; ++i) {
353 ir = new AluInstruction(op2_cube, cubed.reg_i(i), coord.reg_i(src0_chan[i]),
354 coord.reg_i(src1_chan[i]), {alu_write});
355
356 emit_instruction(ir);
357 }
358 ir->set_flag(alu_last_instr);
359
360 ir = new AluInstruction(op1_recip_ieee, cubed.reg_i(2), cubed.reg_i(2), {alu_write, alu_last_instr});
361 ir->set_flag(alu_src0_abs);
362 emit_instruction(ir);
363
364 PValue one_p_5(new LiteralValue(1.5f));
365 for (int i = 0; i < 2; ++i) {
366 ir = new AluInstruction(op3_muladd, cubed.reg_i(i), cubed.reg_i(i), cubed.reg_i(2),
367 one_p_5, {alu_write});
368 emit_instruction(ir);
369 }
370 ir->set_flag(alu_last_instr);
371
372 if (is_array) {
373 auto face = cubed.reg_i(3);
374 PValue array_index = get_temp_register();
375
376 ir = new AluInstruction(op1_rndne, array_index, coord.reg_i(3), {alu_write, alu_last_instr});
377 emit_instruction(ir);
378
379 ir = new AluInstruction(op2_max, array_index, {array_index, Value::zero}, {alu_write, alu_last_instr});
380 emit_instruction(ir);
381
382 ir = new AluInstruction(op3_muladd, face, {array_index, PValue (new LiteralValue(8.0f)), face},
383 {alu_write, alu_last_instr});
384 emit_instruction(ir);
385 }
386
387 return true;
388 }
389
390 bool EmitTexInstruction::emit_buf_txf(nir_tex_instr* instr, TexInputs &src)
391 {
392 auto dst = make_dest(*instr);
393
394 auto ir = new FetchInstruction(vc_fetch, no_index_offset, dst, src.coord.reg_i(0), 0,
395 instr->texture_index + R600_MAX_CONST_BUFFERS,
396 PValue(), bim_none);
397 ir->set_flag(vtx_use_const_field);
398 emit_instruction(ir);
399 return true;
400 }
401
402 bool EmitTexInstruction::emit_tex_tex(nir_tex_instr* instr, TexInputs& src)
403 {
404
405 r600::sfn_log << SfnLog::instr << "emit '"
406 << *reinterpret_cast<nir_instr*>(instr)
407 << "' (" << __func__ << ")\n";
408
409 auto tex_op = TexInstruction::sample;
410
411 auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
412 assert(!sampler.indirect);
413
414 if (instr->is_shadow) {
415 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.comperator,
416 {alu_last_instr, alu_write}));
417 tex_op = TexInstruction::sample_c;
418 }
419
420 auto dst = make_dest(*instr);
421 auto irt = new TexInstruction(tex_op, dst, src.coord, sampler.id,
422 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
423 if (instr->is_array)
424 handle_array_index(*instr, src.coord, irt);
425
426 set_rect_coordinate_flags(instr, irt);
427 set_offsets(irt, src.offset);
428
429 emit_instruction(irt);
430 return true;
431 }
432
433 bool EmitTexInstruction::emit_tex_txd(nir_tex_instr* instr, TexInputs& src)
434 {
435 r600::sfn_log << SfnLog::instr << "emit '"
436 << *reinterpret_cast<nir_instr*>(instr)
437 << "' (" << __func__ << ")\n";
438
439 auto tex_op = TexInstruction::sample_g;
440 auto dst = make_dest(*instr);
441
442 GPRVector empty_dst(0,{7,7,7,7});
443
444 if (instr->is_shadow) {
445 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.comperator,
446 {alu_last_instr, alu_write}));
447 tex_op = TexInstruction::sample_c_g;
448 }
449
450 auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
451 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
452
453 TexInstruction *irgh = new TexInstruction(TexInstruction::set_gradient_h, empty_dst, src.ddx,
454 sampler.id,
455 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
456 irgh->set_dest_swizzle({7,7,7,7});
457
458 TexInstruction *irgv = new TexInstruction(TexInstruction::set_gradient_v, empty_dst, src.ddy,
459 sampler.id, sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
460 irgv->set_dest_swizzle({7,7,7,7});
461
462 TexInstruction *ir = new TexInstruction(tex_op, dst, src.coord, sampler.id,
463 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
464 if (instr->is_array)
465 handle_array_index(*instr, src.coord, ir);
466
467 set_rect_coordinate_flags(instr, ir);
468 set_offsets(ir, src.offset);
469
470 emit_instruction(irgh);
471 emit_instruction(irgv);
472 emit_instruction(ir);
473 return true;
474 }
475
476 bool EmitTexInstruction::emit_tex_txf(nir_tex_instr* instr, TexInputs& src)
477 {
478 r600::sfn_log << SfnLog::instr << "emit '"
479 << *reinterpret_cast<nir_instr*>(instr)
480 << "' (" << __func__ << ")\n";
481
482 auto dst = make_dest(*instr);
483
484 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.lod, {alu_write, alu_last_instr}));
485
486 auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
487 assert(!sampler.indirect);
488
489 /* txf doesn't need rounding for the array index, but 1D has the array index
490 * in the z component */
491 if (instr->is_array && instr->sampler_dim == GLSL_SAMPLER_DIM_1D)
492 src.coord.set_reg_i(2, src.coord.reg_i(1));
493
494 auto tex_ir = new TexInstruction(TexInstruction::ld, dst, src.coord,
495 sampler.id,
496 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
497
498
499 if (src.offset) {
500 assert(src.offset->is_ssa);
501 AluInstruction *ir = nullptr;
502 for (unsigned i = 0; i < src.offset->ssa->num_components; ++i) {
503 ir = new AluInstruction(op2_add_int, src.coord.reg_i(i),
504 {src.coord.reg_i(i), from_nir(*src.offset, i, i)}, {alu_write});
505 emit_instruction(ir);
506 }
507 if (ir)
508 ir->set_flag(alu_last_instr);
509 }
510
511 emit_instruction(tex_ir);
512 return true;
513 }
514
515 bool EmitTexInstruction::emit_tex_lod(nir_tex_instr* instr, TexInputs& src)
516 {
517 auto tex_op = TexInstruction::get_tex_lod;
518
519 auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
520 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
521
522 auto dst = make_dest(*instr);
523 auto irt = new TexInstruction(tex_op, dst, src.coord, sampler.id,
524 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
525 irt->set_dest_swizzle({1,0,7,7});
526 emit_instruction(irt);
527 return true;
528
529 }
530
531 bool EmitTexInstruction::emit_tex_txl(nir_tex_instr* instr, TexInputs& src)
532 {
533 r600::sfn_log << SfnLog::instr << "emit '"
534 << *reinterpret_cast<nir_instr*>(instr)
535 << "' (" << __func__ << ")\n";
536
537 auto tex_op = TexInstruction::sample_l;
538 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.lod,
539 {alu_last_instr, alu_write}));
540
541 if (instr->is_shadow) {
542 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(2), src.comperator,
543 {alu_last_instr, alu_write}));
544 tex_op = TexInstruction::sample_c_l;
545 }
546
547 auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
548 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
549
550 auto dst = make_dest(*instr);
551 auto irt = new TexInstruction(tex_op, dst, src.coord, sampler.id,
552 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
553
554 if (instr->is_array)
555 handle_array_index(*instr, src.coord, irt);
556
557 set_rect_coordinate_flags(instr, irt);
558 set_offsets(irt, src.offset);
559
560 emit_instruction(irt);
561 return true;
562 }
563
564 bool EmitTexInstruction::emit_tex_txb(nir_tex_instr* instr, TexInputs& src)
565 {
566 auto tex_op = TexInstruction::sample_lb;
567
568 std::array<uint8_t, 4> in_swizzle = {0,1,2,3};
569
570 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.bias,
571 {alu_last_instr, alu_write}));
572
573 if (instr->is_shadow) {
574 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(2), src.comperator,
575 {alu_last_instr, alu_write}));
576 tex_op = TexInstruction::sample_c_lb;
577 }
578
579 GPRVector tex_src(src.coord, in_swizzle);
580
581 auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
582 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
583
584 auto dst = make_dest(*instr);
585 auto irt = new TexInstruction(tex_op, dst, tex_src, sampler.id,
586 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
587 if (instr->is_array)
588 handle_array_index(*instr, tex_src, irt);
589
590 set_rect_coordinate_flags(instr, irt);
591 set_offsets(irt, src.offset);
592
593 emit_instruction(irt);
594 return true;
595 }
596
597 bool EmitTexInstruction::emit_tex_txs(nir_tex_instr* instr, TexInputs& tex_src,
598 const std::array<int,4>& dest_swz)
599 {
600 std::array<PValue,4> dst_elms;
601 std::array<PValue,4> src_elms;
602
603 for (uint16_t i = 0; i < 4; ++i) {
604 dst_elms[i] = from_nir(instr->dest, (i < instr->dest.ssa.num_components) ? i : 7);
605 }
606
607 GPRVector dst(dst_elms);
608
609 if (instr->sampler_dim == GLSL_SAMPLER_DIM_BUF) {
610 emit_instruction(new FetchInstruction(dst, PValue(new GPRValue(0, 7)),
611 instr->sampler_index + R600_MAX_CONST_BUFFERS,
612 bim_none));
613 } else {
614 for (uint16_t i = 0; i < 4; ++i)
615 src_elms[i] = tex_src.lod;
616 GPRVector src(src_elms);
617
618 auto sampler = get_samplerr_id(instr->sampler_index, tex_src.sampler_deref);
619 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
620
621 auto ir = new TexInstruction(TexInstruction::get_resinfo, dst, src,
622 sampler.id,
623 sampler.id + R600_MAX_CONST_BUFFERS, tex_src.sampler_offset);
624 ir->set_dest_swizzle(dest_swz);
625 emit_instruction(ir);
626 }
627
628 return true;
629
630 }
631
632 bool EmitTexInstruction::emit_tex_tg4(nir_tex_instr* instr, TexInputs& src)
633 {
634 r600::sfn_log << SfnLog::instr << "emit '"
635 << *reinterpret_cast<nir_instr*>(instr)
636 << "' (" << __func__ << ")\n";
637
638 auto tex_op = TexInstruction::gather4;
639
640 if (instr->is_shadow) {
641 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.comperator,
642 {alu_last_instr, alu_write}));
643 tex_op = TexInstruction::gather4_c;
644 }
645
646 auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
647 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
648
649 bool literal_offset = false;
650 if (src.offset) {
651 literal_offset = src.offset->is_ssa && get_literal_register(*src.offset);
652 r600::sfn_log << SfnLog::tex << " really have offsets and they are " <<
653 (literal_offset ? "literal" : "varying") <<
654 "\n";
655
656 if (!literal_offset) {
657 GPRVector::Swizzle swizzle = {4,4,4,4};
658 for (unsigned i = 0; i < instr->coord_components; ++i)
659 swizzle[i] = i;
660
661 int noffsets = instr->coord_components;
662 if (instr->is_array)
663 --noffsets;
664
665 auto ofs = vec_from_nir_with_fetch_constant(*src.offset,
666 ( 1 << noffsets) - 1,
667 swizzle);
668 GPRVector dummy(0, {7,7,7,7});
669 tex_op = (tex_op == TexInstruction::gather4_c) ?
670 TexInstruction::gather4_c_o : TexInstruction::gather4_o;
671
672 auto set_ofs = new TexInstruction(TexInstruction::set_offsets, dummy,
673 ofs, sampler.id,
674 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
675 set_ofs->set_dest_swizzle({7,7,7,7});
676 emit_instruction(set_ofs);
677 }
678 }
679
680
681 /* pre CAYMAN needs swizzle */
682 auto dst = make_dest(*instr);
683 auto irt = new TexInstruction(tex_op, dst, src.coord, sampler.id,
684 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
685
686 irt->set_dest_swizzle({1,2,0,3});
687 irt->set_gather_comp(instr->component);
688
689 if (instr->is_array)
690 handle_array_index(*instr, src.coord, irt);
691
692 if (literal_offset) {
693 r600::sfn_log << SfnLog::tex << "emit literal offsets\n";
694 set_offsets(irt, src.offset);
695 }
696
697 set_rect_coordinate_flags(instr, irt);
698
699 emit_instruction(irt);
700 return true;
701 }
702
703 bool EmitTexInstruction::emit_cube_tg4(nir_tex_instr* instr, TexInputs& tex_src)
704 {
705 std::array<PValue, 4> v;
706 for (int i = 0; i < 4; ++i)
707 v[i] = from_nir(instr->dest, i);
708
709 auto tex_op = TexInstruction::gather4;
710 GPRVector cubed(v);
711 emit_cube_prep(tex_src.coord, cubed, instr->is_array);
712
713 std::array<PValue,4> dst_elms;
714 std::array<PValue,4> src_elms;
715
716 const uint16_t lookup[4] = {1, 0, 3, 2};
717 for (uint16_t i = 0; i < 4; ++i) {
718 dst_elms[i] = v[i];
719 src_elms[i] = v[lookup[i]];
720 }
721
722 if (instr->is_shadow) {
723 emit_instruction(new AluInstruction(op1_mov, src_elms[3], tex_src.comperator,
724 {alu_last_instr, alu_write}));
725 tex_op = TexInstruction::gather4_c;
726 }
727
728 GPRVector dst(dst_elms);
729 GPRVector src(src_elms);
730
731 auto sampler = get_samplerr_id(instr->sampler_index, tex_src.sampler_deref);
732 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
733
734 auto tir = new TexInstruction(tex_op, dst, src, sampler.id,
735 sampler.id + R600_MAX_CONST_BUFFERS, tex_src.sampler_offset);
736
737 tir->set_gather_comp(instr->component);
738
739 tir->set_dest_swizzle({1, 2, 0, 3});
740
741 if (instr->is_array)
742 tir->set_flag(TexInstruction::z_unnormalized);
743
744 emit_instruction(tir);
745 return true;
746 }
747
748 bool EmitTexInstruction::emit_tex_txf_ms(nir_tex_instr* instr, TexInputs& src)
749 {
750 assert(instr->src[0].src.is_ssa);
751
752 r600::sfn_log << SfnLog::instr << "emit '"
753 << *reinterpret_cast<nir_instr*>(instr)
754 << "' (" << __func__ << ")\n";
755
756 auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
757 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
758
759 int sample_id = allocate_temp_register();
760
761 GPRVector sample_id_dest(sample_id, {0,7,7,7});
762 PValue help(new GPRValue(sample_id, 1));
763
764 /* FIXME: Texture destination registers must be handled differently,
765 * because the swizzle identfies which source componnet has to be written
766 * at a certain position, and the target register is actually different.
767 * At this point we just add a helper register, but for later work (scheduling
768 * and optimization on the r600 IR level, this needs to be implemented
769 * differently */
770
771
772 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3),
773 src.ms_index,
774 {alu_write, alu_last_instr}));
775
776 auto tex_sample_id_ir = new TexInstruction(TexInstruction::ld, sample_id_dest, src.coord,
777 sampler.id,
778 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
779 tex_sample_id_ir->set_flag(TexInstruction::x_unnormalized);
780 tex_sample_id_ir->set_flag(TexInstruction::y_unnormalized);
781 tex_sample_id_ir->set_flag(TexInstruction::z_unnormalized);
782 tex_sample_id_ir->set_flag(TexInstruction::w_unnormalized);
783 tex_sample_id_ir->set_inst_mode(1);
784
785 emit_instruction(tex_sample_id_ir);
786
787 emit_instruction(new AluInstruction(op2_mullo_int, help,
788 {src.ms_index, PValue(new LiteralValue(4))},
789 {alu_write, alu_last_instr}));
790
791 emit_instruction(new AluInstruction(op2_lshr_int, src.coord.reg_i(3),
792 {sample_id_dest.reg_i(0), help},
793 {alu_write, alu_last_instr}));
794
795 emit_instruction(new AluInstruction(op2_and_int, src.coord.reg_i(3),
796 {src.coord.reg_i(3), PValue(new LiteralValue(15))},
797 {alu_write, alu_last_instr}));
798
799 auto dst = make_dest(*instr);
800
801 /* txf doesn't need rounding for the array index, but 1D has the array index
802 * in the z component */
803 if (instr->is_array && instr->sampler_dim == GLSL_SAMPLER_DIM_1D)
804 src.coord.set_reg_i(2, src.coord.reg_i(1));
805
806 auto tex_ir = new TexInstruction(TexInstruction::ld, dst, src.coord,
807 sampler.id,
808 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
809
810
811 if (src.offset) {
812 assert(src.offset->is_ssa);
813 AluInstruction *ir = nullptr;
814 for (unsigned i = 0; i < src.offset->ssa->num_components; ++i) {
815 ir = new AluInstruction(op2_add_int, src.coord.reg_i(i),
816 {src.coord.reg_i(i), from_nir(*src.offset, i, i)}, {alu_write});
817 emit_instruction(ir);
818 }
819 if (ir)
820 ir->set_flag(alu_last_instr);
821 }
822
823 emit_instruction(tex_ir);
824 return true;
825 }
826
827 bool EmitTexInstruction::get_inputs(const nir_tex_instr& instr, TexInputs &src)
828 {
829 sfn_log << SfnLog::tex << "Get Inputs with " << instr.coord_components << " components\n";
830
831 unsigned grad_components = instr.coord_components;
832 if (instr.is_array)
833 --grad_components;
834
835
836 src.offset = nullptr;
837 bool retval = true;
838 for (unsigned i = 0; i < instr.num_srcs; ++i) {
839 switch (instr.src[i].src_type) {
840 case nir_tex_src_bias:
841 src.bias = from_nir(instr.src[i], 0);
842 break;
843
844 case nir_tex_src_coord: {
845 src.coord = vec_from_nir_with_fetch_constant(instr.src[i].src,
846 (1 << instr.coord_components) - 1,
847 {0,1,2,3});
848 } break;
849 case nir_tex_src_comparator:
850 src.comperator = from_nir(instr.src[i], 0);
851 break;
852 case nir_tex_src_ddx: {
853 sfn_log << SfnLog::tex << "Get DDX ";
854 src.ddx = vec_from_nir_with_fetch_constant(instr.src[i].src,
855 (1 << grad_components) - 1,
856 swizzle_from_comps(grad_components));
857 sfn_log << SfnLog::tex << src.ddx << "\n";
858 } break;
859 case nir_tex_src_ddy:{
860 sfn_log << SfnLog::tex << "Get DDY ";
861 src.ddy = vec_from_nir_with_fetch_constant(instr.src[i].src,
862 (1 << grad_components) - 1,
863 swizzle_from_comps(grad_components));
864 sfn_log << SfnLog::tex << src.ddy << "\n";
865 } break;
866 case nir_tex_src_lod:
867 src.lod = from_nir_with_fetch_constant(instr.src[i].src, 0);
868 break;
869 case nir_tex_src_offset:
870 sfn_log << SfnLog::tex << " -- Find offset\n";
871 src.offset = &instr.src[i].src;
872 break;
873 case nir_tex_src_sampler_deref:
874 src.sampler_deref = get_deref_location(instr.src[i].src);
875 break;
876 case nir_tex_src_texture_deref:
877 src.texture_deref = get_deref_location(instr.src[i].src);
878 break;
879 case nir_tex_src_ms_index:
880 src.ms_index = from_nir(instr.src[i], 0);
881 break;
882 case nir_tex_src_texture_offset:
883 src.texture_offset = from_nir(instr.src[i], 0);
884 break;
885 case nir_tex_src_sampler_offset:
886 src.sampler_offset = from_nir(instr.src[i], 0);
887 break;
888 case nir_tex_src_plane:
889 case nir_tex_src_projector:
890 case nir_tex_src_min_lod:
891 case nir_tex_src_ms_mcs:
892 default:
893 sfn_log << SfnLog::tex << "Texture source type " << instr.src[i].src_type << " not supported\n";
894 retval = false;
895 }
896 }
897 return retval;
898 }
899
900 GPRVector EmitTexInstruction::make_dest(nir_tex_instr& instr)
901 {
902 int num_dest_components = instr.dest.is_ssa ? instr.dest.ssa.num_components :
903 instr.dest.reg.reg->num_components;
904 std::array<PValue,4> dst_elms;
905 for (uint16_t i = 0; i < 4; ++i)
906 dst_elms[i] = from_nir(instr.dest, (i < num_dest_components) ? i : 7);
907 return GPRVector(dst_elms);
908 }
909
910
911 GPRVector EmitTexInstruction::make_dest(nir_tex_instr& instr,
912 const std::array<int, 4>& swizzle)
913 {
914 int num_dest_components = instr.dest.is_ssa ? instr.dest.ssa.num_components :
915 instr.dest.reg.reg->num_components;
916 std::array<PValue,4> dst_elms;
917 for (uint16_t i = 0; i < 4; ++i) {
918 int k = swizzle[i];
919 dst_elms[i] = from_nir(instr.dest, (k < num_dest_components) ? k : 7);
920 }
921 return GPRVector(dst_elms);
922 }
923
924 void EmitTexInstruction::set_rect_coordinate_flags(nir_tex_instr* instr,
925 TexInstruction* ir) const
926 {
927 if (instr->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
928 ir->set_flag(TexInstruction::x_unnormalized);
929 ir->set_flag(TexInstruction::y_unnormalized);
930 }
931 }
932
933 void EmitTexInstruction::set_offsets(TexInstruction* ir, nir_src *offset)
934 {
935 if (!offset)
936 return;
937
938 assert(offset->is_ssa);
939 auto literal = get_literal_register(*offset);
940 assert(literal);
941
942 for (int i = 0; i < offset->ssa->num_components; ++i) {
943 ir->set_offset(i, literal->value[i].i32);
944 }
945 }
946
947 void EmitTexInstruction::handle_array_index(const nir_tex_instr& instr, const GPRVector& src, TexInstruction *ir)
948 {
949 int src_idx = instr.sampler_dim == GLSL_SAMPLER_DIM_1D ? 1 : 2;
950 emit_instruction(new AluInstruction(op1_rndne, src.reg_i(2), src.reg_i(src_idx),
951 {alu_last_instr, alu_write}));
952 ir->set_flag(TexInstruction::z_unnormalized);
953 }
954
955 EmitTexInstruction::SamplerId
956 EmitTexInstruction::get_samplerr_id(int sampler_id, const nir_variable *deref)
957 {
958 EmitTexInstruction::SamplerId result = {sampler_id, false};
959
960 if (deref) {
961 assert(glsl_type_is_sampler(deref->type));
962 result.id = deref->data.binding;
963 }
964 return result;
965 }
966
967 EmitTexInstruction::TexInputs::TexInputs():
968 sampler_deref(nullptr),
969 texture_deref(nullptr),
970 offset(nullptr)
971 {
972 }
973
974 }