[Mesa-dev] [PATCH 06/23] i965: Define common register base class shared between both back-ends.
Francisco Jerez
currojerez at riseup.net
Wed Feb 12 10:56:07 PST 2014
Paul Berry <stereotype441 at gmail.com> writes:
> On 19 December 2013 13:30, Francisco Jerez <currojerez at riseup.net> wrote:
>
>> Paul Berry <stereotype441 at gmail.com> writes:
>>
>> > On 2 December 2013 11:31, Francisco Jerez <currojerez at riseup.net> wrote:
>> >
>> >> diff --git a/src/mesa/drivers/dri/i965/brw_shader.h
>> >> b/src/mesa/drivers/dri/i965/brw_shader.h
>> >> index ff5af93..f284389 100644
>> >> --- a/src/mesa/drivers/dri/i965/brw_shader.h
>> >> +++ b/src/mesa/drivers/dri/i965/brw_shader.h
>> >> @@ -23,6 +23,7 @@
>> >>
>> >> #include <stdint.h>
>> >> #include "brw_defines.h"
>> >> +#include "brw_reg.h"
>> >> #include "glsl/ir.h"
>> >>
>> >> #pragma once
>> >> @@ -39,6 +40,45 @@ enum register_file {
>> >>
>> >> #ifdef __cplusplus
>> >>
>> >> +class backend_reg {
>> >> +public:
>> >> + backend_reg();
>> >> + backend_reg(struct brw_reg reg);
>> >> +
>> >> + bool is_zero() const;
>> >> + bool is_one() const;
>> >> + bool is_null() const;
>> >> +
>> >> + /** Register file: GRF, MRF, IMM. */
>> >> + enum register_file file;
>> >> +
>> >> + /**
>> >> + * Register number. For MRF, it's the hardware register. For
>> >> + * GRF, it's a virtual register number until register allocation
>> >> + */
>> >> + int reg;
>> >> +
>> >> + /**
>> >> + * Offset from the start of the contiguous register block.
>> >> + *
>> >> + * For pre-register-allocation GRFs, this is in units of a float per
>> >> pixel
>> >> + * (1 hardware register for SIMD8 mode, or 2 registers for SIMD16
>> >> mode).
>> >>
>> >
>> > Since this code is now shared with the vec4 back-end, can we update this
>> > comment to say "1 hardware register for SIMD8 or SIMD4x2 mode..."?
>> >
>> >
>> >> + * For uniforms, this is in units of 1 float.
>> >> + */
>> >> + int reg_offset;
>> >> +
>> >> + /** Register type. BRW_REGISTER_TYPE_* */
>> >> + int type;
>> >> + struct brw_reg fixed_hw_reg;
>> >> +
>> >> + /** Value for file == BRW_IMMMEDIATE_FILE */
>> >> + union {
>> >> + int32_t i;
>> >> + uint32_t u;
>> >> + float f;
>> >> + } imm;
>> >> +};
>> >> +
>> >> class backend_instruction : public exec_node {
>> >> public:
>> >> bool is_tex();
>> >> diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h
>> >> b/src/mesa/drivers/dri/i965/brw_vec4.h
>> >> index 3b3f35b..a718333 100644
>> >> --- a/src/mesa/drivers/dri/i965/brw_vec4.h
>> >> +++ b/src/mesa/drivers/dri/i965/brw_vec4.h
>> >> @@ -89,28 +89,7 @@ class dst_reg;
>> >> unsigned
>> >> swizzle_for_size(int size);
>> >>
>> >> -class reg
>> >> -{
>> >> -public:
>> >> - /** Register file: GRF, MRF, IMM. */
>> >> - enum register_file file;
>> >> - /** virtual register number. 0 = fixed hw reg */
>> >> - int reg;
>> >> - /** Offset within the virtual register. */
>> >> - int reg_offset;
>> >> - /** Register type. BRW_REGISTER_TYPE_* */
>> >> - int type;
>> >> - struct brw_reg fixed_hw_reg;
>> >> -
>> >> - /** Value for file == BRW_IMMMEDIATE_FILE */
>> >> - union {
>> >> - int32_t i;
>> >> - uint32_t u;
>> >> - float f;
>> >> - } imm;
>> >> -};
>> >> -
>> >> -class src_reg : public reg
>> >> +class src_reg : public backend_reg
>> >> {
>> >> public:
>> >> DECLARE_RALLOC_CXX_OPERATORS(src_reg)
>> >> @@ -123,10 +102,9 @@ public:
>> >> src_reg(uint32_t u);
>> >> src_reg(int32_t i);
>> >> src_reg(struct brw_reg reg);
>> >> + src_reg(const backend_reg ®);
>> >>
>> >
>> > I'm concerned about this constructor (and the corresponding constructors
>> in
>> > the dst_reg and fs_reg classes) contributing to object slicing problems.
>> > Consider this code:
>> >
>> > src_reg r1;
>> > r1.swizzle = BRW_SWIZZLE_XXXX;
>> > backend_reg r2(r1);
>> > src_reg r3(r2);
>> > assert(r3.swizzle == BRW_SWIZZLE_XXXX); /* fails! */
>> >
>> > The reason for the failure is that src_reg::swizzle doesn't appear in the
>> > backend_reg base class. So when r1 is copied to r2, the value of swizzle
>> > is lost. That by itself wouldn't be a problem, except that when we later
>> > try to reconstruct a src_reg from r2, swizzle winds up being initialized
>> to
>> > the default value.
>> >
>> > Of course we would never write code like the above example directly, but
>> > since your shared code for implementing loads/stores (in future patches)
>> > uses backend_reg for all of its register representations, it seems likely
>> > that a src_reg will get converted to a backend_reg and then back to a
>> > src_reg at some point during compilation. So I suspect that when
>> compiling
>> > GLSL source code like the following:
>> >
>> > uniform image2D img;
>> > ivec2 coord;
>> > vec4 v;
>> > imageStore(img, coord, v.yzwx);
>> >
>> > The swizzle would fail to take effect.
>> >
>> > Have you run tests to see if this is in fact the case?
>> >
>>
>> I haven't, but I'm aware of this problem. It's one of the things I wish
>> I had finished before I left. I had a few solutions in mind, all of
>> them likely to be time-consuming and not especially compelling:
>>
>> - Rename what I called backend_reg to e.g. base_reg, make it an
>> abstract base class or use some other technique to prevent its
>> construction. Now backend_reg would be implemented as a sort of
>> type-erased wrapper for the other kinds of regs. This wouldn't be
>> too hard because the only thing we need backend_regs for is to pass
>> values around, the actual uses of those regs know about the real
>> register types.
>>
>> - Prevent construction of backend_reg as before, but pass them around
>> as pointers instead of by value. This would be simple but kind of
>> annoying and inconsistent with the current value semantics of the
>> other register classes.
>>
>> - Make backend_reg a member variable rather than a base class to
>> prevent unsafe up-casting. We could have helper functions to convert
>> a fs/vec4 reg into a backend reg that check if the original register
>> region parameters are the identity mapping and, if they are not, copy
>> the value over to some temporary storage. Assignments would be
>> handled by the visitor itself rather than the surface lowering code.
>>
>> - Use static rather than dynamic polymorphism in the shared code, which
>> would be parameterized by the correct register type. There is really
>> no reason for the shared code to be a (polymorphic) class, other than
>> to avoid templates.
>>
>> I think right now I'm leaning towards possibility 1, but I'll give the
>> matter another thought and try to get one of these solutions working
>> when I find the time. I can't promise when that will happen though.
>>
>> Let me know if you come up with anything else.
>>
>> Thanks.
>>
>
> I played around a little bit yesterday with the last option (using static
> rather than dynamic polymorphism), and I like what I came up with, but it
> involves templates so it would be a hard sell for a lot of folks. I'm
> hoping that I can have an in-person conversation with some of the Intel
> developers about this so that we can hash it out in person without things
> getting too flamey. Unfortunately, several people have already started
> their holiday vacations, so that conversation probably won't happen until
> the new year.
Any news on this?
Thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 229 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20140212/df13b3a4/attachment.pgp>
More information about the mesa-dev
mailing list