[Mesa-dev] [PATCH 6/7] i965/fs: add support for gather4 with nonconstant offsets

Kenneth Graunke kenneth at whitecape.org
Sat Oct 26 00:33:44 PDT 2013


On 10/08/2013 02:35 AM, Chris Forbes wrote:
> Signed-off-by: Chris Forbes <chrisf at ijw.co.nz>
> ---
>  src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 45 ++++++++++++++++++++++++++--
>  1 file changed, 42 insertions(+), 3 deletions(-)
> 
> diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
> index 15cfaa7..fb27ad5 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
> @@ -1249,11 +1249,12 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate,
>        mlen += reg_width;
>     }
>  
> +   bool has_nonconstant_offset = ir->offset && !ir->offset->as_constant();
> +
>     /* Set up the LOD info */
>     switch (ir->op) {
>     case ir_tex:
>     case ir_lod:
> -   case ir_tg4:
>        break;
>     case ir_txb:
>        emit(MOV(fs_reg(MRF, base_mrf + mlen), lod));
> @@ -1350,10 +1351,43 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate,
>           mlen += reg_width;
>        }
>        break;
> +   case ir_tg4:
> +      if (has_nonconstant_offset) {
> +         /* More crazy intermixing */
> +         ir->offset->accept(this);
> +         fs_reg offset_value = this->result;
> +
> +         for (int i = 0; i < 2; i++) { /* u, v */
> +            emit(MOV(fs_reg(MRF, base_mrf + mlen), coordinate));
> +            coordinate.reg_offset++;
> +            mlen += reg_width;
> +         }
> +
> +         for (int i = 0; i < 2; i++) { /* offu, offv */
> +            emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), offset_value));
> +            offset_value.reg_offset++;
> +            mlen += reg_width;
> +         }
> +
> +         if (ir->coordinate->type->vector_elements == 3) { /* r if present */
> +            emit(MOV(fs_reg(MRF, base_mrf + mlen), coordinate));
> +            coordinate.reg_offset++;
> +            mlen += reg_width;
> +         }
> +      }
> +      else {
> +         /* just do the usual thing */
> +         for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
> +            emit(MOV(fs_reg(MRF, base_mrf + mlen), coordinate));
> +            coordinate.reg_offset++;
> +            mlen += reg_width;
> +         }
> +      }
> +      break;
>     }
>  
>     /* Set up the coordinate (except for cases where it was done above) */
> -   if (ir->op != ir_txd && ir->op != ir_txs && ir->op != ir_txf && ir->op != ir_txf_ms && ir->op != ir_query_levels) {
> +   if (ir->op != ir_txd && ir->op != ir_txs && ir->op != ir_txf && ir->op != ir_txf_ms && ir->op != ir_query_levels && ir->op != ir_tg4) {

Egads, this has gotten out of hand.  How about:

if (ir->coordinate && ir->op != ir_txd &&
    !(ir->op == ir_tg4 && has_non_constant_offset))

Then you could also drop the /* just do the usual thing */ clause above
(which duplicates this code).

>        for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
>  	 emit(MOV(fs_reg(MRF, base_mrf + mlen), coordinate));
>  	 coordinate.reg_offset++;
> @@ -1373,7 +1407,12 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate,
>     case ir_txs: inst = emit(SHADER_OPCODE_TXS, dst); break;
>     case ir_query_levels: inst = emit(SHADER_OPCODE_TXS, dst); break;
>     case ir_lod: inst = emit(SHADER_OPCODE_LOD, dst); break;
> -   case ir_tg4: inst = emit(SHADER_OPCODE_TG4, dst); break;
> +   case ir_tg4:
> +      if (has_nonconstant_offset)
> +         inst = emit(SHADER_OPCODE_TG4_OFFSET, dst);
> +      else
> +         inst = emit(SHADER_OPCODE_TG4, dst);
> +      break;
>     }
>     inst->base_mrf = base_mrf;
>     inst->mlen = mlen;
> 



More information about the mesa-dev mailing list