Home | History | Annotate | Line # | Download | only in compiler
      1 /*
      2  * Copyright  Microsoft Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     22  */
     23 
     24 #include "dxil_nir_lower_int_samplers.h"
     25 #include "nir_builder.h"
     26 #include "nir_builtin_builder.h"
     27 
     28 static bool
     29 lower_sample_to_txf_for_integer_tex_filter(const nir_instr *instr,
     30                                            UNUSED const void *_options)
     31 {
     32    if (instr->type != nir_instr_type_tex)
     33       return false;
     34 
     35    nir_tex_instr *tex = nir_instr_as_tex(instr);
     36    if (tex->op != nir_texop_tex &&
     37        tex->op != nir_texop_txb &&
     38        tex->op != nir_texop_txl &&
     39        tex->op != nir_texop_txd)
     40       return false;
     41 
     42    return (tex->dest_type & (nir_type_int | nir_type_uint));
     43 }
     44 
     45 static nir_ssa_def *
     46 dx_get_texture_lod(nir_builder *b, nir_tex_instr *tex)
     47 {
     48    nir_tex_instr *tql;
     49 
     50    unsigned num_srcs = 0;
     51    for (unsigned i = 0; i < tex->num_srcs; i++) {
     52       if (tex->src[i].src_type == nir_tex_src_coord ||
     53           tex->src[i].src_type == nir_tex_src_texture_deref ||
     54           tex->src[i].src_type == nir_tex_src_sampler_deref ||
     55           tex->src[i].src_type == nir_tex_src_texture_offset ||
     56           tex->src[i].src_type == nir_tex_src_sampler_offset ||
     57           tex->src[i].src_type == nir_tex_src_texture_handle ||
     58           tex->src[i].src_type == nir_tex_src_sampler_handle)
     59          num_srcs++;
     60    }
     61 
     62    tql = nir_tex_instr_create(b->shader, num_srcs);
     63    tql->op = nir_texop_lod;
     64    unsigned coord_components = tex->coord_components;
     65    if (tex->is_array)
     66       --coord_components;
     67 
     68    tql->coord_components = coord_components;
     69    tql->sampler_dim = tex->sampler_dim;
     70    tql->is_shadow = tex->is_shadow;
     71    tql->is_new_style_shadow = tex->is_new_style_shadow;
     72    tql->texture_index = tex->texture_index;
     73    tql->sampler_index = tex->sampler_index;
     74    tql->dest_type = nir_type_float32;
     75 
     76    /* The coordinate needs special handling because we might have
     77     * to strip the array index. Don't clutter the code  with an additional
     78     * check for is_array though, in the worst case we create an additional
     79     * move the the optimization will remove later again. */
     80    int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
     81    nir_ssa_def *ssa_src = nir_channels(b, tex->src[coord_index].src.ssa,
     82                                        (1 << coord_components) - 1);
     83    nir_src src = nir_src_for_ssa(ssa_src);
     84    nir_src_copy(&tql->src[0].src, &src);
     85    tql->src[0].src_type = nir_tex_src_coord;
     86 
     87    unsigned idx = 1;
     88    for (unsigned i = 0; i < tex->num_srcs; i++) {
     89       if (tex->src[i].src_type == nir_tex_src_texture_deref ||
     90           tex->src[i].src_type == nir_tex_src_sampler_deref ||
     91           tex->src[i].src_type == nir_tex_src_texture_offset ||
     92           tex->src[i].src_type == nir_tex_src_sampler_offset ||
     93           tex->src[i].src_type == nir_tex_src_texture_handle ||
     94           tex->src[i].src_type == nir_tex_src_sampler_handle) {
     95          nir_src_copy(&tql->src[idx].src, &tex->src[i].src);
     96          tql->src[idx].src_type = tex->src[i].src_type;
     97          idx++;
     98       }
     99    }
    100 
    101    nir_ssa_dest_init(&tql->instr, &tql->dest, 2, 32, NULL);
    102    nir_builder_instr_insert(b, &tql->instr);
    103 
    104    /* DirectX LOD only has a value in x channel */
    105    return nir_channel(b, &tql->dest.ssa, 0);
    106 }
    107 
    108 typedef struct {
    109    nir_ssa_def *coords;
    110    nir_ssa_def *use_border_color;
    111 } wrap_result_t;
    112 
    113 typedef struct {
    114    nir_ssa_def *lod;
    115    nir_ssa_def *size;
    116    int ncoord_comp;
    117    wrap_result_t wrap[3];
    118 } wrap_lower_param_t;
    119 
    120 static void
    121 wrap_clamp_to_edge(nir_builder *b, wrap_result_t *wrap_params, nir_ssa_def *size)
    122 {
    123    /* clamp(coord, 0, size - 1) */
    124    wrap_params->coords = nir_fmin(b, nir_fsub(b, size, nir_imm_float(b, 1.0f)),
    125                                   nir_fmax(b, wrap_params->coords, nir_imm_float(b, 0.0f)));
    126 }
    127 
    128 static void
    129 wrap_repeat(nir_builder *b, wrap_result_t *wrap_params, nir_ssa_def *size)
    130 {
    131    /* mod(coord, size)
    132     * This instruction must be exact, otherwise certain sizes result in
    133     * incorrect sampling */
    134    wrap_params->coords = nir_fmod(b, wrap_params->coords, size);
    135    nir_instr_as_alu(wrap_params->coords->parent_instr)->exact = true;
    136 }
    137 
    138 static nir_ssa_def *
    139 mirror(nir_builder *b, nir_ssa_def *coord)
    140 {
    141    /* coord if >= 0, otherwise -(1 + coord) */
    142    return nir_bcsel(b, nir_fge(b, coord, nir_imm_float(b, 0.0f)), coord,
    143                     nir_fneg(b, nir_fadd(b, nir_imm_float(b, 1.0f), coord)));
    144 }
    145 
    146 static void
    147 wrap_mirror_repeat(nir_builder *b, wrap_result_t *wrap_params, nir_ssa_def *size)
    148 {
    149    /* (size  1)  mirror(mod(coord, 2 * size)  size) */
    150    nir_ssa_def *coord_mod2size = nir_fmod(b, wrap_params->coords, nir_fmul(b, nir_imm_float(b, 2.0f), size));
    151    nir_instr_as_alu(coord_mod2size->parent_instr)->exact = true;
    152    nir_ssa_def *a = nir_fsub(b, coord_mod2size, size);
    153    wrap_params->coords = nir_fsub(b, nir_fsub(b, size, nir_imm_float(b, 1.0f)), mirror(b, a));
    154 }
    155 
    156 static void
    157 wrap_mirror_clamp_to_edge(nir_builder *b, wrap_result_t *wrap_params, nir_ssa_def *size)
    158 {
    159    /* clamp(mirror(coord), 0, size - 1) */
    160    wrap_params->coords = nir_fmin(b, nir_fsub(b, size, nir_imm_float(b, 1.0f)),
    161                                   nir_fmax(b, mirror(b, wrap_params->coords), nir_imm_float(b, 0.0f)));
    162 }
    163 
    164 static void
    165 wrap_clamp(nir_builder *b, wrap_result_t *wrap_params, nir_ssa_def *size)
    166 {
    167    nir_ssa_def *is_low = nir_flt(b, wrap_params->coords, nir_imm_float(b, 0.0));
    168    nir_ssa_def *is_high = nir_fge(b, wrap_params->coords, size);
    169    wrap_params->use_border_color = nir_ior(b, is_low, is_high);
    170 }
    171 
    172 static void
    173 wrap_mirror_clamp(nir_builder *b, wrap_result_t *wrap_params, nir_ssa_def *size)
    174 {
    175    /* We have to take care of the boundaries */
    176    nir_ssa_def *is_low = nir_flt(b, wrap_params->coords, nir_fmul(b, size, nir_imm_float(b, -1.0)));
    177    nir_ssa_def *is_high = nir_flt(b, nir_fmul(b, size, nir_imm_float(b, 2.0)), wrap_params->coords);
    178    wrap_params->use_border_color = nir_ior(b, is_low, is_high);
    179 
    180    /* Within the boundaries this acts like mirror_repeat */
    181    wrap_mirror_repeat(b, wrap_params, size);
    182 
    183 }
    184 
    185 static wrap_result_t
    186 wrap_coords(nir_builder *b, nir_ssa_def *coords, enum pipe_tex_wrap wrap,
    187             nir_ssa_def *size)
    188 {
    189    wrap_result_t result = {coords, nir_imm_false(b)};
    190 
    191    switch (wrap) {
    192    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
    193       wrap_clamp_to_edge(b, &result, size);
    194       break;
    195    case PIPE_TEX_WRAP_REPEAT:
    196       wrap_repeat(b, &result, size);
    197       break;
    198    case PIPE_TEX_WRAP_MIRROR_REPEAT:
    199       wrap_mirror_repeat(b, &result, size);
    200       break;
    201    case PIPE_TEX_WRAP_MIRROR_CLAMP:
    202    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
    203       wrap_mirror_clamp_to_edge(b, &result, size);
    204       break;
    205    case PIPE_TEX_WRAP_CLAMP:
    206    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
    207       wrap_clamp(b, &result, size);
    208       break;
    209    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
    210       wrap_mirror_clamp(b, &result, size);
    211       break;
    212    }
    213    return result;
    214 }
    215 
    216 static nir_ssa_def *
    217 load_bordercolor(nir_builder *b, nir_tex_instr *tex, dxil_wrap_sampler_state *active_state,
    218                  const dxil_texture_swizzle_state *tex_swizzle)
    219 {
    220    nir_const_value const_value[4] = {{0}};
    221    int ndest_comp = nir_dest_num_components(tex->dest);
    222 
    223    unsigned swizzle[4] = {
    224       tex_swizzle->swizzle_r,
    225       tex_swizzle->swizzle_g,
    226       tex_swizzle->swizzle_b,
    227       tex_swizzle->swizzle_a
    228    };
    229 
    230    for (int i = 0; i < ndest_comp; ++i) {
    231       switch (swizzle[i]) {
    232       case PIPE_SWIZZLE_0:
    233          const_value[i].f32 = 0;
    234          break;
    235       case PIPE_SWIZZLE_1:
    236          const_value[i].i32 = 1;
    237          break;
    238       case PIPE_SWIZZLE_X:
    239       case PIPE_SWIZZLE_Y:
    240       case PIPE_SWIZZLE_Z:
    241       case PIPE_SWIZZLE_W:
    242          const_value[i].f32 = active_state->border_color[swizzle[i]];
    243          break;
    244       default:
    245          unreachable("Unexpected swizzle value");
    246       }
    247    }
    248 
    249    return nir_build_imm(b, ndest_comp, 32, const_value);
    250 }
    251 
    252 static nir_tex_instr *
    253 create_txf_from_tex(nir_builder *b, nir_tex_instr *tex)
    254 {
    255    nir_tex_instr *txf;
    256 
    257    unsigned num_srcs = 0;
    258    for (unsigned i = 0; i < tex->num_srcs; i++) {
    259       if (tex->src[i].src_type == nir_tex_src_texture_deref ||
    260           tex->src[i].src_type == nir_tex_src_texture_offset ||
    261           tex->src[i].src_type == nir_tex_src_texture_handle)
    262          num_srcs++;
    263    }
    264 
    265    txf = nir_tex_instr_create(b->shader, num_srcs);
    266    txf->op = nir_texop_txf;
    267    txf->coord_components = tex->coord_components;
    268    txf->sampler_dim = tex->sampler_dim;
    269    txf->is_array = tex->is_array;
    270    txf->is_shadow = tex->is_shadow;
    271    txf->is_new_style_shadow = tex->is_new_style_shadow;
    272    txf->texture_index = tex->texture_index;
    273    txf->sampler_index = tex->sampler_index;
    274    txf->dest_type = tex->dest_type;
    275 
    276    unsigned idx = 0;
    277    for (unsigned i = 0; i < tex->num_srcs; i++) {
    278       if (tex->src[i].src_type == nir_tex_src_texture_deref ||
    279           tex->src[i].src_type == nir_tex_src_texture_offset ||
    280           tex->src[i].src_type == nir_tex_src_texture_handle) {
    281          nir_src_copy(&txf->src[idx].src, &tex->src[i].src);
    282          txf->src[idx].src_type = tex->src[i].src_type;
    283          idx++;
    284       }
    285    }
    286 
    287    nir_ssa_dest_init(&txf->instr, &txf->dest,
    288                      nir_tex_instr_dest_size(txf), 32, NULL);
    289    nir_builder_instr_insert(b, &txf->instr);
    290 
    291    return txf;
    292 }
    293 
    294 static nir_ssa_def *
    295 load_texel(nir_builder *b, nir_tex_instr *tex, wrap_lower_param_t *params)
    296 {
    297    nir_ssa_def *texcoord = NULL;
    298 
    299    /* Put coordinates back together */
    300    switch (tex->coord_components) {
    301    case 1:
    302       texcoord = params->wrap[0].coords;
    303       break;
    304    case 2:
    305       texcoord = nir_vec2(b, params->wrap[0].coords, params->wrap[1].coords);
    306       break;
    307    case 3:
    308       texcoord = nir_vec3(b, params->wrap[0].coords, params->wrap[1].coords, params->wrap[2].coords);
    309       break;
    310    default:
    311       ;
    312    }
    313 
    314    texcoord = nir_f2i32(b, texcoord);
    315 
    316    nir_tex_instr *load = create_txf_from_tex(b, tex);
    317    nir_tex_instr_add_src(load, nir_tex_src_lod, nir_src_for_ssa(params->lod));
    318    nir_tex_instr_add_src(load, nir_tex_src_coord, nir_src_for_ssa(texcoord));
    319    b->cursor = nir_after_instr(&load->instr);
    320    return &load->dest.ssa;
    321 }
    322 
    323 typedef struct {
    324    dxil_wrap_sampler_state *aws;
    325    float max_bias;
    326    nir_ssa_def *size;
    327    int ncoord_comp;
    328 } lod_params;
    329 
    330 static nir_ssa_def *
    331 evalute_active_lod(nir_builder *b, nir_tex_instr *tex, lod_params *params)
    332 {
    333    static nir_ssa_def *lod = NULL;
    334 
    335    /* Later we use min_lod for clamping the LOD to a legal value */
    336    float min_lod = MAX2(params->aws->min_lod, 0.0f);
    337 
    338    /* Evaluate the LOD to be used for the texel fetch */
    339    if (unlikely(tex->op == nir_texop_txl)) {
    340       int lod_index = nir_tex_instr_src_index(tex, nir_tex_src_lod);
    341       /* if we have an explicite LOD, take it */
    342       lod = tex->src[lod_index].src.ssa;
    343    } else if (unlikely(tex->op == nir_texop_txd)) {
    344       int ddx_index = nir_tex_instr_src_index(tex, nir_tex_src_ddx);
    345       int ddy_index = nir_tex_instr_src_index(tex, nir_tex_src_ddy);
    346       assert(ddx_index >= 0 && ddy_index >= 0);
    347 
    348       nir_ssa_def *grad = nir_fmax(b,
    349                                    tex->src[ddx_index].src.ssa,
    350                                    tex->src[ddy_index].src.ssa);
    351 
    352       nir_ssa_def *r = nir_fmul(b, grad, nir_i2f32(b, params->size));
    353       nir_ssa_def *rho = nir_channel(b, r, 0);
    354       for (int i = 1; i < params->ncoord_comp; ++i)
    355          rho = nir_fmax(b, rho, nir_channel(b, r, i));
    356       lod = nir_flog2(b, rho);
    357    } else if (b->shader->info.stage == MESA_SHADER_FRAGMENT){
    358       lod = dx_get_texture_lod(b, tex);
    359    } else {
    360       /* Only fragment shaders provide the gradient information to evaluate a LOD,
    361        * so force 0 otherwise */
    362       lod = nir_imm_float(b, 0.0);
    363    }
    364 
    365    /* Evaluate bias according to OpenGL (4.6 (Compatibility  Profile) October 22, 2019),
    366     * sec. 8.14.1, eq. (8.9)
    367     *
    368     *    lod' = lambda + CLAMP(bias_texobj + bias_texunit + bias_shader)
    369     *
    370     * bias_texobj is the value of TEXTURE_LOD_BIAS for the bound texture object. ...
    371     * bias_textunt is the value of TEXTURE_LOD_BIAS for the current texture unit, ...
    372     * bias shader is the value of the optional bias parameter in the texture
    373     * lookup functions available to fragment shaders. ... The sum of these values
    374     * is clamped to the range [bias_max, bias_max] where bias_max is the value
    375     * of the implementation defined constant MAX_TEXTURE_LOD_BIAS.
    376     * In core contexts the value bias_texunit is dropped from above equation.
    377     *
    378     * Gallium provides the value lod_bias as the sum of bias_texobj and bias_texunit
    379     * in compatibility contexts and as bias_texobj in core contexts, hence the
    380     * implementation here is the same in both cases.
    381     */
    382    nir_ssa_def *lod_bias = nir_imm_float(b, params->aws->lod_bias);
    383 
    384    if (unlikely(tex->op == nir_texop_txb)) {
    385       int bias_index = nir_tex_instr_src_index(tex, nir_tex_src_bias);
    386       lod_bias = nir_fadd(b, lod_bias, tex->src[bias_index].src.ssa);
    387    }
    388 
    389    lod = nir_fadd(b, lod, nir_fclamp(b, lod_bias,
    390                                      nir_imm_float(b, -params->max_bias),
    391                                      nir_imm_float(b, params->max_bias)));
    392 
    393    /* Clamp lod according to ibid. eq. (8.10) */
    394    lod = nir_fmax(b, lod, nir_imm_float(b, min_lod));
    395 
    396    /* If the max lod is > max_bias = log2(max_texture_size), the lod will be clamped
    397     * by the number of levels, no need to clamp it againt the max_lod first. */
    398    if (params->aws->max_lod <= params->max_bias)
    399       lod = nir_fmin(b, lod, nir_imm_float(b, params->aws->max_lod));
    400 
    401    /* Pick nearest LOD */
    402    lod = nir_f2i32(b, nir_fround_even(b, lod));
    403 
    404    /* cap actual lod by number of available levels */
    405    return nir_imin(b, lod, nir_imm_int(b, params->aws->last_level));
    406 }
    407 
    408 typedef struct {
    409    dxil_wrap_sampler_state *wrap_states;
    410    dxil_texture_swizzle_state *tex_swizzles;
    411    float max_bias;
    412 } sampler_states;
    413 
    414 
    415 static nir_ssa_def *
    416 lower_sample_to_txf_for_integer_tex_impl(nir_builder *b, nir_instr *instr,
    417                                          void *options)
    418 {
    419    sampler_states *states = (sampler_states *)options;
    420    wrap_lower_param_t params = {0};
    421 
    422    nir_tex_instr *tex = nir_instr_as_tex(instr);
    423    dxil_wrap_sampler_state *active_wrap_state = &states->wrap_states[tex->sampler_index];
    424 
    425    b->cursor = nir_before_instr(instr);
    426 
    427    int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
    428    nir_ssa_def *old_coord = tex->src[coord_index].src.ssa;
    429    params.ncoord_comp = tex->coord_components;
    430    if (tex->is_array)
    431       params.ncoord_comp -= 1;
    432 
    433    /* This helper to get the texture size always uses LOD 0, and DirectX doesn't support
    434     * giving another LOD when querying the texture size */
    435    nir_ssa_def *size0 = nir_get_texture_size(b, tex);
    436 
    437    params.lod = nir_imm_int(b, 0);
    438 
    439    if (active_wrap_state->last_level > 0) {
    440       lod_params p = {
    441          .aws = active_wrap_state,
    442          .max_bias = states->max_bias,
    443          .size = size0,
    444          .ncoord_comp = params.ncoord_comp
    445       };
    446       params.lod = evalute_active_lod(b, tex, &p);
    447 
    448       /* Evaluate actual level size*/
    449       params.size = nir_i2f32(b, nir_imax(b, nir_ishr(b, size0, params.lod),
    450                                              nir_imm_int(b, 1)));
    451    } else {
    452       params.size = nir_i2f32(b, size0);
    453    }
    454 
    455    nir_ssa_def *new_coord = old_coord;
    456    if (!active_wrap_state->is_nonnormalized_coords) {
    457       /* Evaluate the integer lookup coordinates for the requested LOD, don't touch the
    458        * array index */
    459       if (!tex->is_array) {
    460          new_coord = nir_fmul(b, params.size, old_coord);
    461       } else {
    462          nir_ssa_def *array_index = nir_channel(b, old_coord, params.ncoord_comp);
    463          int mask = (1 << params.ncoord_comp) - 1;
    464          nir_ssa_def *coord = nir_fmul(b, nir_channels(b, params.size, mask),
    465                                           nir_channels(b, old_coord, mask));
    466          switch (params.ncoord_comp) {
    467          case 1:
    468             new_coord = nir_vec2(b, coord, array_index);
    469             break;
    470          case 2:
    471             new_coord = nir_vec3(b, nir_channel(b, coord, 0),
    472                                     nir_channel(b, coord, 1),
    473                                     array_index);
    474             break;
    475          default:
    476             unreachable("unsupported number of non-array coordinates");
    477          }
    478       }
    479    }
    480 
    481    nir_ssa_def *coord_help[3];
    482    for (int i = 0; i < params.ncoord_comp; ++i)
    483       coord_help[i] = nir_ffloor(b, nir_channel(b, new_coord, i));
    484 
    485    // Note: array index needs to be rounded to nearest before clamp rather than floored
    486    if (tex->is_array)
    487       coord_help[params.ncoord_comp] = nir_fround_even(b, nir_channel(b, new_coord, params.ncoord_comp));
    488 
    489    /* Correct the texture coordinates for the offsets. */
    490    int offset_index = nir_tex_instr_src_index(tex, nir_tex_src_offset);
    491    if (offset_index >= 0) {
    492       nir_ssa_def *offset = tex->src[offset_index].src.ssa;
    493       for (int i = 0; i < params.ncoord_comp; ++i)
    494          coord_help[i] = nir_fadd(b, coord_help[i], nir_i2f32(b, nir_channel(b, offset, i)));
    495    }
    496 
    497    nir_ssa_def *use_border_color = nir_imm_false(b);
    498 
    499    if (!active_wrap_state->skip_boundary_conditions) {
    500 
    501       for (int i = 0; i < params.ncoord_comp; ++i) {
    502          params.wrap[i] = wrap_coords(b, coord_help[i], active_wrap_state->wrap[i], nir_channel(b, params.size, i));
    503          use_border_color = nir_ior(b, use_border_color, params.wrap[i].use_border_color);
    504       }
    505 
    506       if (tex->is_array)
    507          params.wrap[params.ncoord_comp] =
    508                wrap_coords(b, coord_help[params.ncoord_comp],
    509                            PIPE_TEX_WRAP_CLAMP_TO_EDGE,
    510                            nir_i2f32(b, nir_channel(b, size0, params.ncoord_comp)));
    511    } else {
    512       /* When we emulate a cube map by using a texture array, the coordinates are always
    513        * in range, and we don't have to take care of boundary conditions */
    514       for (unsigned i = 0; i < 3; ++i) {
    515          params.wrap[i].coords = coord_help[i];
    516          params.wrap[i].use_border_color = nir_imm_false(b);
    517       }
    518    }
    519 
    520    const dxil_texture_swizzle_state one2one = {
    521      PIPE_SWIZZLE_X,  PIPE_SWIZZLE_Y,  PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W
    522    };
    523 
    524    nir_if *border_if = nir_push_if(b, use_border_color);
    525    const dxil_texture_swizzle_state *swizzle = states->tex_swizzles ?
    526                                                  &states->tex_swizzles[tex->sampler_index]:
    527                                                  &one2one;
    528 
    529    nir_ssa_def *border_color = load_bordercolor(b, tex, active_wrap_state, swizzle);
    530    nir_if *border_else = nir_push_else(b, border_if);
    531    nir_ssa_def *sampler_color = load_texel(b, tex, &params);
    532    nir_pop_if(b, border_else);
    533 
    534    return nir_if_phi(b, border_color, sampler_color);
    535 }
    536 
    537 /* Sampling from integer textures is not allowed in DirectX, so we have
    538  * to use texel fetches. For this we have to scale the coordiantes
    539  * to be integer based, and evaluate the LOD the texel fetch has to be
    540  * applied on, and take care of the boundary conditions .
    541  */
    542 bool
    543 dxil_lower_sample_to_txf_for_integer_tex(nir_shader *s,
    544                                          dxil_wrap_sampler_state *wrap_states,
    545                                          dxil_texture_swizzle_state *tex_swizzles,
    546                                          float max_bias)
    547 {
    548    sampler_states states = {wrap_states, tex_swizzles, max_bias};
    549 
    550    bool result =
    551          nir_shader_lower_instructions(s,
    552                                        lower_sample_to_txf_for_integer_tex_filter,
    553                                        lower_sample_to_txf_for_integer_tex_impl,
    554                                        &states);
    555    return result;
    556 }
    557