static bool
lower_offset(nir_builder *b, nir_tex_instr *tex)
{
   int offset_index = nir_tex_instr_src_index(tex, nir_tex_src_offset);
   if (offset_index < 0)
      return false;

   int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
   assert(coord_index >= 0);

   assert(tex->src[offset_index].src.is_ssa);
   assert(tex->src[coord_index].src.is_ssa);
   nir_ssa_def *offset = tex->src[offset_index].src.ssa;
   nir_ssa_def *coord = tex->src[coord_index].src.ssa;

   b->cursor = nir_before_instr(&tex->instr);

   nir_ssa_def *offset_coord;
   if (nir_tex_instr_src_type(tex, coord_index) == nir_type_float) {
      if (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
         offset_coord = nir_fadd(b, coord, nir_i2f32(b, offset));
      } else {
         nir_ssa_def *txs = get_texture_size(b, tex);
         nir_ssa_def *scale = nir_frcp(b, txs);

         offset_coord = nir_fadd(b, coord,
                                 nir_fmul(b,
                                          nir_i2f32(b, offset),
                                          scale));
      }
   } else {
      offset_coord = nir_iadd(b, coord, offset);
   }

   if (tex->is_array) {
      /* The offset is not applied to the array index */
      if (tex->coord_components == 2) {
         offset_coord = nir_vec2(b, nir_channel(b, offset_coord, 0),
                                    nir_channel(b, coord, 1));
      } else if (tex->coord_components == 3) {
         offset_coord = nir_vec3(b, nir_channel(b, offset_coord, 0),
                                    nir_channel(b, offset_coord, 1),
                                    nir_channel(b, coord, 2));
      } else {
         unreachable("Invalid number of components");
      }
   }

   nir_instr_rewrite_src(&tex->instr, &tex->src[coord_index].src,
                         nir_src_for_ssa(offset_coord));

   nir_tex_instr_remove_src(tex, offset_index);

   return true;
}
/* Multiply interp_var_at_offset's offset by transform.x to flip it. */
static void
lower_interp_var_at_offset(lower_wpos_ytransform_state *state,
                           nir_intrinsic_instr *interp)
{
    nir_builder *b = &state->b;
    nir_ssa_def *offset;
    nir_ssa_def *flip_y;

    b->cursor = nir_before_instr(&interp->instr);

    offset = nir_ssa_for_src(b, interp->src[0], 2);
    flip_y = nir_fmul(b, nir_channel(b, offset, 1),
                      nir_channel(b, get_transform(state), 0));
    nir_instr_rewrite_src(&interp->instr, &interp->src[0],
                          nir_src_for_ssa(nir_vec2(b, nir_channel(b, offset, 0),
                                          flip_y)));
}
static void
lower_load_sample_pos(lower_wpos_ytransform_state *state,
                      nir_intrinsic_instr *intr)
{
    nir_builder *b = &state->b;
    b->cursor = nir_after_instr(&intr->instr);

    nir_ssa_def *pos = &intr->dest.ssa;
    nir_ssa_def *scale = nir_channel(b, get_transform(state), 0);
    nir_ssa_def *neg_scale = nir_channel(b, get_transform(state), 2);
    /* Either y or 1-y for scale equal to 1 or -1 respectively. */
    nir_ssa_def *flipped_y =
        nir_fadd(b, nir_fmax(b, neg_scale, nir_imm_float(b, 0.0)),
                 nir_fmul(b, nir_channel(b, pos, 1), scale));
    nir_ssa_def *flipped_pos = nir_vec2(b, nir_channel(b, pos, 0), flipped_y);

    nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, nir_src_for_ssa(flipped_pos),
                                   flipped_pos->parent_instr);
}
static void
lower_load_pointcoord(lower_wpos_ytransform_state *state,
                      nir_intrinsic_instr *intr)
{
   nir_builder *b = &state->b;
   b->cursor = nir_after_instr(&intr->instr);

   nir_ssa_def *pntc = &intr->dest.ssa;
   nir_ssa_def *transform = get_transform(state);
   nir_ssa_def *y = nir_channel(b, pntc, 1);
   /* The offset is 1 if we're flipping, 0 otherwise. */
   nir_ssa_def *offset = nir_fmax(b, nir_channel(b, transform, 2),
                                  nir_imm_float(b, 0.0));
   /* Flip the sign of y if we're flipping. */
   nir_ssa_def *scaled = nir_fmul(b, y, nir_channel(b, transform, 0));

   /* Reassemble the vector. */
   nir_ssa_def *flipped_pntc = nir_vec2(b,
                                        nir_channel(b, pntc, 0),
                                        nir_fadd(b, offset, scaled));

   nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, nir_src_for_ssa(flipped_pntc),
                                  flipped_pntc->parent_instr);
}
static void
project_src(nir_builder *b, nir_tex_instr *tex)
{
   /* Find the projector in the srcs list, if present. */
   int proj_index = nir_tex_instr_src_index(tex, nir_tex_src_projector);
   if (proj_index < 0)
      return;

   b->cursor = nir_before_instr(&tex->instr);

   nir_ssa_def *inv_proj =
      nir_frcp(b, nir_ssa_for_src(b, tex->src[proj_index].src, 1));

   /* Walk through the sources projecting the arguments. */
   for (unsigned i = 0; i < tex->num_srcs; i++) {
      switch (tex->src[i].src_type) {
      case nir_tex_src_coord:
      case nir_tex_src_comparator:
         break;
      default:
         continue;
      }
      nir_ssa_def *unprojected =
         nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i));
      nir_ssa_def *projected = nir_fmul(b, unprojected, inv_proj);

      /* Array indices don't get projected, so make an new vector with the
       * coordinate's array index untouched.
       */
      if (tex->is_array && tex->src[i].src_type == nir_tex_src_coord) {
         switch (tex->coord_components) {
         case 4:
            projected = nir_vec4(b,
                                 nir_channel(b, projected, 0),
                                 nir_channel(b, projected, 1),
                                 nir_channel(b, projected, 2),
                                 nir_channel(b, unprojected, 3));
            break;
         case 3:
            projected = nir_vec3(b,
                                 nir_channel(b, projected, 0),
                                 nir_channel(b, projected, 1),
                                 nir_channel(b, unprojected, 2));
            break;
         case 2:
            projected = nir_vec2(b,
                                 nir_channel(b, projected, 0),
                                 nir_channel(b, unprojected, 1));
            break;
         default:
            unreachable("bad texture coord count for array");
            break;
         }
      }

      nir_instr_rewrite_src(&tex->instr,
                            &tex->src[i].src,
                            nir_src_for_ssa(projected));
   }

   nir_tex_instr_remove_src(tex, proj_index);
}
Beispiel #6
0
static void
vc4_nir_lower_txf_ms_instr(struct vc4_compile *c, nir_builder *b,
                           nir_tex_instr *txf_ms)
{
    if (txf_ms->op != nir_texop_txf_ms)
        return;

    b->cursor = nir_before_instr(&txf_ms->instr);

    nir_tex_instr *txf = nir_tex_instr_create(c->s, 1);
    txf->op = nir_texop_txf;
    txf->sampler = txf_ms->sampler;
    txf->sampler_index = txf_ms->sampler_index;
    txf->coord_components = txf_ms->coord_components;
    txf->is_shadow = txf_ms->is_shadow;
    txf->is_new_style_shadow = txf_ms->is_new_style_shadow;

    nir_ssa_def *coord = NULL, *sample_index = NULL;
    for (int i = 0; i < txf_ms->num_srcs; i++) {
        assert(txf_ms->src[i].src.is_ssa);

        switch (txf_ms->src[i].src_type) {
        case nir_tex_src_coord:
            coord = txf_ms->src[i].src.ssa;
            break;
        case nir_tex_src_ms_index:
            sample_index = txf_ms->src[i].src.ssa;
            break;
        default:
            unreachable("Unknown txf_ms src\n");
        }
    }
    assert(coord);
    assert(sample_index);

    nir_ssa_def *x = nir_channel(b, coord, 0);
    nir_ssa_def *y = nir_channel(b, coord, 1);

    uint32_t tile_w = 32;
    uint32_t tile_h = 32;
    uint32_t tile_w_shift = 5;
    uint32_t tile_h_shift = 5;
    uint32_t tile_size = (tile_h * tile_w *
                          VC4_MAX_SAMPLES * sizeof(uint32_t));
    unsigned unit = txf_ms->sampler_index;
    uint32_t w = align(c->key->tex[unit].msaa_width, tile_w);
    uint32_t w_tiles = w / tile_w;

    nir_ssa_def *x_tile = nir_ushr(b, x, nir_imm_int(b, tile_w_shift));
    nir_ssa_def *y_tile = nir_ushr(b, y, nir_imm_int(b, tile_h_shift));
    nir_ssa_def *tile_addr = nir_iadd(b,
                                      nir_imul(b, x_tile,
                                              nir_imm_int(b, tile_size)),
                                      nir_imul(b, y_tile,
                                              nir_imm_int(b, (w_tiles *
                                                      tile_size))));
    nir_ssa_def *x_subspan = nir_iand(b, x,
                                      nir_imm_int(b, (tile_w - 1) & ~1));
    nir_ssa_def *y_subspan = nir_iand(b, y,
                                      nir_imm_int(b, (tile_h - 1) & ~1));
    nir_ssa_def *subspan_addr = nir_iadd(b,
                                         nir_imul(b, x_subspan,
                                                 nir_imm_int(b, 2 * VC4_MAX_SAMPLES * sizeof(uint32_t))),
                                         nir_imul(b, y_subspan,
                                                 nir_imm_int(b,
                                                         tile_w *
                                                         VC4_MAX_SAMPLES *
                                                         sizeof(uint32_t))));

    nir_ssa_def *pixel_addr = nir_ior(b,
                                      nir_iand(b,
                                              nir_ishl(b, x,
                                                      nir_imm_int(b, 2)),
                                              nir_imm_int(b, (1 << 2))),
                                      nir_iand(b,
                                              nir_ishl(b, y,
                                                      nir_imm_int(b, 3)),
                                              nir_imm_int(b, (1 << 3))));

    nir_ssa_def *sample_addr = nir_ishl(b, sample_index, nir_imm_int(b, 4));

    nir_ssa_def *addr = nir_iadd(b,
                                 nir_ior(b, sample_addr, pixel_addr),
                                 nir_iadd(b, subspan_addr, tile_addr));

    txf->src[0].src_type = nir_tex_src_coord;
    txf->src[0].src = nir_src_for_ssa(nir_vec2(b, addr, nir_imm_int(b, 0)));
    nir_ssa_dest_init(&txf->instr, &txf->dest, 4, NULL);
    nir_builder_instr_insert(b, &txf->instr);
    nir_ssa_def_rewrite_uses(&txf_ms->dest.ssa,
                             nir_src_for_ssa(&txf->dest.ssa));
    nir_instr_remove(&txf_ms->instr);
}