[Mesa-dev] [PATCH] gallium: add new LOD opcode

Nicolai Hähnle nhaehnle at gmail.com
Thu Sep 28 13:54:16 UTC 2017


On 28.09.2017 03:46, sroland at vmware.com wrote:
> From: Roland Scheidegger <sroland at vmware.com>
> 
> The operation performed is all the same as LODQ, but with the usual
> differences between dx10 and GL texture opcodes, that is separate resource
> and sampler indices (plus result swizzling, and setting z/w channels
> to zero).

Acked-by: Nicolai Hähnle <nicolai.haehnle at amd.com>


> ---
>   src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 14 ++++++++
>   src/gallium/auxiliary/tgsi/tgsi_exec.c          | 48 ++++++++++++++++++++++---
>   src/gallium/auxiliary/tgsi/tgsi_info_opcodes.h  |  1 +
>   src/gallium/docs/source/tgsi.rst                | 12 +++++++
>   src/gallium/include/pipe/p_shader_tokens.h      |  4 ++-
>   5 files changed, 74 insertions(+), 5 deletions(-)
> 
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> index 3e47372..fe0068b 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> @@ -3285,6 +3285,18 @@ sviewinfo_emit(
>      emit_size_query(bld, emit_data->inst, emit_data->output, TRUE);
>   }
>   
> +static void
> +lod_emit(
> +   const struct lp_build_tgsi_action * action,
> +   struct lp_build_tgsi_context * bld_base,
> +   struct lp_build_emit_data * emit_data)
> +{
> +   struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
> +
> +   emit_sample(bld, emit_data->inst, LP_BLD_TEX_MODIFIER_NONE,
> +               FALSE, LP_SAMPLER_OP_LODQ, emit_data->output);
> +}
> +
>   static LLVMValueRef
>   mask_vec(struct lp_build_tgsi_context *bld_base)
>   {
> @@ -3899,6 +3911,8 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
>      bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_L].emit = sample_l_emit;
>      bld.bld_base.op_actions[TGSI_OPCODE_GATHER4].emit = gather4_emit;
>      bld.bld_base.op_actions[TGSI_OPCODE_SVIEWINFO].emit = sviewinfo_emit;
> +   bld.bld_base.op_actions[TGSI_OPCODE_LOD].emit = lod_emit;
> +
>   
>      if (gs_iface) {
>         /* There's no specific value for this because it should always
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
> index 1264df0..4257a60 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
> +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
> @@ -2340,15 +2340,22 @@ static void
>   exec_lodq(struct tgsi_exec_machine *mach,
>             const struct tgsi_full_instruction *inst)
>   {
> -   uint unit;
> +   uint resource_unit, sampler_unit;
>      int dim;
>      int i;
>      union tgsi_exec_channel coords[4];
>      const union tgsi_exec_channel *args[ARRAY_SIZE(coords)];
>      union tgsi_exec_channel r[2];
>   
> -   unit = fetch_sampler_unit(mach, inst, 1);
> -   dim = tgsi_util_get_texture_coord_dim(inst->Texture.Texture);
> +   resource_unit = fetch_sampler_unit(mach, inst, 1);
> +   if (inst->Instruction.Opcode == TGSI_OPCODE_LOD) {
> +      uint target = mach->SamplerViews[resource_unit].Resource;
> +      dim = tgsi_util_get_texture_coord_dim(target);
> +      sampler_unit = fetch_sampler_unit(mach, inst, 2);
> +   } else {
> +      dim = tgsi_util_get_texture_coord_dim(inst->Texture.Texture);
> +      sampler_unit = resource_unit;
> +   }
>      assert(dim <= ARRAY_SIZE(coords));
>      /* fetch coordinates */
>      for (i = 0; i < dim; i++) {
> @@ -2358,7 +2365,7 @@ exec_lodq(struct tgsi_exec_machine *mach,
>      for (i = dim; i < ARRAY_SIZE(coords); i++) {
>         args[i] = &ZeroVec;
>      }
> -   mach->Sampler->query_lod(mach->Sampler, unit, unit,
> +   mach->Sampler->query_lod(mach->Sampler, resource_unit, sampler_unit,
>                               args[0]->f,
>                               args[1]->f,
>                               args[2]->f,
> @@ -2375,6 +2382,35 @@ exec_lodq(struct tgsi_exec_machine *mach,
>         store_dest(mach, &r[1], &inst->Dst[0], inst, TGSI_CHAN_Y,
>                    TGSI_EXEC_DATA_FLOAT);
>      }
> +   if (inst->Instruction.Opcode == TGSI_OPCODE_LOD) {
> +      unsigned char swizzles[4];
> +      unsigned chan;
> +      swizzles[0] = inst->Src[1].Register.SwizzleX;
> +      swizzles[1] = inst->Src[1].Register.SwizzleY;
> +      swizzles[2] = inst->Src[1].Register.SwizzleZ;
> +      swizzles[3] = inst->Src[1].Register.SwizzleW;
> +
> +      for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
> +         if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
> +            if (swizzles[chan] >= 2) {
> +               store_dest(mach, &ZeroVec,
> +                          &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
> +            } else {
> +               store_dest(mach, &r[swizzles[chan]],
> +                          &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
> +            }
> +         }
> +      }
> +   } else {
> +      if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
> +         store_dest(mach, &r[0], &inst->Dst[0], inst, TGSI_CHAN_X,
> +                    TGSI_EXEC_DATA_FLOAT);
> +      }
> +      if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
> +         store_dest(mach, &r[1], &inst->Dst[0], inst, TGSI_CHAN_Y,
> +                    TGSI_EXEC_DATA_FLOAT);
> +      }
> +   }
>   }
>   
>   static void
> @@ -5705,6 +5741,10 @@ exec_instruction(
>         assert(0);
>         break;
>   
> +   case TGSI_OPCODE_LOD:
> +      exec_lodq(mach, inst);
> +      break;
> +
>      case TGSI_OPCODE_UARL:
>         exec_vector_unary(mach, inst, micro_uarl, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_UINT);
>         break;
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_info_opcodes.h b/src/gallium/auxiliary/tgsi/tgsi_info_opcodes.h
> index a4a9771..95a29fd 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_info_opcodes.h
> +++ b/src/gallium/auxiliary/tgsi/tgsi_info_opcodes.h
> @@ -249,3 +249,4 @@ OPCODE(1, 2, COMP, U64DIV)
>   OPCODE(1, 2, COMP, I64MOD)
>   OPCODE(1, 2, COMP, U64MOD)
>   OPCODE(1, 2, COMP, DDIV)
> +OPCODE(1, 3, OTHR, LOD)
> diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst
> index 0bd9964..3f80785 100644
> --- a/src/gallium/docs/source/tgsi.rst
> +++ b/src/gallium/docs/source/tgsi.rst
> @@ -2469,6 +2469,18 @@ after lookup.
>     NOTE: no driver has implemented this opcode yet (and no state tracker
>     emits it).  This information is subject to change.
>   
> +.. opcode:: LOD - level of detail
> +
> +   Same syntax as the SAMPLE opcode but instead of performing an actual
> +   texture lookup/filter, return the computed LOD information that the
> +   texture pipe would use to access the texture. The Y component contains
> +   the computed LOD lambda_prime. The X component contains the LOD that will
> +   be accessed, based on min/max lod's and mipmap filters.
> +   The Z and W components are set to 0.
> +
> +   Syntax: ``LOD dst, address, sampler_view, sampler``
> +
> +
>   .. _resourceopcodes:
>   
>   Resource Access Opcodes
> diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
> index fa73054..0bb6739 100644
> --- a/src/gallium/include/pipe/p_shader_tokens.h
> +++ b/src/gallium/include/pipe/p_shader_tokens.h
> @@ -607,7 +607,9 @@ struct tgsi_property_data {
>   
>   #define TGSI_OPCODE_DDIV                248
>   
> -#define TGSI_OPCODE_LAST                249
> +#define TGSI_OPCODE_LOD                 249
> +
> +#define TGSI_OPCODE_LAST                250
>   
>   /**
>    * Opcode is the operation code to execute. A given operation defines the
> 


-- 
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.


More information about the mesa-dev mailing list