[Mesa-dev] [PATCH 2/5] i965: Add support for swizzling arbitrary immediates to (brw_)swizzle().
Iago Toral
itoral at igalia.com
Mon Feb 29 15:15:31 UTC 2016
On Fri, 2016-02-26 at 22:02 -0800, Francisco Jerez wrote:
> 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.
> ---
> src/mesa/drivers/dri/i965/brw_eu.c | 39 +++++++++++++++++++++++++++++++++
> src/mesa/drivers/dri/i965/brw_ir_vec4.h | 6 ++++-
> src/mesa/drivers/dri/i965/brw_reg.h | 7 ++++--
> 3 files changed, 49 insertions(+), 3 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_eu.c b/src/mesa/drivers/dri/i965/brw_eu.c
> index 40ec87d..36bdc7c 100644
> --- a/src/mesa/drivers/dri/i965/brw_eu.c
> +++ b/src/mesa/drivers/dri/i965/brw_eu.c
> @@ -110,6 +110,45 @@ 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)
> +{
> + 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;
> +}
> +
> +/**
> + * 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);
You can assign imm_shift(type, 1) to a variable before the if and reuse
it here.
> + uint32_t y = 0;
> +
> + for (unsigned i = 0; i < n; i++)
> + y |= x >> imm_shift(type, (i & ~3) + BRW_GET_SWZ(swz, i & 3))
> + << imm_shift(type, ~0u)
> + >> imm_shift(type, ~0u - i);
> +
Ugh, took me a while to understand what this was doing even with the
comment in imm_shift(). Another comment here explaining what this series
of operations are doing might save future readers some time... ;)
The implementation looks correct to me:
Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
> + 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 660beca..2b6872e 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 a4bcfca..74ff67f 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;
> }
>
More information about the mesa-dev
mailing list