[Mesa-dev] [PATCH 2/5] i965: Add support for swizzling arbitrary immediates to (brw_)swizzle().
Francisco Jerez
currojerez at riseup.net
Tue Mar 1 00:48:24 UTC 2016
Iago Toral <itoral at igalia.com> writes:
> 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.
>
Heh, I did that mainly out of laziness because it was less noise than
declaring a new variable. It shouldn't make any practical difference
-- Or was your suggestion on purely stylistic grounds?
>> + 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... ;)
>
Sure, I'll throw in some more comments.
> The implementation looks correct to me:
> Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
>
Thanks.
>> + 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;
>> }
>>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 212 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20160229/41693e0d/attachment.sig>
More information about the mesa-dev
mailing list