[Mesa-dev] [PATCH v2 66/78] i965/nir/vec4: Add implementation of nir_emit_texture()

Jason Ekstrand jason at jlekstrand.net
Fri Jul 24 15:54:50 PDT 2015


On Thu, Jul 23, 2015 at 3:17 AM, Eduardo Lima Mitev <elima at igalia.com> wrote:
> From: Alejandro PiƱeiro <apinheiro at igalia.com>
>
> Uses the nir structure to get all the info needed (sources,
> dest reg, etc), and then it uses the common
> vec4_visitor::emit_texture to emit the final code.
> ---
>  src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 184 ++++++++++++++++++++++++++++-
>  1 file changed, 183 insertions(+), 1 deletion(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> index 2771116..83a91b7 100644
> --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> @@ -1286,10 +1286,192 @@ vec4_visitor::nir_emit_jump(nir_jump_instr *instr)
>     }
>  }
>
> +enum ir_texture_opcode
> +ir_texture_opcode_for_nir_texop(nir_texop texop)
> +{
> +   enum ir_texture_opcode op;
> +
> +   switch (texop) {
> +   case nir_texop_lod: op = ir_lod; break;
> +   case nir_texop_query_levels: op = ir_query_levels; break;
> +   case nir_texop_tex: op = ir_tex; break;
> +   case nir_texop_tg4: op = ir_tg4; break;
> +   case nir_texop_txb: op = ir_txb; break;
> +   case nir_texop_txd: op = ir_txd; break;
> +   case nir_texop_txf: op = ir_txf; break;
> +   case nir_texop_txf_ms: op = ir_txf_ms; break;
> +   case nir_texop_txl: op = ir_txl; break;
> +   case nir_texop_txs: op = ir_txs; break;
> +   default:
> +      unreachable("unknown texture opcode");
> +   }
> +
> +   return op;
> +}
> +
>  void
>  vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
>  {
> -   /* @TODO: Not yet implemented */
> +   unsigned sampler = instr->sampler_index;
> +   src_reg sampler_reg = src_reg(sampler);
> +   src_reg coordinate;
> +   const glsl_type *coord_type = NULL;
> +   src_reg shadow_comparitor;
> +   int shadow_compare = 0;
> +   bool has_nonconstant_offset = false;
> +   src_reg offset_value;
> +   src_reg lod, lod2;
> +   src_reg sample_index;
> +   src_reg mcs;
> +
> +   enum glsl_base_type dest_base_type =
> +      brw_glsl_base_type_for_nir_type(instr->dest_type);
> +   const glsl_type *dest_type =
> +      glsl_type::get_instance(dest_base_type,
> +                              nir_tex_instr_dest_size(instr), 1);

Why don't we just make a glsl_type_for_nir_alu_type that takes a
nir_alu_type and a number of components.  That seems easier than this
two-step process.

> +   dst_reg dest = get_nir_dest(instr->dest,
> +                               brw_type_for_base_type(dest_type));

Just use the version of get_nir_dest() that takes a nir_alu_type

> +
> +   /* When tg4 is used with the degenerate ZERO/ONE swizzles, don't bother
> +    * emitting anything other than setting up the constant result.
> +    */
> +   if (instr->op == nir_texop_tg4) {
> +      int swiz = GET_SWZ(key->tex.swizzles[sampler], instr->component);
> +      if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) {
> +         emit(MOV(dest, src_reg(swiz == SWIZZLE_ONE ? 1.0f : 0.0f)));
> +         return;
> +      }
> +   }
> +
> +   /* Load the texture operation sources */
> +   for (unsigned i = 0; i < instr->num_srcs; i++) {
> +      switch (instr->src[i].src_type) {
> +      case nir_tex_src_comparitor:
> +         shadow_comparitor = get_nir_src(instr->src[i].src,
> +                                         BRW_REGISTER_TYPE_F, 4);

I don't think the shadow comparison value is a vec4.  I'm pretty sure
it's just a float.  Use 1 component.

> +         shadow_comparitor.swizzle = BRW_SWIZZLE_XXXX;
> +         shadow_compare = 1;
> +         break;
> +
> +      case nir_tex_src_coord:
> +         switch (instr->op) {
> +         case nir_texop_txf:
> +         case nir_texop_txf_ms:
> +            coordinate = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_D, 4);
> +            coord_type = glsl_type::get_instance(GLSL_TYPE_INT,
> +                                                 instr->coord_components, 1);

Just use glsl_type::ivec(instr->coord_components);

> +            break;
> +
> +         default:
> +            coordinate = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_F, 4);
> +            coord_type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
> +                                                 instr->coord_components, 1);

