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