"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/r600/sfn/sfn_emittexinstruction.cpp" (16 Sep 2020, 33586 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sfn_emittexinstruction.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20.1.5_vs_20.2.0-rc1.

    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          std::unique_ptr<GPRVector> ofs(vec_from_nir_with_fetch_constant(*src.offset,
  662                                                                          ( 1 << instr->coord_components) -1,
  663                                                                          swizzle));
  664          GPRVector dummy(0, {7,7,7,7});
  665          tex_op = (tex_op == TexInstruction::gather4_c) ?
  666                      TexInstruction::gather4_c_o : TexInstruction::gather4_o;
  667 
  668          auto set_ofs = new TexInstruction(TexInstruction::set_offsets, dummy,
  669                                            *ofs, sampler.id,
  670                                            sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
  671          set_ofs->set_dest_swizzle({7,7,7,7});
  672          emit_instruction(set_ofs);
  673       }
  674    }
  675 
  676 
  677    /* pre CAYMAN needs swizzle */
  678    auto dst = make_dest(*instr);
  679    auto irt = new TexInstruction(tex_op, dst, src.coord, sampler.id,
  680                                  sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
  681 
  682    irt->set_dest_swizzle({1,2,0,3});
  683    irt->set_gather_comp(instr->component);
  684 
  685    if (instr->is_array)
  686       handle_array_index(*instr, src.coord, irt);
  687 
  688    if (literal_offset) {
  689       r600::sfn_log << SfnLog::tex << "emit literal offsets\n";
  690       set_offsets(irt, src.offset);
  691    }
  692 
  693    set_rect_coordinate_flags(instr, irt);
  694 
  695    emit_instruction(irt);
  696    return true;
  697 }
  698 
  699 bool EmitTexInstruction::emit_cube_tg4(nir_tex_instr* instr, TexInputs& tex_src)
  700 {
  701    std::array<PValue, 4> v;
  702    for (int i = 0; i < 4; ++i)
  703       v[i] = from_nir(instr->dest, i);
  704 
  705    auto tex_op = TexInstruction::gather4;
  706    GPRVector cubed(v);
  707    emit_cube_prep(tex_src.coord, cubed, instr->is_array);
  708 
  709    std::array<PValue,4> dst_elms;
  710    std::array<PValue,4> src_elms;
  711 
  712    const uint16_t lookup[4] = {1, 0, 3, 2};
  713    for (uint16_t i = 0; i < 4; ++i) {
  714       dst_elms[i] = v[i];
  715       src_elms[i] = v[lookup[i]];
  716    }
  717 
  718    if (instr->is_shadow)  {
  719       emit_instruction(new AluInstruction(op1_mov, src_elms[3], tex_src.comperator,
  720                        {alu_last_instr, alu_write}));
  721       tex_op = TexInstruction::gather4_c;
  722    }
  723 
  724    GPRVector dst(dst_elms);
  725    GPRVector src(src_elms);
  726 
  727    auto sampler = get_samplerr_id(instr->sampler_index, tex_src.sampler_deref);
  728    assert(!sampler.indirect && "Indirect sampler selection not yet supported");
  729 
  730    auto tir = new TexInstruction(tex_op, dst, src, sampler.id,
  731                                  sampler.id + R600_MAX_CONST_BUFFERS, tex_src.sampler_offset);
  732 
  733    tir->set_gather_comp(instr->component);
  734 
  735    tir->set_dest_swizzle({1, 2, 0, 3});
  736 
  737    if (instr->is_array)
  738       tir->set_flag(TexInstruction::z_unnormalized);
  739 
  740    emit_instruction(tir);
  741    return true;
  742 }
  743 
  744 bool EmitTexInstruction::emit_tex_txf_ms(nir_tex_instr* instr, TexInputs& src)
  745 {
  746    assert(instr->src[0].src.is_ssa);
  747 
  748    r600::sfn_log << SfnLog::instr << "emit '"
  749                  << *reinterpret_cast<nir_instr*>(instr)
  750                  << "' (" << __func__ << ")\n";
  751 
  752    auto sampler = get_samplerr_id(instr->sampler_index, src.sampler_deref);
  753    assert(!sampler.indirect && "Indirect sampler selection not yet supported");
  754 
  755    int sample_id = allocate_temp_register();
  756 
  757    GPRVector sample_id_dest(sample_id, {0,7,7,7});
  758    PValue help(new GPRValue(sample_id, 1));
  759 
  760    /* FIXME: Texture destination registers must be handled differently,
  761     * because the swizzle identfies which source componnet has to be written
  762     * at a certain position, and the target register is actually different.
  763     * At this point we just add a helper register, but for later work (scheduling
  764     * and optimization on the r600 IR level, this needs to be implemented
  765     * differently */
  766 
  767 
  768    emit_instruction(new AluInstruction(op1_mov, src.coord.reg_i(3),
  769                                        src.ms_index,
  770                                        {alu_write, alu_last_instr}));
  771 
  772    auto tex_sample_id_ir = new TexInstruction(TexInstruction::ld, sample_id_dest, src.coord,
  773                                               sampler.id,
  774                                               sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
  775    tex_sample_id_ir->set_flag(TexInstruction::x_unnormalized);
  776    tex_sample_id_ir->set_flag(TexInstruction::y_unnormalized);
  777    tex_sample_id_ir->set_flag(TexInstruction::z_unnormalized);
  778    tex_sample_id_ir->set_flag(TexInstruction::w_unnormalized);
  779    tex_sample_id_ir->set_inst_mode(1);
  780 
  781    emit_instruction(tex_sample_id_ir);
  782 
  783    emit_instruction(new AluInstruction(op2_mullo_int, help,
  784                                        {src.ms_index, PValue(new LiteralValue(4))},
  785                                        {alu_write, alu_last_instr}));
  786 
  787    emit_instruction(new AluInstruction(op2_lshr_int, src.coord.reg_i(3),
  788                                        {sample_id_dest.reg_i(0), help},
  789                                        {alu_write, alu_last_instr}));
  790 
  791    emit_instruction(new AluInstruction(op2_and_int, src.coord.reg_i(3),
  792                                        {src.coord.reg_i(3), PValue(new LiteralValue(15))},
  793                                        {alu_write, alu_last_instr}));
  794 
  795    auto dst = make_dest(*instr);
  796 
  797    /* txf doesn't need rounding for the array index, but 1D has the array index
  798     * in the z component */
  799    if (instr->is_array && instr->sampler_dim == GLSL_SAMPLER_DIM_1D)
  800       src.coord.set_reg_i(2, src.coord.reg_i(1));
  801 
  802    auto tex_ir = new TexInstruction(TexInstruction::ld, dst, src.coord,
  803                                     sampler.id,
  804                                     sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
  805 
  806 
  807    if (src.offset) {
  808       assert(src.offset->is_ssa);
  809       AluInstruction *ir = nullptr;
  810       for (unsigned i = 0; i < src.offset->ssa->num_components; ++i) {
  811          ir = new AluInstruction(op2_add_int, src.coord.reg_i(i),
  812                   {src.coord.reg_i(i), from_nir(*src.offset, i, i)}, {alu_write});
  813          emit_instruction(ir);
  814       }
  815       if (ir)
  816          ir->set_flag(alu_last_instr);
  817    }
  818 
  819    emit_instruction(tex_ir);
  820    return true;
  821 }
  822 
  823 bool EmitTexInstruction::get_inputs(const nir_tex_instr& instr, TexInputs &src)
  824 {
  825    sfn_log << SfnLog::tex << "Get Inputs with " << instr.coord_components << " components\n";
  826 
  827    unsigned grad_components = instr.coord_components;
  828    if (instr.is_array)
  829       --grad_components;
  830 
  831 
  832    src.offset = nullptr;
  833    bool retval = true;
  834    for (unsigned i = 0; i < instr.num_srcs; ++i) {
  835       switch (instr.src[i].src_type) {
  836       case nir_tex_src_bias:
  837          src.bias = from_nir(instr.src[i], 0);
  838          break;
  839 
  840       case nir_tex_src_coord: {
  841          std::unique_ptr<GPRVector> coord(vec_from_nir_with_fetch_constant(instr.src[i].src,
  842                                                                            (1 << instr.coord_components) - 1,
  843                                                                            {0,1,2,3}));
  844          src.coord = *coord;
  845 
  846       } break;
  847       case nir_tex_src_comparator:
  848          src.comperator = from_nir(instr.src[i], 0);
  849          break;
  850       case nir_tex_src_ddx: {
  851          sfn_log << SfnLog::tex << "Get DDX ";
  852          std::unique_ptr<GPRVector> coord(vec_from_nir_with_fetch_constant(instr.src[i].src,
  853                                                                            (1 << grad_components) - 1,
  854                                                                            swizzle_from_mask(grad_components)));
  855          src.ddx = *coord;
  856          sfn_log << SfnLog::tex << src.ddx << "\n";
  857       } break;
  858       case nir_tex_src_ddy:{
  859          sfn_log << SfnLog::tex << "Get DDY ";
  860          std::unique_ptr<GPRVector> coord(vec_from_nir_with_fetch_constant(instr.src[i].src,
  861                                                                            (1 << grad_components) - 1,
  862                                                                            swizzle_from_mask(grad_components)));
  863          src.ddy = *coord;
  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 }