i965: Add support for swizzling arbitrary immediates to (brw_)swizzle().
authorFrancisco Jerez <currojerez@riseup.net>
Sat, 27 Feb 2016 01:12:27 +0000 (17:12 -0800)
committerFrancisco Jerez <currojerez@riseup.net>
Sun, 6 Mar 2016 20:22:40 +0000 (12:22 -0800)
Scalar immediates used to be handled correctly by swizzle() (as the
identity) but since commit 58fa9d47b536403c4e3ca5d6a2495691338388fd it
will corrupt the contents of the immediate.  Vector immediates were
never handled correctly, but we had ad-hoc code to swizzle VF
immediates in the vec4 copy propagation pass.  This takes care of
swizzling V and UV in addition.

v2: Don't implement swizzling of V/UV immediates (Matt).  If you need
    to swizzle an integer vector immediate in the future apply the
    following diff to go back to v1:

--- a/src/mesa/drivers/dri/i965/brw_eu.c
+++ b/src/mesa/drivers/dri/i965/brw_eu.c
@@ -119,11 +119,10 @@ brw_swap_cmod(uint32_t cmod)
 static unsigned
 imm_shift(enum brw_reg_type type, unsigned i)
 {
-   assert(type != BRW_REGISTER_TYPE_UV && type != BRW_REGISTER_TYPE_V &&
-          "Not implemented.");
-
    if (type == BRW_REGISTER_TYPE_VF)
       return 8 * (i & 3);
+   else if (type == BRW_REGISTER_TYPE_UV || type == BRW_REGISTER_TYPE_V)
+      return 4 * (i & 7);
    else
       return 0;
 }

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
src/mesa/drivers/dri/i965/brw_eu.c
src/mesa/drivers/dri/i965/brw_ir_vec4.h
src/mesa/drivers/dri/i965/brw_reg.h

index 40ec87d38f05ef182744aaeb142669ecf2b617b3..6961a88c6a8318c45b48e002aa2051ca0cb2d83f 100644 (file)
@@ -110,6 +110,50 @@ brw_swap_cmod(uint32_t cmod)
    }
 }
 
+/**
+ * Get the least significant bit offset of the i+1-th component of immediate
+ * type \p type.  For \p i equal to the two's complement of j, return the
+ * offset of the j-th component starting from the end of the vector.  For
+ * scalar register types return zero.
+ */
+static unsigned
+imm_shift(enum brw_reg_type type, unsigned i)
+{
+   assert(type != BRW_REGISTER_TYPE_UV && type != BRW_REGISTER_TYPE_V &&
+          "Not implemented.");
+
+   if (type == BRW_REGISTER_TYPE_VF)
+      return 8 * (i & 3);
+   else
+      return 0;
+}
+
+/**
+ * Swizzle an arbitrary immediate \p x of the given type according to the
+ * permutation specified as \p swz.
+ */
+uint32_t
+brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz)
+{
+   if (imm_shift(type, 1)) {
+      const unsigned n = 32 / imm_shift(type, 1);
+      uint32_t y = 0;
+
+      for (unsigned i = 0; i < n; i++) {
+         /* Shift the specified component all the way to the right and left to
+          * discard any undesired L/MSBs, then shift it right into component i.
+          */
+         y |= x >> imm_shift(type, (i & ~3) + BRW_GET_SWZ(swz, i & 3))
+                << imm_shift(type, ~0u)
+                >> imm_shift(type, ~0u - i);
+      }
+
+      return y;
+   } else {
+      return x;
+   }
+}
+
 void
 brw_set_default_exec_size(struct brw_codegen *p, unsigned value)
 {
index 660becaafa74703cdc2cfabd11799aa594d93aed..2b6872e6d318c10a9f18f46d8fa6daf714884a24 100644 (file)
@@ -76,7 +76,11 @@ offset(src_reg reg, unsigned delta)
 static inline src_reg
 swizzle(src_reg reg, unsigned swizzle)
 {
-   reg.swizzle = brw_compose_swizzle(swizzle, reg.swizzle);
+   if (reg.file == IMM)
+      reg.ud = brw_swizzle_immediate(reg.type, reg.ud, swizzle);
+   else
+      reg.swizzle = brw_compose_swizzle(swizzle, reg.swizzle);
+
    return reg;
 }
 
index a4bcfca0b1d8cdbd7ffff6b28d459c562970e88b..74ff67fca5f97141392a471f79c0301d0ca0dc6c 100644 (file)
@@ -223,6 +223,7 @@ enum PACKED brw_reg_type {
 unsigned brw_reg_type_to_hw_type(const struct brw_device_info *devinfo,
                                  enum brw_reg_type type, enum brw_reg_file file);
 const char *brw_reg_type_letters(unsigned brw_reg_type);
+uint32_t brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz);
 
 #define REG_SIZE (8*4)
 
@@ -876,9 +877,11 @@ get_element_d(struct brw_reg reg, unsigned elt)
 static inline struct brw_reg
 brw_swizzle(struct brw_reg reg, unsigned swz)
 {
-   assert(reg.file != BRW_IMMEDIATE_VALUE);
+   if (reg.file == BRW_IMMEDIATE_VALUE)
+      reg.ud = brw_swizzle_immediate(reg.type, reg.ud, swz);
+   else
+      reg.swizzle = brw_compose_swizzle(swz, reg.swizzle);
 
-   reg.swizzle = brw_compose_swizzle(swz, reg.swizzle);
    return reg;
 }