diff options
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_eu.c | 44 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_ir_vec4.h | 6 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_reg.h | 7 |
3 files changed, 54 insertions, 3 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_eu.c b/src/mesa/drivers/dri/i965/brw_eu.c index 40ec87d38f0..6961a88c6a8 100644 --- a/src/mesa/drivers/dri/i965/brw_eu.c +++ b/src/mesa/drivers/dri/i965/brw_eu.c @@ -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) { diff --git a/src/mesa/drivers/dri/i965/brw_ir_vec4.h b/src/mesa/drivers/dri/i965/brw_ir_vec4.h index 660becaafa7..2b6872e6d31 100644 --- a/src/mesa/drivers/dri/i965/brw_ir_vec4.h +++ b/src/mesa/drivers/dri/i965/brw_ir_vec4.h @@ -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; } diff --git a/src/mesa/drivers/dri/i965/brw_reg.h b/src/mesa/drivers/dri/i965/brw_reg.h index a4bcfca0b1d..74ff67fca5f 100644 --- a/src/mesa/drivers/dri/i965/brw_reg.h +++ b/src/mesa/drivers/dri/i965/brw_reg.h @@ -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; } |