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
EmitTexInstruction(ShaderFromNirProcessor & processor)33 EmitTexInstruction::EmitTexInstruction(ShaderFromNirProcessor &processor):
34 EmitInstruction (processor)
35 {
36 }
37
do_emit(nir_instr * instr)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_BUF) {
47 switch (ir->op) {
48 case nir_texop_txf:
49 return emit_buf_txf(ir, src);
50 case nir_texop_txs:
51 return emit_tex_txs(ir, src, {0,1,2,3});
52 default:
53 return false;
54 }
55 } else {
56 switch (ir->op) {
57 case nir_texop_tex:
58 return emit_tex_tex(ir, src);
59 case nir_texop_txf:
60 return emit_tex_txf(ir, src);
61 case nir_texop_txb:
62 return emit_tex_txb(ir, src);
63 case nir_texop_txl:
64 return emit_tex_txl(ir, src);
65 case nir_texop_txd:
66 return emit_tex_txd(ir, src);
67 case nir_texop_txs:
68 return emit_tex_txs(ir, src, {0,1,2,3});
69 case nir_texop_lod:
70 return emit_tex_lod(ir, src);
71 case nir_texop_tg4:
72 return emit_tex_tg4(ir, src);
73 case nir_texop_txf_ms:
74 return emit_tex_txf_ms(ir, src);
75 case nir_texop_query_levels:
76 return emit_tex_txs(ir, src, {3,7,7,7});
77 case nir_texop_texture_samples:
78 return emit_tex_texture_samples(ir, src, {3,7,7,7});
79 default:
80
81 return false;
82 }
83 }
84 }
85
emit_buf_txf(nir_tex_instr * instr,TexInputs & src)86 bool EmitTexInstruction::emit_buf_txf(nir_tex_instr* instr, TexInputs &src)
87 {
88 auto dst = make_dest(*instr);
89
90 auto ir = new FetchInstruction(vc_fetch, no_index_offset, dst, src.coord.reg_i(0), 0,
91 instr->texture_index + R600_MAX_CONST_BUFFERS,
92 src.texture_offset, bim_none);
93 ir->set_flag(vtx_use_const_field);
94 emit_instruction(ir);
95 return true;
96 }
97
emit_tex_tex(nir_tex_instr * instr,TexInputs & src)98 bool EmitTexInstruction::emit_tex_tex(nir_tex_instr* instr, TexInputs& src)
99 {
100
101 r600::sfn_log << SfnLog::instr << "emit '"
102 << *reinterpret_cast<nir_instr*>(instr)
103 << "' (" << __func__ << ")\n";
104
105 auto tex_op = TexInstruction::sample;
106
107 auto sampler = get_sampler_id(instr->sampler_index, src.sampler_deref);
108 assert(!sampler.indirect);
109
110 if (instr->is_shadow) {
111 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.comperator,
112 {alu_last_instr, alu_write}));
113 tex_op = TexInstruction::sample_c;
114 }
115
116 auto dst = make_dest(*instr);
117 auto irt = new TexInstruction(tex_op, dst, src.coord, sampler.id,
118 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
119 if (instr->is_array)
120 handle_array_index(*instr, src.coord, irt);
121
122 set_rect_coordinate_flags(instr, irt);
123 set_offsets(irt, src.offset);
124
125 emit_instruction(irt);
126 return true;
127 }
128
emit_tex_txd(nir_tex_instr * instr,TexInputs & src)129 bool EmitTexInstruction::emit_tex_txd(nir_tex_instr* instr, TexInputs& src)
130 {
131 r600::sfn_log << SfnLog::instr << "emit '"
132 << *reinterpret_cast<nir_instr*>(instr)
133 << "' (" << __func__ << ")\n";
134
135 auto tex_op = TexInstruction::sample_g;
136 auto dst = make_dest(*instr);
137
138 GPRVector empty_dst(0,{7,7,7,7});
139
140 if (instr->is_shadow) {
141 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.comperator,
142 {alu_last_instr, alu_write}));
143 tex_op = TexInstruction::sample_c_g;
144 }
145
146 auto sampler = get_sampler_id(instr->sampler_index, src.sampler_deref);
147 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
148
149 TexInstruction *irgh = new TexInstruction(TexInstruction::set_gradient_h, empty_dst, src.ddx,
150 sampler.id,
151 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
152 irgh->set_dest_swizzle({7,7,7,7});
153
154 TexInstruction *irgv = new TexInstruction(TexInstruction::set_gradient_v, empty_dst, src.ddy,
155 sampler.id, sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
156 irgv->set_dest_swizzle({7,7,7,7});
157
158 TexInstruction *ir = new TexInstruction(tex_op, dst, src.coord, sampler.id,
159 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
160 if (instr->is_array)
161 handle_array_index(*instr, src.coord, ir);
162
163 set_rect_coordinate_flags(instr, ir);
164 set_offsets(ir, src.offset);
165
166 emit_instruction(irgh);
167 emit_instruction(irgv);
168 emit_instruction(ir);
169 return true;
170 }
171
emit_tex_txf(nir_tex_instr * instr,TexInputs & src)172 bool EmitTexInstruction::emit_tex_txf(nir_tex_instr* instr, TexInputs& src)
173 {
174 r600::sfn_log << SfnLog::instr << "emit '"
175 << *reinterpret_cast<nir_instr*>(instr)
176 << "' (" << __func__ << ")\n";
177
178 auto dst = make_dest(*instr);
179
180 if (*src.coord.reg_i(3) != *src.lod) {
181 if (src.coord.sel() != src.lod->sel())
182 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.lod, {alu_write, alu_last_instr}));
183 else
184 src.coord.set_reg_i(3, src.lod);
185 }
186
187 auto sampler = get_sampler_id(instr->sampler_index, src.sampler_deref);
188 assert(!sampler.indirect);
189
190 /* txf doesn't need rounding for the array index, but 1D has the array index
191 * in the z component */
192 if (instr->is_array && instr->sampler_dim == GLSL_SAMPLER_DIM_1D)
193 src.coord.set_reg_i(2, src.coord.reg_i(1));
194
195 auto tex_ir = new TexInstruction(TexInstruction::ld, dst, src.coord,
196 sampler.id,
197 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
198
199
200 if (src.offset) {
201 assert(src.offset->is_ssa);
202 AluInstruction *ir = nullptr;
203 for (unsigned i = 0; i < src.offset->ssa->num_components; ++i) {
204 ir = new AluInstruction(op2_add_int, src.coord.reg_i(i),
205 {src.coord.reg_i(i), from_nir(*src.offset, i, i)}, {alu_write});
206 emit_instruction(ir);
207 }
208 if (ir)
209 ir->set_flag(alu_last_instr);
210 }
211
212 if (instr->is_array)
213 tex_ir->set_flag(TexInstruction::z_unnormalized);
214
215 emit_instruction(tex_ir);
216 return true;
217 }
218
emit_tex_lod(nir_tex_instr * instr,TexInputs & src)219 bool EmitTexInstruction::emit_tex_lod(nir_tex_instr* instr, TexInputs& src)
220 {
221 auto tex_op = TexInstruction::get_tex_lod;
222
223 auto sampler = get_sampler_id(instr->sampler_index, src.sampler_deref);
224 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
225
226 auto dst = make_dest(*instr);
227 auto irt = new TexInstruction(tex_op, dst, src.coord, sampler.id,
228 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
229 irt->set_dest_swizzle({1,0,7,7});
230 emit_instruction(irt);
231
232 return true;
233
234 }
235
emit_tex_txl(nir_tex_instr * instr,TexInputs & src)236 bool EmitTexInstruction::emit_tex_txl(nir_tex_instr* instr, TexInputs& src)
237 {
238 r600::sfn_log << SfnLog::instr << "emit '"
239 << *reinterpret_cast<nir_instr*>(instr)
240 << "' (" << __func__ << ")\n";
241
242 auto tex_op = TexInstruction::sample_l;
243 if (instr->is_shadow) {
244 if (src.coord.sel() != src.comperator->sel())
245 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(2), src.comperator, {alu_write}));
246 else
247 src.coord.set_reg_i(2, src.comperator);
248 tex_op = TexInstruction::sample_c_l;
249 }
250
251 if (src.coord.sel() != src.lod->sel())
252 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.lod, {last_write}));
253 else
254 src.coord.set_reg_i(3, src.lod);
255
256 auto sampler = get_sampler_id(instr->sampler_index, src.sampler_deref);
257 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
258
259 auto dst = make_dest(*instr);
260 auto irt = new TexInstruction(tex_op, dst, src.coord, sampler.id,
261 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
262
263 if (instr->is_array)
264 handle_array_index(*instr, src.coord, irt);
265
266 set_rect_coordinate_flags(instr, irt);
267 set_offsets(irt, src.offset);
268
269 emit_instruction(irt);
270 return true;
271 }
272
emit_tex_txb(nir_tex_instr * instr,TexInputs & src)273 bool EmitTexInstruction::emit_tex_txb(nir_tex_instr* instr, TexInputs& src)
274 {
275 auto tex_op = TexInstruction::sample_lb;
276
277 std::array<uint8_t, 4> in_swizzle = {0,1,2,3};
278
279 if (instr->is_shadow) {
280 if (src.coord.sel() != src.comperator->sel())
281 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(2), src.comperator, {alu_write}));
282 else
283 src.coord.set_reg_i(2, src.comperator);
284 tex_op = TexInstruction::sample_c_lb;
285 }
286
287 if (src.coord.sel() != src.bias->sel())
288 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.bias, {last_write}));
289 else
290 src.coord.set_reg_i(3, src.bias);
291
292 GPRVector tex_src(src.coord, in_swizzle);
293
294 auto sampler = get_sampler_id(instr->sampler_index, src.sampler_deref);
295 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
296
297 auto dst = make_dest(*instr);
298 auto irt = new TexInstruction(tex_op, dst, tex_src, sampler.id,
299 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
300 if (instr->is_array)
301 handle_array_index(*instr, tex_src, irt);
302
303 set_rect_coordinate_flags(instr, irt);
304 set_offsets(irt, src.offset);
305
306 emit_instruction(irt);
307 return true;
308 }
309
emit_tex_txs(nir_tex_instr * instr,TexInputs & tex_src,const std::array<int,4> & dest_swz)310 bool EmitTexInstruction::emit_tex_txs(nir_tex_instr* instr, TexInputs& tex_src,
311 const std::array<int,4>& dest_swz)
312 {
313 std::array<PValue,4> dst_elms;
314 std::array<PValue,4> src_elms;
315
316 for (uint16_t i = 0; i < 4; ++i) {
317 dst_elms[i] = from_nir(instr->dest, (i < instr->dest.ssa.num_components) ? i : 7);
318 }
319
320 GPRVector dst(dst_elms);
321
322 if (instr->sampler_dim == GLSL_SAMPLER_DIM_BUF) {
323 emit_instruction(new FetchInstruction(dst, PValue(new GPRValue(0, 7)),
324 instr->sampler_index + R600_MAX_CONST_BUFFERS,
325 bim_none));
326 } else {
327 for (uint16_t i = 0; i < 4; ++i)
328 src_elms[i] = tex_src.lod;
329 GPRVector src(src_elms);
330
331 auto sampler = get_sampler_id(instr->sampler_index, tex_src.sampler_deref);
332 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
333
334 auto ir = new TexInstruction(TexInstruction::get_resinfo, dst, src,
335 sampler.id,
336 sampler.id + R600_MAX_CONST_BUFFERS, tex_src.sampler_offset);
337 ir->set_dest_swizzle(dest_swz);
338 emit_instruction(ir);
339
340 if (instr->is_array && instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE) {
341 PValue src(new UniformValue(512 + R600_BUFFER_INFO_OFFSET / 16 + (sampler.id >> 2),
342 sampler.id & 3, R600_BUFFER_INFO_CONST_BUFFER));
343
344 auto alu = new AluInstruction(op1_mov, dst[2], src, {last_write});
345 emit_instruction(alu);
346 set_has_txs_cube_array_comp();
347 }
348 }
349
350 return true;
351
352 }
353
emit_tex_texture_samples(nir_tex_instr * instr,TexInputs & src,const std::array<int,4> & dest_swz)354 bool EmitTexInstruction::emit_tex_texture_samples(nir_tex_instr* instr, TexInputs& src,
355 const std::array<int, 4> &dest_swz)
356 {
357 GPRVector dest = vec_from_nir(instr->dest, nir_dest_num_components(instr->dest));
358 GPRVector help{0,{4,4,4,4}};
359
360 auto dyn_offset = PValue();
361 int res_id = R600_MAX_CONST_BUFFERS + instr->sampler_index;
362
363 auto ir = new TexInstruction(TexInstruction::get_nsampled, dest, help,
364 0, res_id, src.sampler_offset);
365 ir->set_dest_swizzle(dest_swz);
366 emit_instruction(ir);
367 return true;
368 }
369
emit_tex_tg4(nir_tex_instr * instr,TexInputs & src)370 bool EmitTexInstruction::emit_tex_tg4(nir_tex_instr* instr, TexInputs& src)
371 {
372 r600::sfn_log << SfnLog::instr << "emit '"
373 << *reinterpret_cast<nir_instr*>(instr)
374 << "' (" << __func__ << ")\n";
375
376 TexInstruction *set_ofs = nullptr;
377
378 auto tex_op = TexInstruction::gather4;
379
380 if (instr->is_shadow) {
381 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3), src.comperator,
382 {alu_last_instr, alu_write}));
383 tex_op = TexInstruction::gather4_c;
384 }
385
386 auto sampler = get_sampler_id(instr->sampler_index, src.sampler_deref);
387 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
388
389 bool literal_offset = false;
390 if (src.offset) {
391 literal_offset = nir_src_as_const_value(*src.offset) != 0;
392 r600::sfn_log << SfnLog::tex << " really have offsets and they are " <<
393 (literal_offset ? "literal" : "varying") <<
394 "\n";
395
396 if (!literal_offset) {
397 GPRVector::Swizzle swizzle = {4,4,4,4};
398 for (unsigned i = 0; i < instr->coord_components; ++i)
399 swizzle[i] = i;
400
401 int noffsets = instr->coord_components;
402 if (instr->is_array)
403 --noffsets;
404
405 auto ofs = vec_from_nir_with_fetch_constant(*src.offset,
406 ( 1 << noffsets) - 1,
407 swizzle);
408 GPRVector dummy(0, {7,7,7,7});
409 tex_op = (tex_op == TexInstruction::gather4_c) ?
410 TexInstruction::gather4_c_o : TexInstruction::gather4_o;
411
412 set_ofs = new TexInstruction(TexInstruction::set_offsets, dummy,
413 ofs, sampler.id,
414 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
415 set_ofs->set_dest_swizzle({7,7,7,7});
416 }
417 }
418
419
420 /* pre CAYMAN needs swizzle */
421 auto dst = make_dest(*instr);
422 auto irt = new TexInstruction(tex_op, dst, src.coord, sampler.id,
423 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
424
425 if (get_chip_class() != CAYMAN)
426 irt->set_dest_swizzle({1,2,0,3});
427 irt->set_gather_comp(instr->component);
428
429 if (instr->is_array)
430 handle_array_index(*instr, src.coord, irt);
431
432 if (literal_offset) {
433 r600::sfn_log << SfnLog::tex << "emit literal offsets\n";
434 set_offsets(irt, src.offset);
435 }
436
437 set_rect_coordinate_flags(instr, irt);
438
439 if (set_ofs)
440 emit_instruction(set_ofs);
441
442 emit_instruction(irt);
443 return true;
444 }
445
emit_tex_txf_ms(nir_tex_instr * instr,TexInputs & src)446 bool EmitTexInstruction::emit_tex_txf_ms(nir_tex_instr* instr, TexInputs& src)
447 {
448 assert(instr->src[0].src.is_ssa);
449
450 r600::sfn_log << SfnLog::instr << "emit '"
451 << *reinterpret_cast<nir_instr*>(instr)
452 << "' (" << __func__ << ")\n";
453
454 auto sampler = get_sampler_id(instr->sampler_index, src.sampler_deref);
455 assert(!sampler.indirect && "Indirect sampler selection not yet supported");
456
457 PGPRValue sample_id_dest_reg = get_temp_register();
458 GPRVector sample_id_dest(sample_id_dest_reg->sel(), {7,7,7,7});
459 sample_id_dest.set_reg_i(sample_id_dest_reg->chan(), sample_id_dest_reg);
460 std::array<int,4> dest_swz = {7,7,7,7};
461 dest_swz[sample_id_dest_reg->chan()] = 0;
462
463 emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3),
464 src.ms_index,
465 {alu_write, alu_last_instr}));
466
467 auto tex_sample_id_ir = new TexInstruction(TexInstruction::ld, sample_id_dest, src.coord,
468 sampler.id,
469 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
470 tex_sample_id_ir->set_flag(TexInstruction::x_unnormalized);
471 tex_sample_id_ir->set_flag(TexInstruction::y_unnormalized);
472 tex_sample_id_ir->set_flag(TexInstruction::z_unnormalized);
473 tex_sample_id_ir->set_flag(TexInstruction::w_unnormalized);
474 tex_sample_id_ir->set_inst_mode(1);
475
476 tex_sample_id_ir->set_dest_swizzle(dest_swz);
477
478 emit_instruction(tex_sample_id_ir);
479
480 if (src.ms_index->type() != Value::literal ||
481 static_cast<const LiteralValue&>(*src.ms_index).value() != 0) {
482 PValue help = get_temp_register();
483
484 emit_instruction(new AluInstruction(op2_lshl_int, help,
485 src.ms_index, literal(2),
486 {alu_write, alu_last_instr}));
487
488 emit_instruction(new AluInstruction(op2_lshr_int, sample_id_dest_reg,
489 {sample_id_dest_reg, help},
490 {alu_write, alu_last_instr}));
491 }
492
493 emit_instruction(new AluInstruction(op2_and_int, src.coord.reg_i(3),
494 {sample_id_dest_reg, PValue(new LiteralValue(15))},
495 {alu_write, alu_last_instr}));
496
497 auto dst = make_dest(*instr);
498
499 /* txf doesn't need rounding for the array index, but 1D has the array index
500 * in the z component */
501 if (instr->is_array && instr->sampler_dim == GLSL_SAMPLER_DIM_1D)
502 src.coord.set_reg_i(2, src.coord.reg_i(1));
503
504 auto tex_ir = new TexInstruction(TexInstruction::ld, dst, src.coord,
505 sampler.id,
506 sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
507
508
509 if (src.offset) {
510 assert(src.offset->is_ssa);
511 AluInstruction *ir = nullptr;
512 for (unsigned i = 0; i < src.offset->ssa->num_components; ++i) {
513 ir = new AluInstruction(op2_add_int, src.coord.reg_i(i),
514 {src.coord.reg_i(i), from_nir(*src.offset, i, i)}, {alu_write});
515 emit_instruction(ir);
516 }
517 if (ir)
518 ir->set_flag(alu_last_instr);
519 }
520
521 emit_instruction(tex_ir);
522 return true;
523 }
524
get_inputs(const nir_tex_instr & instr,TexInputs & src)525 bool EmitTexInstruction::get_inputs(const nir_tex_instr& instr, TexInputs &src)
526 {
527 sfn_log << SfnLog::tex << "Get Inputs with " << instr.coord_components << " components\n";
528
529 unsigned grad_components = instr.coord_components;
530 if (instr.is_array && !instr.array_is_lowered_cube)
531 --grad_components;
532
533
534 src.offset = nullptr;
535 bool retval = true;
536 for (unsigned i = 0; i < instr.num_srcs; ++i) {
537 switch (instr.src[i].src_type) {
538 case nir_tex_src_bias:
539 src.bias = from_nir(instr.src[i], 0);
540 break;
541
542 case nir_tex_src_coord: {
543 src.coord = vec_from_nir_with_fetch_constant(instr.src[i].src,
544 (1 << instr.coord_components) - 1,
545 {0,1,2,3});
546 } break;
547 case nir_tex_src_comparator:
548 src.comperator = from_nir(instr.src[i], 0);
549 break;
550 case nir_tex_src_ddx: {
551 sfn_log << SfnLog::tex << "Get DDX ";
552 src.ddx = vec_from_nir_with_fetch_constant(instr.src[i].src,
553 (1 << grad_components) - 1,
554 swizzle_from_comps(grad_components));
555 sfn_log << SfnLog::tex << src.ddx << "\n";
556 } break;
557 case nir_tex_src_ddy:{
558 sfn_log << SfnLog::tex << "Get DDY ";
559 src.ddy = vec_from_nir_with_fetch_constant(instr.src[i].src,
560 (1 << grad_components) - 1,
561 swizzle_from_comps(grad_components));
562 sfn_log << SfnLog::tex << src.ddy << "\n";
563 } break;
564 case nir_tex_src_lod:
565 src.lod = from_nir_with_fetch_constant(instr.src[i].src, 0);
566 break;
567 case nir_tex_src_offset:
568 sfn_log << SfnLog::tex << " -- Find offset\n";
569 src.offset = &instr.src[i].src;
570 break;
571 case nir_tex_src_sampler_deref:
572 src.sampler_deref = get_deref_location(instr.src[i].src);
573 break;
574 case nir_tex_src_texture_deref:
575 src.texture_deref = get_deref_location(instr.src[i].src);
576 break;
577 case nir_tex_src_ms_index:
578 src.ms_index = from_nir(instr.src[i], 0);
579 break;
580 case nir_tex_src_texture_offset:
581 src.texture_offset = from_nir(instr.src[i], 0);
582 break;
583 case nir_tex_src_sampler_offset:
584 src.sampler_offset = from_nir(instr.src[i], 0);
585 break;
586 case nir_tex_src_plane:
587 case nir_tex_src_projector:
588 case nir_tex_src_min_lod:
589 default:
590 sfn_log << SfnLog::tex << "Texture source type " << instr.src[i].src_type << " not supported\n";
591 retval = false;
592 }
593 }
594 return retval;
595 }
596
make_dest(nir_tex_instr & instr)597 GPRVector EmitTexInstruction::make_dest(nir_tex_instr& instr)
598 {
599 int num_dest_components = instr.dest.is_ssa ? instr.dest.ssa.num_components :
600 instr.dest.reg.reg->num_components;
601 std::array<PValue,4> dst_elms;
602 for (uint16_t i = 0; i < 4; ++i)
603 dst_elms[i] = from_nir(instr.dest, (i < num_dest_components) ? i : 7);
604 return GPRVector(dst_elms);
605 }
606
607
make_dest(nir_tex_instr & instr,const std::array<int,4> & swizzle)608 GPRVector EmitTexInstruction::make_dest(nir_tex_instr& instr,
609 const std::array<int, 4>& swizzle)
610 {
611 int num_dest_components = instr.dest.is_ssa ? instr.dest.ssa.num_components :
612 instr.dest.reg.reg->num_components;
613 std::array<PValue,4> dst_elms;
614 for (uint16_t i = 0; i < 4; ++i) {
615 int k = swizzle[i];
616 dst_elms[i] = from_nir(instr.dest, (k < num_dest_components) ? k : 7);
617 }
618 return GPRVector(dst_elms);
619 }
620
set_rect_coordinate_flags(nir_tex_instr * instr,TexInstruction * ir) const621 void EmitTexInstruction::set_rect_coordinate_flags(nir_tex_instr* instr,
622 TexInstruction* ir) const
623 {
624 if (instr->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
625 ir->set_flag(TexInstruction::x_unnormalized);
626 ir->set_flag(TexInstruction::y_unnormalized);
627 }
628 }
629
set_offsets(TexInstruction * ir,nir_src * offset)630 void EmitTexInstruction::set_offsets(TexInstruction* ir, nir_src *offset)
631 {
632 if (!offset)
633 return;
634
635 assert(offset->is_ssa);
636 auto literal = nir_src_as_const_value(*offset);
637 assert(literal);
638
639 for (int i = 0; i < offset->ssa->num_components; ++i) {
640 ir->set_offset(i, literal[i].i32);
641 }
642 }
643
handle_array_index(const nir_tex_instr & instr,const GPRVector & src,TexInstruction * ir)644 void EmitTexInstruction::handle_array_index(const nir_tex_instr& instr, const GPRVector& src, TexInstruction *ir)
645 {
646 int src_idx = instr.sampler_dim == GLSL_SAMPLER_DIM_1D ? 1 : 2;
647 emit_instruction(new AluInstruction(op1_rndne, src.reg_i(2), src.reg_i(src_idx),
648 {alu_last_instr, alu_write}));
649 ir->set_flag(TexInstruction::z_unnormalized);
650 }
651
652 EmitTexInstruction::SamplerId
get_sampler_id(int sampler_id,const nir_variable * deref)653 EmitTexInstruction::get_sampler_id(int sampler_id, const nir_variable *deref)
654 {
655 EmitTexInstruction::SamplerId result = {sampler_id, false};
656
657 if (deref) {
658 assert(glsl_type_is_sampler(deref->type));
659 result.id = deref->data.binding;
660 }
661 return result;
662 }
663
TexInputs()664 EmitTexInstruction::TexInputs::TexInputs():
665 sampler_deref(nullptr),
666 texture_deref(nullptr),
667 offset(nullptr)
668 {
669 }
670
671 }
672