static bool
constant_fold_intrinsic_instr(nir_intrinsic_instr *instr)
{
   bool progress = false;

   if (instr->intrinsic == nir_intrinsic_discard_if &&
       nir_src_is_const(instr->src[0])) {
      if (nir_src_as_bool(instr->src[0])) {
         /* This method of getting a nir_shader * from a nir_instr is
          * admittedly gross, but given the rarity of hitting this case I think
          * it's preferable to plumbing an otherwise unused nir_shader *
          * parameter through four functions to get here.
          */
         nir_cf_node *cf_node = &instr->instr.block->cf_node;
         nir_function_impl *impl = nir_cf_node_get_function(cf_node);
         nir_shader *shader = impl->function->shader;

         nir_intrinsic_instr *discard =
            nir_intrinsic_instr_create(shader, nir_intrinsic_discard);
         nir_instr_insert_before(&instr->instr, &discard->instr);
         nir_instr_remove(&instr->instr);
         progress = true;
      } else {
         /* We're not discarding, just delete the instruction */
         nir_instr_remove(&instr->instr);
         progress = true;
      }
   }

   return progress;
}
static nir_src
get_deref_reg_src(nir_deref_instr *deref, struct locals_to_regs_state *state)
{
   nir_builder *b = &state->builder;

   nir_src src;

   src.is_ssa = false;
   src.reg.reg = get_reg_for_deref(deref, state);
   src.reg.base_offset = 0;
   src.reg.indirect = NULL;

   /* It is possible for a user to create a shader that has an array with a
    * single element and then proceed to access it indirectly.  Indirectly
    * accessing a non-array register is not allowed in NIR.  In order to
    * handle this case we just convert it to a direct reference.
    */
   if (src.reg.reg->num_array_elems == 0)
      return src;

   unsigned inner_array_size = 1;
   for (const nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) {
      if (d->deref_type != nir_deref_type_array)
         continue;

      if (nir_src_is_const(d->arr.index) && !src.reg.indirect) {
         src.reg.base_offset += nir_src_as_uint(d->arr.index) *
                                inner_array_size;
      } else {
         if (src.reg.indirect) {
            assert(src.reg.base_offset == 0);
         } else {
            src.reg.indirect = ralloc(b->shader, nir_src);
            *src.reg.indirect =
               nir_src_for_ssa(nir_imm_int(b, src.reg.base_offset));
            src.reg.base_offset = 0;
         }

         assert(src.reg.indirect->is_ssa);
         nir_ssa_def *index = nir_i2i(b, nir_ssa_for_src(b, d->arr.index, 1), 32);
         src.reg.indirect->ssa =
            nir_iadd(b, src.reg.indirect->ssa,
                        nir_imul(b, index, nir_imm_int(b, inner_array_size)));
      }

      inner_array_size *= glsl_get_length(nir_deref_instr_parent(d)->type);
   }

   return src;
}
示例#3
0
static unsigned
get_io_offset(nir_deref_instr *deref, bool is_vertex_input)
{
   unsigned offset = 0;

   for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) {
      if (d->deref_type == nir_deref_type_array) {
         if (!nir_src_is_const(d->arr.index))
            return -1;

         offset += glsl_count_attribute_slots(d->type, is_vertex_input) *
                   nir_src_as_uint(d->arr.index);
      }
      /* TODO: we can get the offset for structs here see nir_lower_io() */
   }

   return offset;
}