Just use glsl_type::vec(instr->coord_components);

> +            break;
> +         }
> +         break;
> +
> +      case nir_tex_src_ddx:
> +         lod = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_F, 4);
> +         break;
> +
> +      case nir_tex_src_ddy:
> +         lod2 = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_F, 4);
> +         break;
> +
> +      case nir_tex_src_lod:
> +         switch (instr->op) {
> +         case nir_texop_txs:
> +            lod = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_UD, 4);
> +            break;
> +
> +         case nir_texop_txf:
> +            lod = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_D, 4);
> +            lod.swizzle = BRW_SWIZZLE_XXXX;
> +            break;
> +
> +         default:
> +            lod = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_F, 4);

Also, I don't think any of the above get_nir_src calls should be for 4
components.  lod in txf is obviously only for 1 from what you've
written.  Let's call get_nir_src with the right number of components.

> +            break;
> +         }
> +         break;
> +
> +      case nir_tex_src_ms_index: {
> +         sample_index = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_D, 4);

Again, index looks like a single component.

> +
> +         assert(coord_type != NULL);
> +         if (devinfo->gen >= 7 &&
> +             key->tex.compressed_multisample_layout_mask & (1<<sampler)) {
> +            mcs = emit_mcs_fetch(coord_type, coordinate, sampler_reg);
> +         } else {
> +            mcs = src_reg(0u);
> +         }
> +         mcs = retype(mcs, BRW_REGISTER_TYPE_UD);
> +         break;
> +      }
> +
> +      case nir_tex_src_offset:
> +         offset_value = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_D, 4);

again

> +         has_nonconstant_offset = true;
> +         break;
> +
> +      case nir_tex_src_sampler_offset: {
> +         /* The highest sampler which may be used by this operation is
> +          * the last element of the array. Mark it here, because the generator
> +          * doesn't have enough information to determine the bound.
> +          */
> +         uint32_t array_size = instr->sampler_array_size;
> +         src_reg src = get_nir_src(instr->src[i].src, 4);

Again, not 4 components.

> +         uint32_t max_used = sampler + array_size - 1;
> +         if (instr->op == nir_texop_tg4) {
> +            max_used += prog_data->base.binding_table.gather_texture_start;
> +         } else {
> +            max_used += prog_data->base.binding_table.texture_start;
> +         }
> +
> +         brw_mark_surface_used(&prog_data->base, max_used);
> +
> +         /* Emit code to evaluate the actual indexing expression */
> +         src_reg temp(this, glsl_type::uint_type);
> +         emit(ADD(dst_reg(temp), src, src_reg(sampler)));
> +         sampler_reg = emit_uniformize(temp);
> +         break;
> +      }
> +
> +      case nir_tex_src_projector:
> +         unreachable("Should be lowered by do_lower_texture_projection");
> +
> +      case nir_tex_src_bias:
> +         unreachable("LOD bias is not valid for vertex shaders.\n");
> +
> +      default:
> +         unreachable("unknown texture source");
> +      }
> +   }
> +
> +   uint32_t constant_offset = 0;
> +   for (unsigned i = 0; i < 3; i++) {
> +      if (instr->const_offset[i] != 0) {
> +         constant_offset = brw_texture_offset(instr->const_offset, 3);
> +         break;
> +      }
> +   }
> +
> +   /* Stuff the channel select bits in the top of the texture offset */
> +   if (instr->op == nir_texop_tg4)
> +      constant_offset |= gather_channel(instr->component, sampler) << 16;
> +
> +   ir_texture_opcode op = ir_texture_opcode_for_nir_texop(instr->op);
> +
> +   bool is_cube_array =
> +      instr->op == nir_texop_txs &&
> +      instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE &&
> +      instr->is_array;
> +
> +   emit_texture(op, dest, dest_type, coordinate, instr->coord_components,
> +                shadow_compare, shadow_comparitor,
> +                lod, lod2, sample_index,
> +                has_nonconstant_offset, constant_offset, offset_value,
> +                mcs, is_cube_array, sampler, sampler_reg);
>  }
>
>  }
> --
> 2.1.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list