Home | History | Annotate | Download | only in nir
      1 /*
      2  * Copyright  2014-2015 Broadcom
      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  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  */
     23 
     24 #ifndef NIR_BUILDER_H
     25 #define NIR_BUILDER_H
     26 
     27 #include "nir_control_flow.h"
     28 
     29 struct exec_list;
     30 
     31 typedef struct nir_builder {
     32    nir_cursor cursor;
     33 
     34    /* Whether new ALU instructions will be marked "exact" */
     35    bool exact;
     36 
     37    nir_shader *shader;
     38    nir_function_impl *impl;
     39 } nir_builder;
     40 
     41 static inline void
     42 nir_builder_init(nir_builder *build, nir_function_impl *impl)
     43 {
     44    memset(build, 0, sizeof(*build));
     45    build->exact = false;
     46    build->impl = impl;
     47    build->shader = impl->function->shader;
     48 }
     49 
     50 static inline void
     51 nir_builder_init_simple_shader(nir_builder *build, void *mem_ctx,
     52                                gl_shader_stage stage,
     53                                const nir_shader_compiler_options *options)
     54 {
     55    build->shader = nir_shader_create(mem_ctx, stage, options, NULL);
     56    nir_function *func = nir_function_create(build->shader, "main");
     57    build->exact = false;
     58    build->impl = nir_function_impl_create(func);
     59    build->cursor = nir_after_cf_list(&build->impl->body);
     60 }
     61 
     62 static inline void
     63 nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
     64 {
     65    nir_instr_insert(build->cursor, instr);
     66 
     67    /* Move the cursor forward. */
     68    build->cursor = nir_after_instr(instr);
     69 }
     70 
     71 static inline nir_instr *
     72 nir_builder_last_instr(nir_builder *build)
     73 {
     74    assert(build->cursor.option == nir_cursor_after_instr);
     75    return build->cursor.instr;
     76 }
     77 
     78 static inline void
     79 nir_builder_cf_insert(nir_builder *build, nir_cf_node *cf)
     80 {
     81    nir_cf_node_insert(build->cursor, cf);
     82 }
     83 
     84 static inline nir_ssa_def *
     85 nir_ssa_undef(nir_builder *build, unsigned num_components, unsigned bit_size)
     86 {
     87    nir_ssa_undef_instr *undef =
     88       nir_ssa_undef_instr_create(build->shader, num_components, bit_size);
     89    if (!undef)
     90       return NULL;
     91 
     92    nir_instr_insert(nir_before_cf_list(&build->impl->body), &undef->instr);
     93 
     94    return &undef->def;
     95 }
     96 
     97 static inline nir_ssa_def *
     98 nir_build_imm(nir_builder *build, unsigned num_components,
     99               unsigned bit_size, nir_const_value value)
    100 {
    101    nir_load_const_instr *load_const =
    102       nir_load_const_instr_create(build->shader, num_components, bit_size);
    103    if (!load_const)
    104       return NULL;
    105 
    106    load_const->value = value;
    107 
    108    nir_builder_instr_insert(build, &load_const->instr);
    109 
    110    return &load_const->def;
    111 }
    112 
    113 static inline nir_ssa_def *
    114 nir_imm_float(nir_builder *build, float x)
    115 {
    116    nir_const_value v;
    117 
    118    memset(&v, 0, sizeof(v));
    119    v.f32[0] = x;
    120 
    121    return nir_build_imm(build, 1, 32, v);
    122 }
    123 
    124 static inline nir_ssa_def *
    125 nir_imm_double(nir_builder *build, double x)
    126 {
    127    nir_const_value v;
    128 
    129    memset(&v, 0, sizeof(v));
    130    v.f64[0] = x;
    131 
    132    return nir_build_imm(build, 1, 64, v);
    133 }
    134 
    135 static inline nir_ssa_def *
    136 nir_imm_vec4(nir_builder *build, float x, float y, float z, float w)
    137 {
    138    nir_const_value v;
    139 
    140    memset(&v, 0, sizeof(v));
    141    v.f32[0] = x;
    142    v.f32[1] = y;
    143    v.f32[2] = z;
    144    v.f32[3] = w;
    145 
    146    return nir_build_imm(build, 4, 32, v);
    147 }
    148 
    149 static inline nir_ssa_def *
    150 nir_imm_int(nir_builder *build, int x)
    151 {
    152    nir_const_value v;
    153 
    154    memset(&v, 0, sizeof(v));
    155    v.i32[0] = x;
    156 
    157    return nir_build_imm(build, 1, 32, v);
    158 }
    159 
    160 static inline nir_ssa_def *
    161 nir_imm_ivec4(nir_builder *build, int x, int y, int z, int w)
    162 {
    163    nir_const_value v;
    164 
    165    memset(&v, 0, sizeof(v));
    166    v.i32[0] = x;
    167    v.i32[1] = y;
    168    v.i32[2] = z;
    169    v.i32[3] = w;
    170 
    171    return nir_build_imm(build, 4, 32, v);
    172 }
    173 
    174 static inline nir_ssa_def *
    175 nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0,
    176               nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3)
    177 {
    178    const nir_op_info *op_info = &nir_op_infos[op];
    179    nir_alu_instr *instr = nir_alu_instr_create(build->shader, op);
    180    if (!instr)
    181       return NULL;
    182 
    183    instr->exact = build->exact;
    184 
    185    instr->src[0].src = nir_src_for_ssa(src0);
    186    if (src1)
    187       instr->src[1].src = nir_src_for_ssa(src1);
    188    if (src2)
    189       instr->src[2].src = nir_src_for_ssa(src2);
    190    if (src3)
    191       instr->src[3].src = nir_src_for_ssa(src3);
    192 
    193    /* Guess the number of components the destination temporary should have
    194     * based on our input sizes, if it's not fixed for the op.
    195     */
    196    unsigned num_components = op_info->output_size;
    197    if (num_components == 0) {
    198       for (unsigned i = 0; i < op_info->num_inputs; i++) {
    199          if (op_info->input_sizes[i] == 0)
    200             num_components = MAX2(num_components,
    201                                   instr->src[i].src.ssa->num_components);
    202       }
    203    }
    204    assert(num_components != 0);
    205 
    206    /* Figure out the bitwidth based on the source bitwidth if the instruction
    207     * is variable-width.
    208     */
    209    unsigned bit_size = nir_alu_type_get_type_size(op_info->output_type);
    210    if (bit_size == 0) {
    211       for (unsigned i = 0; i < op_info->num_inputs; i++) {
    212          unsigned src_bit_size = instr->src[i].src.ssa->bit_size;
    213          if (nir_alu_type_get_type_size(op_info->input_types[i]) == 0) {
    214             if (bit_size)
    215                assert(src_bit_size == bit_size);
    216             else
    217                bit_size = src_bit_size;
    218          } else {
    219             assert(src_bit_size ==
    220                nir_alu_type_get_type_size(op_info->input_types[i]));
    221          }
    222       }
    223    }
    224 
    225    /* Make sure we don't swizzle from outside of our source vector (like if a
    226     * scalar value was passed into a multiply with a vector).
    227     */
    228    for (unsigned i = 0; i < op_info->num_inputs; i++) {
    229       for (unsigned j = instr->src[i].src.ssa->num_components; j < 4; j++) {
    230          instr->src[i].swizzle[j] = instr->src[i].src.ssa->num_components - 1;
    231       }
    232    }
    233 
    234    nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components,
    235                      bit_size, NULL);
    236    instr->dest.write_mask = (1 << num_components) - 1;
    237 
    238    nir_builder_instr_insert(build, &instr->instr);
    239 
    240    return &instr->dest.dest.ssa;
    241 }
    242 
    243 #include "nir_builder_opcodes.h"
    244 
    245 static inline nir_ssa_def *
    246 nir_vec(nir_builder *build, nir_ssa_def **comp, unsigned num_components)
    247 {
    248    switch (num_components) {
    249    case 4:
    250       return nir_vec4(build, comp[0], comp[1], comp[2], comp[3]);
    251    case 3:
    252       return nir_vec3(build, comp[0], comp[1], comp[2]);
    253    case 2:
    254       return nir_vec2(build, comp[0], comp[1]);
    255    case 1:
    256       return comp[0];
    257    default:
    258       unreachable("bad component count");
    259       return NULL;
    260    }
    261 }
    262 
    263 /**
    264  * Similar to nir_fmov, but takes a nir_alu_src instead of a nir_ssa_def.
    265  */
    266 static inline nir_ssa_def *
    267 nir_fmov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
    268 {
    269    nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_fmov);
    270    nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components,
    271                      nir_src_bit_size(src.src), NULL);
    272    mov->exact = build->exact;
    273    mov->dest.write_mask = (1 << num_components) - 1;
    274    mov->src[0] = src;
    275    nir_builder_instr_insert(build, &mov->instr);
    276 
    277    return &mov->dest.dest.ssa;
    278 }
    279 
    280 static inline nir_ssa_def *
    281 nir_imov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
    282 {
    283    nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_imov);
    284    nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components,
    285                      nir_src_bit_size(src.src), NULL);
    286    mov->exact = build->exact;
    287    mov->dest.write_mask = (1 << num_components) - 1;
    288    mov->src[0] = src;
    289    nir_builder_instr_insert(build, &mov->instr);
    290 
    291    return &mov->dest.dest.ssa;
    292 }
    293 
    294 /**
    295  * Construct an fmov or imov that reswizzles the source's components.
    296  */
    297 static inline nir_ssa_def *
    298 nir_swizzle(nir_builder *build, nir_ssa_def *src, const unsigned swiz[4],
    299             unsigned num_components, bool use_fmov)
    300 {
    301    nir_alu_src alu_src = { NIR_SRC_INIT };
    302    alu_src.src = nir_src_for_ssa(src);
    303    for (unsigned i = 0; i < num_components; i++)
    304       alu_src.swizzle[i] = swiz[i];
    305 
    306    return use_fmov ? nir_fmov_alu(build, alu_src, num_components) :
    307                      nir_imov_alu(build, alu_src, num_components);
    308 }
    309 
    310 /* Selects the right fdot given the number of components in each source. */
    311 static inline nir_ssa_def *
    312 nir_fdot(nir_builder *build, nir_ssa_def *src0, nir_ssa_def *src1)
    313 {
    314    assert(src0->num_components == src1->num_components);
    315    switch (src0->num_components) {
    316    case 1: return nir_fmul(build, src0, src1);
    317    case 2: return nir_fdot2(build, src0, src1);
    318    case 3: return nir_fdot3(build, src0, src1);
    319    case 4: return nir_fdot4(build, src0, src1);
    320    default:
    321       unreachable("bad component size");
    322    }
    323 
    324    return NULL;
    325 }
    326 
    327 static inline nir_ssa_def *
    328 nir_bany_inequal(nir_builder *b, nir_ssa_def *src0, nir_ssa_def *src1)
    329 {
    330    switch (src0->num_components) {
    331    case 1: return nir_ine(b, src0, src1);
    332    case 2: return nir_bany_inequal2(b, src0, src1);
    333    case 3: return nir_bany_inequal3(b, src0, src1);
    334    case 4: return nir_bany_inequal4(b, src0, src1);
    335    default:
    336       unreachable("bad component size");
    337    }
    338 }
    339 
    340 static inline nir_ssa_def *
    341 nir_bany(nir_builder *b, nir_ssa_def *src)
    342 {
    343    return nir_bany_inequal(b, src, nir_imm_int(b, 0));
    344 }
    345 
    346 static inline nir_ssa_def *
    347 nir_channel(nir_builder *b, nir_ssa_def *def, unsigned c)
    348 {
    349    unsigned swizzle[4] = {c, c, c, c};
    350    return nir_swizzle(b, def, swizzle, 1, false);
    351 }
    352 
    353 static inline nir_ssa_def *
    354 nir_channels(nir_builder *b, nir_ssa_def *def, unsigned mask)
    355 {
    356    unsigned num_channels = 0, swizzle[4] = { 0, 0, 0, 0 };
    357 
    358    for (unsigned i = 0; i < 4; i++) {
    359       if ((mask & (1 << i)) == 0)
    360          continue;
    361       swizzle[num_channels++] = i;
    362    }
    363 
    364    return nir_swizzle(b, def, swizzle, num_channels, false);
    365 }
    366 
    367 /**
    368  * Turns a nir_src into a nir_ssa_def * so it can be passed to
    369  * nir_build_alu()-based builder calls.
    370  *
    371  * See nir_ssa_for_alu_src() for alu instructions.
    372  */
    373 static inline nir_ssa_def *
    374 nir_ssa_for_src(nir_builder *build, nir_src src, int num_components)
    375 {
    376    if (src.is_ssa && src.ssa->num_components == num_components)
    377       return src.ssa;
    378 
    379    nir_alu_src alu = { NIR_SRC_INIT };
    380    alu.src = src;
    381    for (int j = 0; j < 4; j++)
    382       alu.swizzle[j] = j;
    383 
    384    return nir_imov_alu(build, alu, num_components);
    385 }
    386 
    387 /**
    388  * Similar to nir_ssa_for_src(), but for alu src's, respecting the
    389  * nir_alu_src's swizzle.
    390  */
    391 static inline nir_ssa_def *
    392 nir_ssa_for_alu_src(nir_builder *build, nir_alu_instr *instr, unsigned srcn)
    393 {
    394    static uint8_t trivial_swizzle[4] = { 0, 1, 2, 3 };
    395    nir_alu_src *src = &instr->src[srcn];
    396    unsigned num_components = nir_ssa_alu_instr_src_components(instr, srcn);
    397 
    398    if (src->src.is_ssa && (src->src.ssa->num_components == num_components) &&
    399        !src->abs && !src->negate &&
    400        (memcmp(src->swizzle, trivial_swizzle, num_components) == 0))
    401       return src->src.ssa;
    402 
    403    return nir_imov_alu(build, *src, num_components);
    404 }
    405 
    406 static inline nir_ssa_def *
    407 nir_load_var(nir_builder *build, nir_variable *var)
    408 {
    409    const unsigned num_components = glsl_get_vector_elements(var->type);
    410 
    411    nir_intrinsic_instr *load =
    412       nir_intrinsic_instr_create(build->shader, nir_intrinsic_load_var);
    413    load->num_components = num_components;
    414    load->variables[0] = nir_deref_var_create(load, var);
    415    nir_ssa_dest_init(&load->instr, &load->dest, num_components,
    416                      glsl_get_bit_size(var->type), NULL);
    417    nir_builder_instr_insert(build, &load->instr);
    418    return &load->dest.ssa;
    419 }
    420 
    421 static inline nir_ssa_def *
    422 nir_load_deref_var(nir_builder *build, nir_deref_var *deref)
    423 {
    424    const struct glsl_type *type = nir_deref_tail(&deref->deref)->type;
    425    const unsigned num_components = glsl_get_vector_elements(type);
    426 
    427    nir_intrinsic_instr *load =
    428       nir_intrinsic_instr_create(build->shader, nir_intrinsic_load_var);
    429    load->num_components = num_components;
    430    load->variables[0] = nir_deref_var_clone(deref, load);
    431    nir_ssa_dest_init(&load->instr, &load->dest, num_components,
    432                      glsl_get_bit_size(type), NULL);
    433    nir_builder_instr_insert(build, &load->instr);
    434    return &load->dest.ssa;
    435 }
    436 
    437 static inline void
    438 nir_store_var(nir_builder *build, nir_variable *var, nir_ssa_def *value,
    439               unsigned writemask)
    440 {
    441    const unsigned num_components = glsl_get_vector_elements(var->type);
    442 
    443    nir_intrinsic_instr *store =
    444       nir_intrinsic_instr_create(build->shader, nir_intrinsic_store_var);
    445    store->num_components = num_components;
    446    nir_intrinsic_set_write_mask(store, writemask);
    447    store->variables[0] = nir_deref_var_create(store, var);
    448    store->src[0] = nir_src_for_ssa(value);
    449    nir_builder_instr_insert(build, &store->instr);
    450 }
    451 
    452 static inline void
    453 nir_store_deref_var(nir_builder *build, nir_deref_var *deref,
    454                     nir_ssa_def *value, unsigned writemask)
    455 {
    456    const unsigned num_components =
    457       glsl_get_vector_elements(nir_deref_tail(&deref->deref)->type);
    458 
    459    nir_intrinsic_instr *store =
    460       nir_intrinsic_instr_create(build->shader, nir_intrinsic_store_var);
    461    store->num_components = num_components;
    462    store->const_index[0] = writemask & ((1 << num_components) - 1);
    463    store->variables[0] = nir_deref_var_clone(deref, store);
    464    store->src[0] = nir_src_for_ssa(value);
    465    nir_builder_instr_insert(build, &store->instr);
    466 }
    467 
    468 static inline void
    469 nir_copy_deref_var(nir_builder *build, nir_deref_var *dest, nir_deref_var *src)
    470 {
    471    assert(nir_deref_tail(&dest->deref)->type ==
    472           nir_deref_tail(&src->deref)->type);
    473 
    474    nir_intrinsic_instr *copy =
    475       nir_intrinsic_instr_create(build->shader, nir_intrinsic_copy_var);
    476    copy->variables[0] = nir_deref_var_clone(dest, copy);
    477    copy->variables[1] = nir_deref_var_clone(src, copy);
    478    nir_builder_instr_insert(build, &copy->instr);
    479 }
    480 
    481 static inline void
    482 nir_copy_var(nir_builder *build, nir_variable *dest, nir_variable *src)
    483 {
    484    nir_intrinsic_instr *copy =
    485       nir_intrinsic_instr_create(build->shader, nir_intrinsic_copy_var);
    486    copy->variables[0] = nir_deref_var_create(copy, dest);
    487    copy->variables[1] = nir_deref_var_create(copy, src);
    488    nir_builder_instr_insert(build, &copy->instr);
    489 }
    490 
    491 /* Generic builder for system values. */
    492 static inline nir_ssa_def *
    493 nir_load_system_value(nir_builder *build, nir_intrinsic_op op, int index)
    494 {
    495    nir_intrinsic_instr *load = nir_intrinsic_instr_create(build->shader, op);
    496    load->num_components = nir_intrinsic_infos[op].dest_components;
    497    load->const_index[0] = index;
    498    nir_ssa_dest_init(&load->instr, &load->dest,
    499                      nir_intrinsic_infos[op].dest_components, 32, NULL);
    500    nir_builder_instr_insert(build, &load->instr);
    501    return &load->dest.ssa;
    502 }
    503 
    504 /* Generate custom builders for system values. */
    505 #define INTRINSIC(name, num_srcs, src_components, has_dest, dest_components, \
    506                   num_variables, num_indices, idx0, idx1, idx2, flags)
    507 #define LAST_INTRINSIC(name)
    508 
    509 #define DEFINE_SYSTEM_VALUE(name)                                        \
    510    static inline nir_ssa_def *                                           \
    511    nir_load_##name(nir_builder *build)                                   \
    512    {                                                                     \
    513       return nir_load_system_value(build, nir_intrinsic_load_##name, 0); \
    514    }                                                                     \
    515 
    516 #include "nir_intrinsics.h"
    517 
    518 static inline nir_ssa_def *
    519 nir_load_barycentric(nir_builder *build, nir_intrinsic_op op,
    520                      unsigned interp_mode)
    521 {
    522    nir_intrinsic_instr *bary = nir_intrinsic_instr_create(build->shader, op);
    523    nir_ssa_dest_init(&bary->instr, &bary->dest, 2, 32, NULL);
    524    nir_intrinsic_set_interp_mode(bary, interp_mode);
    525    nir_builder_instr_insert(build, &bary->instr);
    526    return &bary->dest.ssa;
    527 }
    528 
    529 static inline void
    530 nir_jump(nir_builder *build, nir_jump_type jump_type)
    531 {
    532    nir_jump_instr *jump = nir_jump_instr_create(build->shader, jump_type);
    533    nir_builder_instr_insert(build, &jump->instr);
    534 }
    535 
    536 #endif /* NIR_BUILDER_H */
    537