예제 #1
0
static void
lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_program,
              gl_shader_stage stage, nir_builder *builder)
{
   if (instr->sampler == NULL)
      return;

   instr->sampler_index = 0;
   unsigned location = instr->sampler->var->data.location;
   unsigned array_elements = 1;
   nir_ssa_def *indirect = NULL;

   builder->cursor = nir_before_instr(&instr->instr);
   calc_sampler_offsets(&instr->sampler->deref, instr, &array_elements,
                        &indirect, builder, &location);

   if (indirect) {
      /* First, we have to resize the array of texture sources */
      nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,
                                            instr->num_srcs + 1);

      for (unsigned i = 0; i < instr->num_srcs; i++) {
         new_srcs[i].src_type = instr->src[i].src_type;
         nir_instr_move_src(&instr->instr, &new_srcs[i].src,
                            &instr->src[i].src);
      }

      ralloc_free(instr->src);
      instr->src = new_srcs;

      /* Now we can go ahead and move the source over to being a
       * first-class texture source.
       */
      instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;
      instr->num_srcs++;
      nir_instr_rewrite_src(&instr->instr,
                            &instr->src[instr->num_srcs - 1].src,
                            nir_src_for_ssa(indirect));

      instr->sampler_array_size = array_elements;
   }

   if (location > shader_program->NumUniformStorage - 1 ||
       !shader_program->UniformStorage[location].opaque[stage].active) {
      assert(!"cannot return a sampler");
      return;
   }

   instr->sampler_index +=
      shader_program->UniformStorage[location].opaque[stage].index;

   instr->sampler = NULL;
}
예제 #2
0
static void
project_src(nir_builder *b, nir_tex_instr *tex)
{
   /* Find the projector in the srcs list, if present. */
   unsigned proj_index;
   for (proj_index = 0; proj_index < tex->num_srcs; proj_index++) {
      if (tex->src[proj_index].src_type == nir_tex_src_projector)
         break;
   }
   if (proj_index == tex->num_srcs)
      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_comparitor:
         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));
   }

   /* Now move the later tex sources down the array so that the projector
    * disappears.
    */
   nir_instr_rewrite_src(&tex->instr, &tex->src[proj_index].src,
                         NIR_SRC_INIT);
   for (unsigned i = proj_index + 1; i < tex->num_srcs; i++) {
      tex->src[i-1].src_type = tex->src[i].src_type;
      nir_instr_move_src(&tex->instr, &tex->src[i-1].src, &tex->src[i].src);
   }
   tex->num_srcs--;
}