[Mesa-dev] [PATCH v2 65/78] i965/ir/vec4: Refactor visit(ir_texture *ir)

Jason Ekstrand jason at jlekstrand.net
Fri Jul 24 16:49:56 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>
>
> Splitted in two. The emission is moved to a new vec4_visitor
> method, vec4_visitor::emit_texture, ir order to be reused
> on the nir path.
> ---
>  src/mesa/drivers/dri/i965/brw_vec4.h           |  15 +
>  src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 370 +++++++++++++------------
>  2 files changed, 212 insertions(+), 173 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
> index 56394af..561dd58 100644
> --- a/src/mesa/drivers/dri/i965/brw_vec4.h
> +++ b/src/mesa/drivers/dri/i965/brw_vec4.h
> @@ -330,6 +330,21 @@ public:
>     void emit_pack_unorm_4x8(const dst_reg &dst, const src_reg &src0);
>     void emit_pack_snorm_4x8(const dst_reg &dst, const src_reg &src0);
>
> +   void emit_texture(ir_texture_opcode op,
> +                     dst_reg dest,
> +                     const glsl_type *dest_type,
> +                     src_reg coordinate,
> +                     int coord_components,
> +                     bool shadow_compare, src_reg shadow_comparitor,

We don't need the boolean.  We can just use shadow_comparitor.file !=
BAD_FILE instead of the boolean

> +                     src_reg lod, src_reg lod2,
> +                     src_reg sample_index,
> +                     bool has_nonconstant_offset,
> +                     uint32_t constant_offset,

Same here.  There's no reason for both a register and a boolean.

> +                     src_reg offset_value,
> +                     src_reg mcs,
> +                     bool is_cube_array,
> +                     uint32_t sampler, src_reg sampler_reg);
> +
>     uint32_t gather_channel(unsigned gather_component, uint32_t sampler);
>     src_reg emit_mcs_fetch(const glsl_type *coordinate_type, src_reg coordinate,
>                            src_reg sampler);
> diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
> index 82b93fa..ec68919 100644
> --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
> @@ -2509,6 +2509,185 @@ vec4_visitor::is_high_sampler(src_reg sampler)
>  }
>
>  void
> +vec4_visitor::emit_texture(ir_texture_opcode op,
> +                           dst_reg dest,
> +                           const glsl_type *dest_type,
> +                           src_reg coordinate,
> +                           int coord_components,
> +                           bool shadow_compare,
> +                           src_reg shadow_comparitor,
> +                           src_reg lod, src_reg lod2,
> +                           src_reg sample_index,
> +                           bool has_nonconstant_offset,
> +                           uint32_t constant_offset,
> +                           src_reg offset_value,
> +                           src_reg mcs,
> +                           bool is_cube_array,
> +                           uint32_t sampler,
> +                           src_reg sampler_reg)
> +{
> +   enum opcode opcode;
> +   switch (op) {
> +   case ir_tex: opcode = SHADER_OPCODE_TXL; break;
> +   case ir_txl: opcode = SHADER_OPCODE_TXL; break;
> +   case ir_txd: opcode = SHADER_OPCODE_TXD; break;
> +   case ir_txf: opcode = SHADER_OPCODE_TXF; break;
> +   case ir_txf_ms: opcode = SHADER_OPCODE_TXF_CMS; break;
> +   case ir_txs: opcode = SHADER_OPCODE_TXS; break;
> +   case ir_tg4: opcode = has_nonconstant_offset
> +                         ? SHADER_OPCODE_TG4_OFFSET : SHADER_OPCODE_TG4; break;
> +   case ir_query_levels: opcode = SHADER_OPCODE_TXS; break;
> +   case ir_txb:
> +      unreachable("TXB is not valid for vertex shaders.");
> +   case ir_lod:
> +      unreachable("LOD is not valid for vertex shaders.");
> +   default:
> +      unreachable("Unrecognized tex op");
> +   }
> +
> +   vec4_instruction *inst = new(mem_ctx) vec4_instruction(
> +      opcode, dst_reg(this, dest_type));
> +
> +   inst->offset = constant_offset;
> +
> +   /* The message header is necessary for:
> +    * - Gen4 (always)
> +    * - Gen9+ for selecting SIMD4x2
> +    * - Texel offsets
> +    * - Gather channel selection
> +    * - Sampler indices too large to fit in a 4-bit value.
> +    */
> +   inst->header_size =
> +      (devinfo->gen < 5 || devinfo->gen >= 9 ||
> +       inst->offset != 0 || op == ir_tg4 ||
> +       is_high_sampler(sampler_reg)) ? 1 : 0;
> +   inst->base_mrf = 2;
> +   inst->mlen = inst->header_size + 1; /* always at least one */
> +   inst->dst.writemask = WRITEMASK_XYZW;
> +   inst->shadow_compare = shadow_compare;
> +
> +   inst->src[1] = sampler_reg;
> +
> +   /* MRF for the first parameter */
> +   int param_base = inst->base_mrf + inst->header_size;
> +
> +   if (op == ir_txs || op == ir_query_levels) {
> +      int writemask = devinfo->gen == 4 ? WRITEMASK_W : WRITEMASK_X;
> +      emit(MOV(dst_reg(MRF, param_base, lod.type, writemask), lod));
> +   } else {
> +      /* Load the coordinate */
> +      /* FINISHME: gl_clamp_mask and saturate */
> +      int coord_mask = (1 << coord_components) - 1;
> +      int zero_mask = 0xf & ~coord_mask;
> +
> +      emit(MOV(dst_reg(MRF, param_base, coordinate.type, coord_mask),
> +               coordinate));
> +
> +      if (zero_mask != 0) {
> +         emit(MOV(dst_reg(MRF, param_base, coordinate.type, zero_mask),
> +                  src_reg(0)));
> +      }
> +      /* Load the shadow comparitor */
> +      if (shadow_compare && op != ir_txd && (op != ir_tg4 || !has_nonconstant_offset)) {
> +        emit(MOV(dst_reg(MRF, param_base + 1, shadow_comparitor.type,
> +                         WRITEMASK_X),
> +                 shadow_comparitor));
> +        inst->mlen++;
> +      }
> +
> +      /* Load the LOD info */
> +      if (op == ir_tex || op == ir_txl) {
> +        int mrf, writemask;
> +        if (devinfo->gen >= 5) {
> +           mrf = param_base + 1;
> +           if (shadow_compare) {
> +              writemask = WRITEMASK_Y;
> +              /* mlen already incremented */
> +           } else {
> +              writemask = WRITEMASK_X;
> +              inst->mlen++;
> +           }
> +        } else /* devinfo->gen == 4 */ {
> +           mrf = param_base;
> +           writemask = WRITEMASK_W;
> +        }
> +         lod.swizzle = BRW_SWIZZLE_XXXX;
> +        emit(MOV(dst_reg(MRF, mrf, lod.type, writemask), lod));
> +      } else if (op == ir_txf) {
> +         emit(MOV(dst_reg(MRF, param_base, lod.type, WRITEMASK_W), lod));
> +      } else if (op == ir_txf_ms) {
> +         emit(MOV(dst_reg(MRF, param_base + 1, sample_index.type, WRITEMASK_X),
> +                  sample_index));
> +         if (devinfo->gen >= 7) {
> +            /* MCS data is in the first channel of `mcs`, but we need to get it into
> +             * the .y channel of the second vec4 of params, so replicate .x across
> +             * the whole vec4 and then mask off everything except .y
> +             */
> +            mcs.swizzle = BRW_SWIZZLE_XXXX;
> +            emit(MOV(dst_reg(MRF, param_base + 1, glsl_type::uint_type, WRITEMASK_Y),
> +                     mcs));
> +         }
> +         inst->mlen++;
> +      } else if (op == ir_txd) {
> +         const brw_reg_type type = lod.type;
> +
> +        if (devinfo->gen >= 5) {
> +           lod.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
> +           lod2.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
> +           emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XZ), lod));
> +           emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_YW), lod2));
> +           inst->mlen++;
> +
> +           if (dest_type->vector_elements == 3 || shadow_compare) {
> +              lod.swizzle = BRW_SWIZZLE_ZZZZ;
> +              lod2.swizzle = BRW_SWIZZLE_ZZZZ;
> +              emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_X), lod));
> +              emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_Y), lod2));
> +              inst->mlen++;
> +
> +               if (shadow_compare) {
> +                  emit(MOV(dst_reg(MRF, param_base + 2,
> +                                   shadow_comparitor.type, WRITEMASK_Z),
> +                           shadow_comparitor));
> +               }
> +           }
> +        } else /* devinfo->gen == 4 */ {
> +           emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XYZ), lod));
> +           emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_XYZ), lod2));
> +           inst->mlen += 2;
> +        }
> +      } else if (op == ir_tg4 && has_nonconstant_offset) {
> +         if (shadow_compare) {
> +            emit(MOV(dst_reg(MRF, param_base, shadow_comparitor.type, WRITEMASK_W),
> +                     shadow_comparitor));
> +         }
> +
> +         emit(MOV(dst_reg(MRF, param_base + 1, glsl_type::ivec2_type, WRITEMASK_XY),
> +                  offset_value));
> +         inst->mlen++;
> +      }
> +   }
> +
> +   emit(inst);
> +
> +   /* fixup num layers (z) for cube arrays: hardware returns faces * layers;
> +    * spec requires layers.
> +    */
> +   if (op == ir_txs && is_cube_array) {
> +      emit_math(SHADER_OPCODE_INT_QUOTIENT,
> +                writemask(inst->dst, WRITEMASK_Z),
> +                src_reg(inst->dst), src_reg(6));
> +   }
> +
> +   if (devinfo->gen == 6 && op == ir_tg4) {
> +      emit_gen6_gather_wa(key->tex.gen6_gather_wa[sampler], inst->dst);
> +   }
> +
> +   swizzle_result(op, dest,
> +                  src_reg(inst->dst), sampler, dest_type);
> +}
> +
> +void
>  vec4_visitor::visit(ir_texture *ir)
>  {
>     uint32_t sampler =
> @@ -2573,7 +2752,9 @@ vec4_visitor::visit(ir_texture *ir)
>      * generating these values may involve SEND messages that need the MRFs.
>      */
>     src_reg coordinate;
> +   int coord_components = 0;
>     if (ir->coordinate) {
> +      coord_components = ir->coordinate->type->vector_elements;
>        ir->coordinate->accept(this);
>        coordinate = this->result;
>     }
> @@ -2591,28 +2772,23 @@ vec4_visitor::visit(ir_texture *ir)
>        offset_value = src_reg(this->result);
>     }
>
> -   const glsl_type *lod_type = NULL, *sample_index_type = NULL;
> -   src_reg lod, dPdx, dPdy, sample_index, mcs;
> +   src_reg lod, lod2, sample_index, mcs;
>     switch (ir->op) {
>     case ir_tex:
>        lod = src_reg(0.0f);
> -      lod_type = glsl_type::float_type;
>        break;
>     case ir_txf:
>     case ir_txl:
>     case ir_txs:
>        ir->lod_info.lod->accept(this);
>        lod = this->result;
> -      lod_type = ir->lod_info.lod->type;
>        break;
>     case ir_query_levels:
>        lod = src_reg(0);
> -      lod_type = glsl_type::int_type;
>        break;
>     case ir_txf_ms:
>        ir->lod_info.sample_index->accept(this);
>        sample_index = this->result;
> -      sample_index_type = ir->lod_info.sample_index->type;
>
>        if (devinfo->gen >= 7 && key->tex.compressed_multisample_layout_mask & (1<<sampler))
>           mcs = emit_mcs_fetch(ir->coordinate->type, coordinate, sampler_reg);
> @@ -2621,12 +2797,10 @@ vec4_visitor::visit(ir_texture *ir)
>        break;
>     case ir_txd:
>        ir->lod_info.grad.dPdx->accept(this);
> -      dPdx = this->result;
> +      lod = this->result;
>
>        ir->lod_info.grad.dPdy->accept(this);
> -      dPdy = this->result;
> -
> -      lod_type = ir->lod_info.grad.dPdx->type;
> +      lod2 = this->result;
>        break;
>     case ir_txb:
>     case ir_lod:
> @@ -2634,181 +2808,31 @@ vec4_visitor::visit(ir_texture *ir)
>        break;
>     }
>
> -   enum opcode opcode;
> -   switch (ir->op) {
> -   case ir_tex: opcode = SHADER_OPCODE_TXL; break;
> -   case ir_txl: opcode = SHADER_OPCODE_TXL; break;
> -   case ir_txd: opcode = SHADER_OPCODE_TXD; break;
> -   case ir_txf: opcode = SHADER_OPCODE_TXF; break;
> -   case ir_txf_ms: opcode = SHADER_OPCODE_TXF_CMS; break;
> -   case ir_txs: opcode = SHADER_OPCODE_TXS; break;
> -   case ir_tg4: opcode = has_nonconstant_offset
> -                         ? SHADER_OPCODE_TG4_OFFSET : SHADER_OPCODE_TG4; break;
> -   case ir_query_levels: opcode = SHADER_OPCODE_TXS; break;
> -   case ir_txb:
> -      unreachable("TXB is not valid for vertex shaders.");
> -   case ir_lod:
> -      unreachable("LOD is not valid for vertex shaders.");
> -   default:
> -      unreachable("Unrecognized tex op");
> -   }
> -
> -   vec4_instruction *inst = new(mem_ctx) vec4_instruction(
> -      opcode, dst_reg(this, ir->type));
> -
> +   uint32_t constant_offset = 0;
>     if (ir->offset != NULL && !has_nonconstant_offset) {
> -      inst->offset =
> +      constant_offset  =
>           brw_texture_offset(ir->offset->as_constant()->value.i,
>                              ir->offset->type->vector_elements);
>     }
>
>     /* Stuff the channel select bits in the top of the texture offset */
>     if (ir->op == ir_tg4)
> -      inst->offset |=
> -        gather_channel( ir->lod_info.component->as_constant()->value.i[0],
> -                        sampler) << 16;
> +      constant_offset |=
> +         gather_channel( ir->lod_info.component->as_constant()->value.i[0],
> +                         sampler) << 16;
>
> -   /* The message header is necessary for:
> -    * - Gen4 (always)
> -    * - Gen9+ for selecting SIMD4x2
> -    * - Texel offsets
> -    * - Gather channel selection
> -    * - Sampler indices too large to fit in a 4-bit value.
> -    */
> -   inst->header_size =
> -      (devinfo->gen < 5 || devinfo->gen >= 9 ||
> -       inst->offset != 0 || ir->op == ir_tg4 ||
> -       is_high_sampler(sampler_reg)) ? 1 : 0;
> -   inst->base_mrf = 2;
> -   inst->mlen = inst->header_size + 1; /* always at least one */
> -   inst->dst.writemask = WRITEMASK_XYZW;
> -   inst->shadow_compare = ir->shadow_comparitor != NULL;
> -
> -   inst->src[1] = sampler_reg;
> -
> -   /* MRF for the first parameter */
> -   int param_base = inst->base_mrf + inst->header_size;
> -
> -   if (ir->op == ir_txs || ir->op == ir_query_levels) {
> -      int writemask = devinfo->gen == 4 ? WRITEMASK_W : WRITEMASK_X;
> -      emit(MOV(dst_reg(MRF, param_base, lod_type, writemask), lod));
> -   } else {
> -      /* Load the coordinate */
> -      /* FINISHME: gl_clamp_mask and saturate */
> -      int coord_mask = (1 << ir->coordinate->type->vector_elements) - 1;
> -      int zero_mask = 0xf & ~coord_mask;
> -
> -      emit(MOV(dst_reg(MRF, param_base, ir->coordinate->type, coord_mask),
> -               coordinate));
> -
> -      if (zero_mask != 0) {
> -         emit(MOV(dst_reg(MRF, param_base, ir->coordinate->type, zero_mask),
> -                  src_reg(0)));
> -      }
> -      /* Load the shadow comparitor */
> -      if (ir->shadow_comparitor && ir->op != ir_txd && (ir->op != ir_tg4 || !has_nonconstant_offset)) {
> -        emit(MOV(dst_reg(MRF, param_base + 1, ir->shadow_comparitor->type,
> -                         WRITEMASK_X),
> -                 shadow_comparitor));
> -        inst->mlen++;
> -      }
> -
> -      /* Load the LOD info */
> -      if (ir->op == ir_tex || ir->op == ir_txl) {
> -        int mrf, writemask;
> -        if (devinfo->gen >= 5) {
> -           mrf = param_base + 1;
> -           if (ir->shadow_comparitor) {
> -              writemask = WRITEMASK_Y;
> -              /* mlen already incremented */
> -           } else {
> -              writemask = WRITEMASK_X;
> -              inst->mlen++;
> -           }
> -        } else /* devinfo->gen == 4 */ {
> -           mrf = param_base;
> -           writemask = WRITEMASK_W;
> -        }
> -        emit(MOV(dst_reg(MRF, mrf, lod_type, writemask), lod));
> -      } else if (ir->op == ir_txf) {
> -         emit(MOV(dst_reg(MRF, param_base, lod_type, WRITEMASK_W), lod));
> -      } else if (ir->op == ir_txf_ms) {
> -         emit(MOV(dst_reg(MRF, param_base + 1, sample_index_type, WRITEMASK_X),
> -                  sample_index));
> -         if (devinfo->gen >= 7) {
> -            /* MCS data is in the first channel of `mcs`, but we need to get it into
> -             * the .y channel of the second vec4 of params, so replicate .x across
> -             * the whole vec4 and then mask off everything except .y
> -             */
> -            mcs.swizzle = BRW_SWIZZLE_XXXX;
> -            emit(MOV(dst_reg(MRF, param_base + 1, glsl_type::uint_type, WRITEMASK_Y),
> -                     mcs));
> -         }
> -         inst->mlen++;
> -      } else if (ir->op == ir_txd) {
> -        const glsl_type *type = lod_type;
> -
> -        if (devinfo->gen >= 5) {
> -           dPdx.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
> -           dPdy.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
> -           emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XZ), dPdx));
> -           emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_YW), dPdy));
> -           inst->mlen++;
> -
> -           if (ir->type->vector_elements == 3 || ir->shadow_comparitor) {
> -              dPdx.swizzle = BRW_SWIZZLE_ZZZZ;
> -              dPdy.swizzle = BRW_SWIZZLE_ZZZZ;
> -              emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_X), dPdx));
> -              emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_Y), dPdy));
> -              inst->mlen++;
> -
> -               if (ir->shadow_comparitor) {
> -                  emit(MOV(dst_reg(MRF, param_base + 2,
> -                                   ir->shadow_comparitor->type, WRITEMASK_Z),
> -                           shadow_comparitor));
> -               }
> -           }
> -        } else /* devinfo->gen == 4 */ {
> -           emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XYZ), dPdx));
> -           emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_XYZ), dPdy));
> -           inst->mlen += 2;
> -        }
> -      } else if (ir->op == ir_tg4 && has_nonconstant_offset) {
> -         if (ir->shadow_comparitor) {
> -            emit(MOV(dst_reg(MRF, param_base, ir->shadow_comparitor->type, WRITEMASK_W),
> -                     shadow_comparitor));
> -         }
> -
> -         emit(MOV(dst_reg(MRF, param_base + 1, glsl_type::ivec2_type, WRITEMASK_XY),
> -                  offset_value));
> -         inst->mlen++;
> -      }
> -   }
> -
> -   emit(inst);
> -
> -   /* fixup num layers (z) for cube arrays: hardware returns faces * layers;
> -    * spec requires layers.
> -    */
> -   if (ir->op == ir_txs) {
> -      glsl_type const *type = ir->sampler->type;
> -      if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE &&
> -          type->sampler_array) {
> -         emit_math(SHADER_OPCODE_INT_QUOTIENT,
> -                   writemask(inst->dst, WRITEMASK_Z),
> -                   src_reg(inst->dst), src_reg(6));
> -      }
> -   }
> -
> -   if (devinfo->gen == 6 && ir->op == ir_tg4) {
> -      emit_gen6_gather_wa(key->tex.gen6_gather_wa[sampler], inst->dst);
> -   }
> +   glsl_type const *type = ir->sampler->type;
> +   bool is_cube_array = type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE &&
> +      type->sampler_array;
>
>     this->result = src_reg(this, ir->type);
>     dst_reg dest = dst_reg(this->result);
>
> -   swizzle_result(ir->op, dest, src_reg(inst->dst),
> -                  sampler, ir->type);
> +   emit_texture(ir->op, dest, ir->type, coordinate, coord_components,
> +                ir->shadow_comparitor != NULL, 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