tgsi: handle texel swizzles correctly for d3d10-style sample opcodes
authorRoland Scheidegger <sroland@vmware.com>
Fri, 26 Jul 2013 19:39:27 +0000 (21:39 +0200)
committerRoland Scheidegger <sroland@vmware.com>
Sat, 27 Jul 2013 14:41:29 +0000 (16:41 +0200)
Same as for gallivm (though these don't quite work correctly in softpipe,
so untested).

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
src/gallium/auxiliary/tgsi/tgsi_exec.c

index 1f8e62d6f3eed11e85cade81eae71ff27aa084a8..3ac69017a80035a7e3613775546682f7fa5e7bb9 100644 (file)
@@ -2041,9 +2041,25 @@ exec_txf(struct tgsi_exec_machine *mach,
       r[3].f[j] = rgba[3][j];
    }
 
-   for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
-      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
-         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+   if (inst->Instruction.Opcode == TGSI_OPCODE_SAMPLE_I) {
+      unsigned char swizzles[4];
+      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)) {
+            store_dest(mach, &r[swizzles[chan]],
+                       &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+         }
+      }
+   }
+   else {
+      for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
+         if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+            store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+         }
       }
    }
 }
@@ -2087,6 +2103,7 @@ exec_sample(struct tgsi_exec_machine *mach,
    const union tgsi_exec_channel *lod = &ZeroVec;
    enum tgsi_sampler_control control = tgsi_sampler_lod_none;
    uint chan;
+   unsigned char swizzles[4];
    int8_t offsets[3];
 
    /* always fetch all 3 offsets, overkill but keeps code simple */
@@ -2193,9 +2210,15 @@ exec_sample(struct tgsi_exec_machine *mach,
       assert(0);
    }
 
+   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)) {
-         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+         store_dest(mach, &r[swizzles[chan]],
+                    &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
       }
    }
 }
@@ -2209,6 +2232,7 @@ exec_sample_d(struct tgsi_exec_machine *mach,
    union tgsi_exec_channel r[4];
    float derivs[3][2][TGSI_QUAD_SIZE];
    uint chan;
+   unsigned char swizzles[4];
    int8_t offsets[3];
 
    /* always fetch all 3 offsets, overkill but keeps code simple */
@@ -2268,9 +2292,15 @@ exec_sample_d(struct tgsi_exec_machine *mach,
       assert(0);
    }
 
+   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)) {
-         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+         store_dest(mach, &r[swizzles[chan]],
+                    &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
       }
    }
 }