gallium: add new LOD opcode
authorRoland Scheidegger <sroland@vmware.com>
Thu, 28 Sep 2017 01:45:04 +0000 (03:45 +0200)
committerRoland Scheidegger <sroland@vmware.com>
Sat, 30 Sep 2017 00:58:09 +0000 (02:58 +0200)
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).

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
Acked-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
src/gallium/auxiliary/tgsi/tgsi_exec.c
src/gallium/auxiliary/tgsi/tgsi_info_opcodes.h
src/gallium/docs/source/tgsi.rst
src/gallium/include/pipe/p_shader_tokens.h

index e5d0293b8f9cb53a6f7ee84d8ad720797d84a673..de18f629cd06d933620431faef661e3b87decb9f 100644 (file)
@@ -3284,6 +3284,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)
 {
@@ -3898,6 +3910,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
index 9c019a311d7f8797c6a6475ae848c29326b51f70..afed96c9b1db6f90606594d783c48d45bcb495c3 100644 (file)
@@ -2351,15 +2351,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++) {
@@ -2369,7 +2376,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,
@@ -2386,6 +2393,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
@@ -5718,6 +5754,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;
index fdb0f1078a1eba79ccfedcf83ee4ec017b302d8f..1b2803cf3fe669c669089b0605d1b959cba4cdb7 100644 (file)
@@ -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)
index 274646703b44f1f56260eb531714afb57771bf48..551e9dd379f035ae54c3b322f102b0b02f7a4866 100644 (file)
@@ -2479,6 +2479,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
index a5adedd9875b475f315f74d22f741d1197a8541f..97deef738309b42e72cdd2cdd7477ca0cfd8ce9f 100644 (file)
@@ -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