Home | History | Annotate | Line # | Download | only in d3d12
      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 "d3d12_nir_passes.h"
     25 #include "d3d12_compiler.h"
     26 #include "nir_builder.h"
     27 #include "nir_builtin_builder.h"
     28 #include "nir_format_convert.h"
     29 #include "program/prog_instruction.h"
     30 #include "dxil_nir.h"
     31 
     32 /**
     33  * Lower Y Flip:
     34  *
     35  * We can't do a Y flip simply by negating the viewport height,
     36  * so we need to lower the flip into the NIR shader.
     37  */
     38 
     39 static nir_ssa_def *
     40 get_state_var(nir_builder *b,
     41               enum d3d12_state_var var_enum,
     42               const char *var_name,
     43               const struct glsl_type *var_type,
     44               nir_variable **out_var)
     45 {
     46    const gl_state_index16 tokens[STATE_LENGTH] = { STATE_INTERNAL_DRIVER, var_enum };
     47    if (*out_var == NULL) {
     48       nir_variable *var = nir_variable_create(b->shader,
     49                                               nir_var_uniform,
     50                                               var_type,
     51                                               var_name);
     52 
     53       var->num_state_slots = 1;
     54       var->state_slots = ralloc_array(var, nir_state_slot, 1);
     55       memcpy(var->state_slots[0].tokens, tokens,
     56              sizeof(var->state_slots[0].tokens));
     57       var->data.how_declared = nir_var_hidden;
     58       b->shader->num_uniforms++;
     59       *out_var = var;
     60    }
     61    return nir_load_var(b, *out_var);
     62 }
     63 
     64 static void
     65 lower_pos_write(nir_builder *b, struct nir_instr *instr, nir_variable **flip)
     66 {
     67    if (instr->type != nir_instr_type_intrinsic)
     68       return;
     69 
     70    nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
     71    if (intr->intrinsic != nir_intrinsic_store_deref)
     72       return;
     73 
     74    nir_variable *var = nir_intrinsic_get_var(intr, 0);
     75    if (var->data.mode != nir_var_shader_out ||
     76        var->data.location != VARYING_SLOT_POS)
     77       return;
     78 
     79    b->cursor = nir_before_instr(&intr->instr);
     80 
     81    nir_ssa_def *pos = nir_ssa_for_src(b, intr->src[1], 4);
     82    nir_ssa_def *flip_y = get_state_var(b, D3D12_STATE_VAR_Y_FLIP, "d3d12_FlipY",
     83                                        glsl_float_type(), flip);
     84    nir_ssa_def *def = nir_vec4(b,
     85                                nir_channel(b, pos, 0),
     86                                nir_fmul(b, nir_channel(b, pos, 1), flip_y),
     87                                nir_channel(b, pos, 2),
     88                                nir_channel(b, pos, 3));
     89    nir_instr_rewrite_src(&intr->instr, intr->src + 1, nir_src_for_ssa(def));
     90 }
     91 
     92 void
     93 d3d12_lower_yflip(nir_shader *nir)
     94 {
     95    nir_variable *flip = NULL;
     96 
     97    if (nir->info.stage != MESA_SHADER_VERTEX &&
     98        nir->info.stage != MESA_SHADER_GEOMETRY)
     99       return;
    100 
    101    nir_foreach_function(function, nir) {
    102       if (function->impl) {
    103          nir_builder b;
    104          nir_builder_init(&b, function->impl);
    105 
    106          nir_foreach_block(block, function->impl) {
    107             nir_foreach_instr_safe(instr, block) {
    108                lower_pos_write(&b, instr, &flip);
    109             }
    110          }
    111 
    112          nir_metadata_preserve(function->impl, nir_metadata_block_index |
    113                                                nir_metadata_dominance);
    114       }
    115    }
    116 }
    117 
    118 static void
    119 lower_load_face(nir_builder *b, struct nir_instr *instr, nir_variable *var)
    120 {
    121    if (instr->type != nir_instr_type_intrinsic)
    122       return;
    123 
    124    nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
    125    if (intr->intrinsic != nir_intrinsic_load_front_face)
    126       return;
    127 
    128    b->cursor = nir_before_instr(&intr->instr);
    129 
    130    nir_ssa_def *load = nir_load_var(b, var);
    131 
    132    nir_ssa_def_rewrite_uses(&intr->dest.ssa, load);
    133    nir_instr_remove(instr);
    134 }
    135 
    136 void
    137 d3d12_forward_front_face(nir_shader *nir)
    138 {
    139    assert(nir->info.stage == MESA_SHADER_FRAGMENT);
    140 
    141    nir_variable *var = nir_variable_create(nir, nir_var_shader_in,
    142                                            glsl_bool_type(),
    143                                            "gl_FrontFacing");
    144    var->data.location = VARYING_SLOT_VAR12;
    145    var->data.interpolation = INTERP_MODE_FLAT;
    146 
    147 
    148    nir_foreach_function(function, nir) {
    149       if (function->impl) {
    150          nir_builder b;
    151          nir_builder_init(&b, function->impl);
    152 
    153          nir_foreach_block(block, function->impl) {
    154             nir_foreach_instr_safe(instr, block) {
    155                lower_load_face(&b, instr, var);
    156             }
    157          }
    158 
    159          nir_metadata_preserve(function->impl, nir_metadata_block_index |
    160                                                nir_metadata_dominance);
    161       }
    162    }
    163 }
    164 
    165 static void
    166 lower_pos_read(nir_builder *b, struct nir_instr *instr,
    167                nir_variable **depth_transform_var)
    168 {
    169    if (instr->type != nir_instr_type_intrinsic)
    170       return;
    171 
    172    nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
    173    if (intr->intrinsic != nir_intrinsic_load_deref)
    174       return;
    175 
    176    nir_variable *var = nir_intrinsic_get_var(intr, 0);
    177    if (var->data.mode != nir_var_shader_in ||
    178        var->data.location != VARYING_SLOT_POS)
    179       return;
    180 
    181    b->cursor = nir_after_instr(instr);
    182 
    183    nir_ssa_def *pos = nir_instr_ssa_def(instr);
    184    nir_ssa_def *depth = nir_channel(b, pos, 2);
    185 
    186    assert(depth_transform_var);
    187    nir_ssa_def *depth_transform = get_state_var(b, D3D12_STATE_VAR_DEPTH_TRANSFORM,
    188                                                 "d3d12_DepthTransform",
    189                                                 glsl_vec_type(2),
    190                                                 depth_transform_var);
    191    depth = nir_fmad(b, depth, nir_channel(b, depth_transform, 0),
    192                               nir_channel(b, depth_transform, 1));
    193 
    194    pos = nir_vector_insert_imm(b, pos, depth, 2);
    195 
    196    assert(intr->dest.is_ssa);
    197    nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, pos,
    198                                   pos->parent_instr);
    199 }
    200 
    201 void
    202 d3d12_lower_depth_range(nir_shader *nir)
    203 {
    204    assert(nir->info.stage == MESA_SHADER_FRAGMENT);
    205    nir_variable *depth_transform = NULL;
    206    nir_foreach_function(function, nir) {
    207       if (function->impl) {
    208          nir_builder b;
    209          nir_builder_init(&b, function->impl);
    210 
    211          nir_foreach_block(block, function->impl) {
    212             nir_foreach_instr_safe(instr, block) {
    213                lower_pos_read(&b, instr, &depth_transform);
    214             }
    215          }
    216 
    217          nir_metadata_preserve(function->impl, nir_metadata_block_index |
    218                                                nir_metadata_dominance);
    219       }
    220    }
    221 }
    222 
    223 static bool
    224 is_color_output(nir_variable *var)
    225 {
    226    return (var->data.mode == nir_var_shader_out &&
    227            (var->data.location == FRAG_RESULT_COLOR ||
    228             var->data.location >= FRAG_RESULT_DATA0));
    229 }
    230 
    231 static void
    232 lower_uint_color_write(nir_builder *b, struct nir_instr *instr, bool is_signed)
    233 {
    234    const unsigned NUM_BITS = 8;
    235    const unsigned bits[4] = { NUM_BITS, NUM_BITS, NUM_BITS, NUM_BITS };
    236 
    237    if (instr->type != nir_instr_type_intrinsic)
    238       return;
    239 
    240    nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
    241    if (intr->intrinsic != nir_intrinsic_store_deref)
    242       return;
    243 
    244    nir_variable *var = nir_intrinsic_get_var(intr, 0);
    245    if (!is_color_output(var))
    246       return;
    247 
    248    b->cursor = nir_before_instr(&intr->instr);
    249 
    250    nir_ssa_def *col = nir_ssa_for_src(b, intr->src[1], intr->num_components);
    251    nir_ssa_def *def = is_signed ? nir_format_float_to_snorm(b, col, bits) :
    252                                   nir_format_float_to_unorm(b, col, bits);
    253    if (is_signed)
    254       def = nir_bcsel(b, nir_ilt(b, def, nir_imm_int(b, 0)),
    255                       nir_iadd(b, def, nir_imm_int(b, 1 << NUM_BITS)),
    256                       def);
    257    nir_instr_rewrite_src(&intr->instr, intr->src + 1, nir_src_for_ssa(def));
    258 }
    259 
    260 void
    261 d3d12_lower_uint_cast(nir_shader *nir, bool is_signed)
    262 {
    263    if (nir->info.stage != MESA_SHADER_FRAGMENT)
    264       return;
    265 
    266    nir_foreach_function(function, nir) {
    267       if (function->impl) {
    268          nir_builder b;
    269          nir_builder_init(&b, function->impl);
    270 
    271          nir_foreach_block(block, function->impl) {
    272             nir_foreach_instr_safe(instr, block) {
    273                lower_uint_color_write(&b, instr, is_signed);
    274             }
    275          }
    276 
    277          nir_metadata_preserve(function->impl, nir_metadata_block_index |
    278                                                nir_metadata_dominance);
    279       }
    280    }
    281 }
    282 
    283 static bool
    284 lower_load_first_vertex(nir_builder *b, nir_instr *instr, nir_variable **first_vertex)
    285 {
    286    if (instr->type != nir_instr_type_intrinsic)
    287       return false;
    288 
    289    nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
    290 
    291    if (intr->intrinsic != nir_intrinsic_load_first_vertex)
    292       return false;
    293 
    294    b->cursor = nir_before_instr(&intr->instr);
    295 
    296    nir_ssa_def *load = get_state_var(b, D3D12_STATE_VAR_FIRST_VERTEX, "d3d12_FirstVertex",
    297                                      glsl_uint_type(), first_vertex);
    298    nir_ssa_def_rewrite_uses(&intr->dest.ssa, load);
    299    nir_instr_remove(instr);
    300 
    301    return true;
    302 }
    303 
    304 bool
    305 d3d12_lower_load_first_vertex(struct nir_shader *nir)
    306 {
    307    nir_variable *first_vertex = NULL;
    308    bool progress = false;
    309 
    310    if (nir->info.stage != MESA_SHADER_VERTEX)
    311       return false;
    312 
    313    nir_foreach_function(function, nir) {
    314       if (function->impl) {
    315          nir_builder b;
    316          nir_builder_init(&b, function->impl);
    317 
    318          nir_foreach_block(block, function->impl) {
    319             nir_foreach_instr_safe(instr, block) {
    320                progress |= lower_load_first_vertex(&b, instr, &first_vertex);
    321             }
    322          }
    323 
    324          nir_metadata_preserve(function->impl, nir_metadata_block_index |
    325                                                nir_metadata_dominance);
    326       }
    327    }
    328    return progress;
    329 }
    330 
    331 static void
    332 invert_depth(nir_builder *b, struct nir_instr *instr)
    333 {
    334    if (instr->type != nir_instr_type_intrinsic)
    335       return;
    336 
    337    nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
    338    if (intr->intrinsic != nir_intrinsic_store_deref)
    339       return;
    340 
    341    nir_variable *var = nir_intrinsic_get_var(intr, 0);
    342    if (var->data.mode != nir_var_shader_out ||
    343        var->data.location != VARYING_SLOT_POS)
    344       return;
    345 
    346    b->cursor = nir_before_instr(&intr->instr);
    347 
    348    nir_ssa_def *pos = nir_ssa_for_src(b, intr->src[1], 4);
    349    nir_ssa_def *def = nir_vec4(b,
    350                                nir_channel(b, pos, 0),
    351                                nir_channel(b, pos, 1),
    352                                nir_fneg(b, nir_channel(b, pos, 2)),
    353                                nir_channel(b, pos, 3));
    354    nir_instr_rewrite_src(&intr->instr, intr->src + 1, nir_src_for_ssa(def));
    355 }
    356 
    357 /* In OpenGL the windows space depth value z_w is evaluated according to "s * z_d + b"
    358  * with  "s + (far - near) / 2" (depth clip:minus_one_to_one) [OpenGL 3.3, 2.13.1].
    359  * When we switch the far and near value to satisfy DirectX requirements we have
    360  * to compensate by inverting "z_d' = -z_d" with this lowering pass.
    361  */
    362 void
    363 d3d12_nir_invert_depth(nir_shader *shader)
    364 {
    365    if (shader->info.stage != MESA_SHADER_VERTEX &&
    366        shader->info.stage != MESA_SHADER_GEOMETRY)
    367       return;
    368 
    369    nir_foreach_function(function, shader) {
    370       if (function->impl) {
    371          nir_builder b;
    372          nir_builder_init(&b, function->impl);
    373 
    374          nir_foreach_block(block, function->impl) {
    375             nir_foreach_instr_safe(instr, block) {
    376                invert_depth(&b, instr);
    377             }
    378          }
    379 
    380          nir_metadata_preserve(function->impl, nir_metadata_block_index |
    381                                                nir_metadata_dominance);
    382       }
    383    }
    384 }
    385 
    386 
    387 /**
    388  * Lower State Vars:
    389  *
    390  * All uniforms related to internal D3D12 variables are
    391  * condensed into a UBO that is appended at the end of the
    392  * current ones.
    393  */
    394 
    395 static unsigned
    396 get_state_var_offset(struct d3d12_shader *shader, enum d3d12_state_var var)
    397 {
    398    for (unsigned i = 0; i < shader->num_state_vars; ++i) {
    399       if (shader->state_vars[i].var == var)
    400          return shader->state_vars[i].offset;
    401    }
    402 
    403    unsigned offset = shader->state_vars_size;
    404    shader->state_vars[shader->num_state_vars].offset = offset;
    405    shader->state_vars[shader->num_state_vars].var = var;
    406    shader->state_vars_size += 4; /* Use 4-words slots no matter the variable size */
    407    shader->num_state_vars++;
    408 
    409    return offset;
    410 }
    411 
    412 static bool
    413 lower_instr(nir_intrinsic_instr *instr, nir_builder *b,
    414             struct d3d12_shader *shader, unsigned binding)
    415 {
    416    nir_variable *variable = NULL;
    417    nir_deref_instr *deref = NULL;
    418 
    419    b->cursor = nir_before_instr(&instr->instr);
    420 
    421    if (instr->intrinsic == nir_intrinsic_load_uniform) {
    422       nir_foreach_variable_with_modes(var, b->shader, nir_var_uniform) {
    423          if (var->data.driver_location == nir_intrinsic_base(instr)) {
    424             variable = var;
    425             break;
    426          }
    427       }
    428    } else if (instr->intrinsic == nir_intrinsic_load_deref) {
    429       deref = nir_src_as_deref(instr->src[0]);
    430       variable = nir_intrinsic_get_var(instr, 0);
    431    }
    432 
    433    if (variable == NULL ||
    434        variable->num_state_slots != 1 ||
    435        variable->state_slots[0].tokens[0] != STATE_INTERNAL_DRIVER)
    436       return false;
    437 
    438    enum d3d12_state_var var = variable->state_slots[0].tokens[1];
    439    nir_ssa_def *ubo_idx = nir_imm_int(b, binding);
    440    nir_ssa_def *ubo_offset =  nir_imm_int(b, get_state_var_offset(shader, var) * 4);
    441    nir_ssa_def *load =
    442       nir_load_ubo(b, instr->num_components, instr->dest.ssa.bit_size,
    443                    ubo_idx, ubo_offset,
    444                    .align_mul = instr->dest.ssa.bit_size / 8,
    445                    .align_offset = 0,
    446                    .range_base = 0,
    447                    .range = ~0,
    448                    );
    449 
    450    nir_ssa_def_rewrite_uses(&instr->dest.ssa, load);
    451 
    452    /* Remove the old load_* instruction and any parent derefs */
    453    nir_instr_remove(&instr->instr);
    454    for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) {
    455       /* If anyone is using this deref, leave it alone */
    456       assert(d->dest.is_ssa);
    457       if (!list_is_empty(&d->dest.ssa.uses))
    458          break;
    459 
    460       nir_instr_remove(&d->instr);
    461    }
    462 
    463    return true;
    464 }
    465 
    466 bool
    467 d3d12_lower_state_vars(nir_shader *nir, struct d3d12_shader *shader)
    468 {
    469    bool progress = false;
    470 
    471    /* The state var UBO is added after all the other UBOs if it already
    472     * exists it will be replaced by using the same binding.
    473     * In the event there are no other UBO's, use binding slot 1 to
    474     * be consistent with other non-default UBO's */
    475    unsigned binding = MAX2(nir->info.num_ubos, 1);
    476 
    477    nir_foreach_variable_with_modes_safe(var, nir, nir_var_uniform) {
    478       if (var->num_state_slots == 1 &&
    479           var->state_slots[0].tokens[0] == STATE_INTERNAL_DRIVER) {
    480          if (var->data.mode == nir_var_mem_ubo) {
    481             binding = var->data.binding;
    482          }
    483       }
    484    }
    485 
    486    nir_foreach_function(function, nir) {
    487       if (function->impl) {
    488          nir_builder builder;
    489          nir_builder_init(&builder, function->impl);
    490          nir_foreach_block(block, function->impl) {
    491             nir_foreach_instr_safe(instr, block) {
    492                if (instr->type == nir_instr_type_intrinsic)
    493                   progress |= lower_instr(nir_instr_as_intrinsic(instr),
    494                                           &builder,
    495                                           shader,
    496                                           binding);
    497             }
    498          }
    499 
    500          nir_metadata_preserve(function->impl, nir_metadata_block_index |
    501                                                nir_metadata_dominance);
    502       }
    503    }
    504 
    505    if (progress) {
    506       assert(shader->num_state_vars > 0);
    507 
    508       shader->state_vars_used = true;
    509 
    510       /* Remove state variables */
    511       nir_foreach_variable_with_modes_safe(var, nir, nir_var_uniform) {
    512          if (var->num_state_slots == 1 &&
    513              var->state_slots[0].tokens[0] == STATE_INTERNAL_DRIVER) {
    514             exec_node_remove(&var->node);
    515             nir->num_uniforms--;
    516          }
    517       }
    518 
    519       const gl_state_index16 tokens[STATE_LENGTH] = { STATE_INTERNAL_DRIVER };
    520       const struct glsl_type *type = glsl_array_type(glsl_vec4_type(),
    521                                                      shader->state_vars_size / 4, 0);
    522       nir_variable *ubo = nir_variable_create(nir, nir_var_mem_ubo, type,
    523                                                   "d3d12_state_vars");
    524       if (binding >= nir->info.num_ubos)
    525          nir->info.num_ubos = binding + 1;
    526       ubo->data.binding = binding;
    527       ubo->num_state_slots = 1;
    528       ubo->state_slots = ralloc_array(ubo, nir_state_slot, 1);
    529       memcpy(ubo->state_slots[0].tokens, tokens,
    530               sizeof(ubo->state_slots[0].tokens));
    531 
    532       struct glsl_struct_field field = {
    533           .type = type,
    534           .name = "data",
    535           .location = -1,
    536       };
    537       ubo->interface_type =
    538               glsl_interface_type(&field, 1, GLSL_INTERFACE_PACKING_STD430,
    539                                   false, "__d3d12_state_vars_interface");
    540    }
    541 
    542    return progress;
    543 }
    544 
    545 void
    546 d3d12_add_missing_dual_src_target(struct nir_shader *s,
    547                                   unsigned missing_mask)
    548 {
    549    assert(missing_mask != 0);
    550    nir_builder b;
    551    nir_function_impl *impl = nir_shader_get_entrypoint(s);
    552    nir_builder_init(&b, impl);
    553    b.cursor = nir_before_cf_list(&impl->body);
    554 
    555    nir_ssa_def *zero = nir_imm_zero(&b, 4, 32);
    556    for (unsigned i = 0; i < 2; ++i) {
    557 
    558       if (!(missing_mask & (1u << i)))
    559          continue;
    560 
    561       const char *name = i == 0 ? "gl_FragData[0]" :
    562                                   "gl_SecondaryFragDataEXT[0]";
    563       nir_variable *out = nir_variable_create(s, nir_var_shader_out,
    564                                               glsl_vec4_type(), name);
    565       out->data.location = FRAG_RESULT_DATA0;
    566       out->data.driver_location = i;
    567       out->data.index = i;
    568 
    569       nir_store_var(&b, out, zero, 0xf);
    570    }
    571    nir_metadata_preserve(impl, nir_metadata_block_index |
    572                                nir_metadata_dominance);
    573 }
    574 
    575 static bool
    576 fix_io_uint_type(struct nir_shader *s, nir_variable_mode modes, int slot)
    577 {
    578    nir_variable *fixed_var = NULL;
    579    nir_foreach_variable_with_modes(var, s, modes) {
    580       if (var->data.location == slot) {
    581          var->type = glsl_uint_type();
    582          fixed_var = var;
    583          break;
    584       }
    585    }
    586 
    587    assert(fixed_var);
    588 
    589    nir_foreach_function(function, s) {
    590       if (function->impl) {
    591          nir_foreach_block(block, function->impl) {
    592             nir_foreach_instr_safe(instr, block) {
    593                if (instr->type == nir_instr_type_deref) {
    594                   nir_deref_instr *deref = nir_instr_as_deref(instr);
    595                   if (deref->var == fixed_var)
    596                      deref->type = fixed_var->type;
    597                }
    598             }
    599          }
    600       }
    601    }
    602    return true;
    603 }
    604 
    605 bool
    606 d3d12_fix_io_uint_type(struct nir_shader *s, uint64_t in_mask, uint64_t out_mask)
    607 {
    608    if (!(s->info.outputs_written & out_mask) &&
    609        !(s->info.inputs_read & in_mask))
    610       return false;
    611 
    612    bool progress = false;
    613 
    614    while (in_mask) {
    615       int slot = u_bit_scan64(&in_mask);
    616       progress |= (s->info.inputs_read & (1ull << slot)) &&
    617                   fix_io_uint_type(s, nir_var_shader_in, slot);
    618    }
    619 
    620    while (out_mask) {
    621       int slot = u_bit_scan64(&out_mask);
    622       progress |= (s->info.outputs_written & (1ull << slot)) &&
    623                   fix_io_uint_type(s, nir_var_shader_out, slot);
    624    }
    625 
    626    return progress;
    627 }
    628 
    629 static bool
    630 lower_load_ubo_packed_filter(const nir_instr *instr,
    631                              UNUSED const void *_options) {
    632    if (instr->type != nir_instr_type_intrinsic)
    633       return false;
    634 
    635    nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
    636 
    637    return intr->intrinsic == nir_intrinsic_load_ubo;
    638 }
    639 
    640 static nir_ssa_def *
    641 lower_load_ubo_packed_impl(nir_builder *b, nir_instr *instr,
    642                               UNUSED void *_options) {
    643    nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
    644 
    645    nir_ssa_def *buffer = intr->src[0].ssa;
    646    nir_ssa_def *offset = intr->src[1].ssa;
    647 
    648    nir_ssa_def *result =
    649       build_load_ubo_dxil(b, buffer,
    650                           offset,
    651                           nir_dest_num_components(intr->dest),
    652                           nir_dest_bit_size(intr->dest));
    653    return result;
    654 }
    655 
    656 bool
    657 nir_lower_packed_ubo_loads(nir_shader *nir) {
    658    return nir_shader_lower_instructions(nir,
    659                                         lower_load_ubo_packed_filter,
    660                                         lower_load_ubo_packed_impl,
    661                                         NULL);
    662 }
    663 
    664 void
    665 d3d12_lower_primitive_id(nir_shader *shader)
    666 {
    667    nir_builder b;
    668    nir_function_impl *impl = nir_shader_get_entrypoint(shader);
    669    nir_ssa_def *primitive_id;
    670    nir_builder_init(&b, impl);
    671 
    672    nir_variable *primitive_id_var = nir_variable_create(shader, nir_var_shader_out,
    673                                                         glsl_uint_type(), "primitive_id");
    674    primitive_id_var->data.location = VARYING_SLOT_PRIMITIVE_ID;
    675    primitive_id_var->data.interpolation = INTERP_MODE_FLAT;
    676 
    677    nir_foreach_block(block, impl) {
    678       b.cursor = nir_before_block(block);
    679       primitive_id = nir_load_primitive_id(&b);
    680 
    681       nir_foreach_instr_safe(instr, block) {
    682          if (instr->type != nir_instr_type_intrinsic ||
    683              nir_instr_as_intrinsic(instr)->intrinsic != nir_intrinsic_emit_vertex)
    684             continue;
    685 
    686          b.cursor = nir_before_instr(instr);
    687          nir_store_var(&b, primitive_id_var, primitive_id, 0x1);
    688       }
    689    }
    690 
    691    nir_metadata_preserve(impl, nir_metadata_none);
    692 }
    693 
    694 static void
    695 lower_triangle_strip_store(nir_builder *b, nir_intrinsic_instr *intr,
    696                            nir_variable *vertex_count_var,
    697                            nir_variable **varyings)
    698 {
    699    /**
    700     * tmp_varying[slot][min(vertex_count, 2)] = src
    701     */
    702    nir_ssa_def *vertex_count = nir_load_var(b, vertex_count_var);
    703    nir_ssa_def *index = nir_imin(b, vertex_count, nir_imm_int(b, 2));
    704    nir_variable *var = nir_intrinsic_get_var(intr, 0);
    705 
    706    if (var->data.mode != nir_var_shader_out)
    707       return;
    708 
    709    nir_deref_instr *deref = nir_build_deref_array(b, nir_build_deref_var(b, varyings[var->data.location]), index);
    710    nir_ssa_def *value = nir_ssa_for_src(b, intr->src[1], intr->num_components);
    711    nir_store_deref(b, deref, value, 0xf);
    712    nir_instr_remove(&intr->instr);
    713 }
    714 
    715 static void
    716 lower_triangle_strip_emit_vertex(nir_builder *b, nir_intrinsic_instr *intr,
    717                                  nir_variable *vertex_count_var,
    718                                  nir_variable **varyings,
    719                                  nir_variable **out_varyings)
    720 {
    721    // TODO xfb + flat shading + last_pv
    722    /**
    723     * if (vertex_count >= 2) {
    724     *    for (i = 0; i < 3; i++) {
    725     *       foreach(slot)
    726     *          out[slot] = tmp_varying[slot][i];
    727     *       EmitVertex();
    728     *    }
    729     *    EndPrimitive();
    730     *    foreach(slot)
    731     *       tmp_varying[slot][vertex_count % 2] = tmp_varying[slot][2];
    732     * }
    733     * vertex_count++;
    734     */
    735 
    736    nir_ssa_def *two = nir_imm_int(b, 2);
    737    nir_ssa_def *vertex_count = nir_load_var(b, vertex_count_var);
    738    nir_ssa_def *count_cmp = nir_uge(b, vertex_count, two);
    739    nir_if *count_check = nir_push_if(b, count_cmp);
    740 
    741    for (int j = 0; j < 3; ++j) {
    742       for (int i = 0; i < VARYING_SLOT_MAX; ++i) {
    743          if (!varyings[i])
    744             continue;
    745          nir_copy_deref(b, nir_build_deref_var(b, out_varyings[i]),
    746                         nir_build_deref_array_imm(b, nir_build_deref_var(b, varyings[i]), j));
    747       }
    748       nir_emit_vertex(b, 0);
    749    }
    750 
    751    for (int i = 0; i < VARYING_SLOT_MAX; ++i) {
    752       if (!varyings[i])
    753          continue;
    754       nir_copy_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, varyings[i]), nir_umod(b, vertex_count, two)),
    755                         nir_build_deref_array(b, nir_build_deref_var(b, varyings[i]), two));
    756    }
    757 
    758    nir_end_primitive(b, .stream_id = 0);
    759 
    760    nir_pop_if(b, count_check);
    761 
    762    vertex_count = nir_iadd(b, vertex_count, nir_imm_int(b, 1));
    763    nir_store_var(b, vertex_count_var, vertex_count, 0x1);
    764 
    765    nir_instr_remove(&intr->instr);
    766 }
    767 
    768 static void
    769 lower_triangle_strip_end_primitive(nir_builder *b, nir_intrinsic_instr *intr,
    770                                    nir_variable *vertex_count_var)
    771 {
    772    /**
    773     * vertex_count = 0;
    774     */
    775    nir_store_var(b, vertex_count_var, nir_imm_int(b, 0), 0x1);
    776    nir_instr_remove(&intr->instr);
    777 }
    778 
    779 void
    780 d3d12_lower_triangle_strip(nir_shader *shader)
    781 {
    782    nir_builder b;
    783    nir_function_impl *impl = nir_shader_get_entrypoint(shader);
    784    nir_variable *tmp_vars[VARYING_SLOT_MAX] = {0};
    785    nir_variable *out_vars[VARYING_SLOT_MAX] = {0};
    786    nir_builder_init(&b, impl);
    787 
    788    shader->info.gs.vertices_out = (shader->info.gs.vertices_out - 2) * 3;
    789 
    790    nir_variable *vertex_count_var =
    791       nir_local_variable_create(impl, glsl_uint_type(), "vertex_count");
    792 
    793    nir_block *first = nir_start_block(impl);
    794    b.cursor = nir_before_block(first);
    795    nir_foreach_variable_with_modes(var, shader, nir_var_shader_out) {
    796       const struct glsl_type *type = glsl_array_type(var->type, 3, 0);
    797       tmp_vars[var->data.location] =  nir_local_variable_create(impl, type, "tmp_var");
    798       out_vars[var->data.location] = var;
    799    }
    800    nir_store_var(&b, vertex_count_var, nir_imm_int(&b, 0), 1);
    801 
    802    nir_foreach_block(block, impl) {
    803       nir_foreach_instr_safe(instr, block) {
    804          if (instr->type != nir_instr_type_intrinsic)
    805             continue;
    806 
    807          nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
    808          switch (intrin->intrinsic) {
    809          case nir_intrinsic_store_deref:
    810             b.cursor = nir_before_instr(instr);
    811             lower_triangle_strip_store(&b, intrin, vertex_count_var, tmp_vars);
    812             break;
    813          case nir_intrinsic_emit_vertex_with_counter:
    814          case nir_intrinsic_emit_vertex:
    815             b.cursor = nir_before_instr(instr);
    816             lower_triangle_strip_emit_vertex(&b, intrin, vertex_count_var,
    817                                              tmp_vars, out_vars);
    818             break;
    819          case nir_intrinsic_end_primitive:
    820          case nir_intrinsic_end_primitive_with_counter:
    821             b.cursor = nir_before_instr(instr);
    822             lower_triangle_strip_end_primitive(&b, intrin, vertex_count_var);
    823             break;
    824          default:
    825             break;
    826          }
    827       }
    828    }
    829 
    830    nir_metadata_preserve(impl, nir_metadata_none);
    831    NIR_PASS_V(shader, nir_lower_var_copies);
    832 }
    833