[Mesa-dev] [PATCH 11/21] i965/fs: Define scalarizing VEC4 pseudo-IR.
Mark Janes
mark.a.janes at intel.com
Thu Apr 30 17:48:06 PDT 2015
Francisco Jerez <currojerez at riseup.net> writes:
> This is not a real IR in the sense of a long-lived representation of
> the program. An SVEC4 instruction, defined as an opcode operating on
> 4-vectors of FS registers, is broken up into its scalar components
> (each an fs_inst) as soon as it's emitted. The svec4_inst object is a
> convenient way to carry around the expanded FS instructions and apply
> some transformations on them (using the back-end-independent exec_*()
> API introduced by a future commit).
>
> A src_svec4 register is a vector of FS registers with its components
> ordered according to a swizzle, and a dst_svec4 register is a subset
> of vector components used as destination of some vector operation,
> pretty much like the source and destination registers of the VEC4
> back-end.
>
> On the one hand this simplifies the translation of VEC4 higher level
> languages (e.g. GLSL IR) and VEC4-centric APIs
> (e.g. ARB_shader_image_load_store) into the scalar i965 back-end IR,
> and on the other hand it can greatly reduce the amount of duplication
> between back-ends, as it provides an interface to generate scalar IR
> with semantics consistent with the VEC4 IR interface.
>
> This patch only defines the essential data structures of the SVEC4
> pseudo-IR. The interface to construct, scalarize and emit SVEC4
> instructions will be introduced in a future commit.
> ---
> src/mesa/drivers/dri/i965/Makefile.sources | 1 +
> src/mesa/drivers/dri/i965/brw_ir_svec4.h | 296 +++++++++++++++++++++++++++++
> src/mesa/drivers/dri/i965/brw_ir_vec4.h | 18 ++
> 3 files changed, 315 insertions(+)
> create mode 100644 src/mesa/drivers/dri/i965/brw_ir_svec4.h
>
> diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources
> index 6d4659f..83acbd0 100644
> --- a/src/mesa/drivers/dri/i965/Makefile.sources
> +++ b/src/mesa/drivers/dri/i965/Makefile.sources
> @@ -66,6 +66,7 @@ i965_FILES = \
> brw_interpolation_map.c \
> brw_ir_allocator.h \
> brw_ir_fs.h \
> + brw_ir_svec4.h \
> brw_ir_vec4.h \
> brw_lower_texture_gradients.cpp \
> brw_lower_unnormalized_offset.cpp \
> diff --git a/src/mesa/drivers/dri/i965/brw_ir_svec4.h b/src/mesa/drivers/dri/i965/brw_ir_svec4.h
> new file mode 100644
> index 0000000..d1eafdd
> --- /dev/null
> +++ b/src/mesa/drivers/dri/i965/brw_ir_svec4.h
> @@ -0,0 +1,296 @@
> +/* -*- c++ -*- */
> +/*
> + * Copyright © 2015 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +#ifndef BRW_IR_SVEC4_H
> +#define BRW_IR_SVEC4_H
> +
> +#include "brw_ir_fs.h"
> +
> +namespace brw {
> + class dst_svec4;
> +
> + /**
> + * Source vector of one to four scalar FS registers. These are the sources
> + * of SVEC4 pseudo-instructions and provide VEC4-like semantics in the
> + * scalar back-end with implicit scalarization.
> + *
> + * It inherits from fs_reg privately because there is an
> + * implemented-in-terms-of relationship rather than an is-a relationship
> + * (the Liskov substitution principle doesn't hold).
> + */
> + class src_svec4 : private fs_reg {
Every product I've worked on has disallowed private inheritance as a
policy. I'm surprised to see usage of such an obscure feature, because
it seems like Mesa has a pretty limited subset of c++ that is used.
If you need an implemented-in-terms-of relationship, it seems like
composition should be used.
One example of a public c++ style guide that disallows private
inheritance:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Inheritance
> + public:
> + src_svec4() : fs_reg(), swizzle(0)
> + {
> + }
> +
> + src_svec4(const fs_reg ®, unsigned swizzle = BRW_SWIZZLE_NOOP) :
> + fs_reg(reg), swizzle(swizzle)
> + {
> + }
> +
> + src_svec4(float f) : fs_reg(f), swizzle(BRW_SWIZZLE_XXXX)
> + {
> + }
> +
> + src_svec4(int32_t i) : fs_reg(i), swizzle(BRW_SWIZZLE_XXXX)
> + {
> + }
> +
> + src_svec4(uint32_t u) : fs_reg(u), swizzle(BRW_SWIZZLE_XXXX)
> + {
> + }
> +
> + /**
> + * Construct a source vector from a destination vector.
> + */
> + inline
> + src_svec4(const dst_svec4 ®);
> +
> + /**
> + * Return the standard representation of this register in the IR. This
> + * is basically an up-cast but it's exposed as a function to prevent
> + * accidental casts which are unsafe in general.
> + */
> + friend const fs_reg &
> + repr(const src_svec4 ®)
> + {
> + return reg;
> + }
> +
> + using fs_reg::is_null;
> + using fs_reg::is_accumulator;
> + using fs_reg::file;
> + using fs_reg::type;
> + using fs_reg::reg;
> + using fs_reg::reg_offset;
> + using fs_reg::fixed_hw_reg;
> + using fs_reg::negate;
> + using fs_reg::abs;
> + using fs_reg::reladdr;
> +
> + unsigned swizzle;
> + };
> +
> + /**
> + * Construct a source vector of \p n components starting from \p reg.
> + */
> + inline src_svec4
> + src_vector(const fs_reg ®, unsigned n)
> + {
> + return src_svec4(reg, brw_swizzle_for_size(n));
> + }
> +
> + inline src_svec4
> + retype(src_svec4 reg, enum brw_reg_type type)
> + {
> + reg.fixed_hw_reg.type = reg.type = type;
> + return reg;
> + }
> +
> + inline src_svec4
> + offset(const src_svec4 ®, unsigned delta)
> + {
> + return src_svec4(offset(repr(reg), delta), reg.swizzle);
> + }
> +
> + inline src_svec4
> + swizzle(src_svec4 reg, unsigned swizzle)
> + {
> + assert(reg.file != HW_REG);
> + reg.swizzle = brw_compose_swizzle(swizzle, reg.swizzle);
> + return reg;
> + }
> +
> + inline src_svec4
> + negate(src_svec4 reg)
> + {
> + assert(reg.file != HW_REG && reg.file != IMM);
> + reg.negate = !reg.negate;
> + return reg;
> + }
> +
> + /**
> + * Return the i-th logical component of register \p reg. A logical
> + * component is itself a vector with as many channels as the SIMD width of
> + * \p reg.
> + */
> + inline fs_reg
> + component(const src_svec4 ®, unsigned i)
> + {
> + assert(i < 4);
> + if (reg.is_null())
> + return repr(reg);
> + else
> + return offset(repr(reg), BRW_GET_SWZ(reg.swizzle, i));
> + }
> +
> + /**
> + * Return a register with the first \p n components of \p reg.
> + */
> + inline src_svec4
> + resize(const src_svec4 ®, unsigned n)
> + {
> + return swizzle(reg, brw_swizzle_for_size(n));
> + }
> +
> + /**
> + * Destination vector of one to four scalar FS registers. This is the
> + * destination of an SVEC4 pseudo-instruction and provides VEC4-like
> + * semantics in the scalar back-end with implicit scalarization.
> + *
> + * \sa brw::src_svec4
> + */
> + class dst_svec4 : private fs_reg {
> + public:
> + dst_svec4() : fs_reg(), writemask(0)
> + {
> + }
> +
> + dst_svec4(const fs_reg ®, unsigned writemask = WRITEMASK_XYZW) :
> + fs_reg(reg), writemask(writemask)
> + {
> + }
> +
> + /**
> + * Construct a destination vector from a source vector. Marked explicit
> + * because the swizzle-to-writemask conversion is many-to-one and loses
> + * information about the ordering of components.
> + */
> + explicit
> + dst_svec4(const src_svec4 ®) :
> + fs_reg(repr(reg)),
> + writemask(brw_mask_for_swizzle(reg.swizzle))
> + {
> + }
> +
> + /**
> + * Return the standard representation of this register in the IR. This
> + * is basically an up-cast but it's exposed as a function to prevent
> + * accidental casts which are unsafe in general.
> + */
> + friend const fs_reg &
> + repr(const dst_svec4 ®)
> + {
> + return reg;
> + }
> +
> + using fs_reg::is_null;
> + using fs_reg::is_accumulator;
> + using fs_reg::file;
> + using fs_reg::type;
> + using fs_reg::reg;
> + using fs_reg::reg_offset;
> + using fs_reg::fixed_hw_reg;
> + using fs_reg::negate;
> + using fs_reg::abs;
> + using fs_reg::reladdr;
> +
> + unsigned writemask;
> + };
> +
> + /**
> + * Construct a destination vector of \p n components starting from \p reg.
> + */
> + inline dst_svec4
> + dst_vector(const fs_reg ®, unsigned n)
> + {
> + return dst_svec4(reg, (1 << n) - 1);
> + }
> +
> + inline dst_svec4
> + retype(dst_svec4 reg, enum brw_reg_type type)
> + {
> + reg.fixed_hw_reg.type = reg.type = type;
> + return reg;
> + }
> +
> + inline dst_svec4
> + offset(const dst_svec4 ®, unsigned delta)
> + {
> + return dst_svec4(offset(repr(reg), delta), reg.writemask);
> + }
> +
> + inline dst_svec4
> + writemask(dst_svec4 reg, unsigned mask)
> + {
> + assert(reg.file != HW_REG && reg.file != IMM);
> + reg.writemask &= mask;
> + return reg;
> + }
> +
> + /**
> + * Return the i-th logical component of register \p reg. A logical
> + * component is itself a vector with as many channels as the SIMD width of
> + * \p reg.
> + */
> + inline fs_reg
> + component(const dst_svec4 ®, unsigned i)
> + {
> + assert(reg.writemask & (1 << i));
> + if (reg.is_null())
> + return repr(reg);
> + else
> + return offset(repr(reg), i);
> + }
> +
> + /**
> + * Return a register with the first \p n components of \p reg.
> + */
> + inline dst_svec4
> + resize(dst_svec4 reg, unsigned n)
> + {
> + return writemask(reg, (1 << n) - 1);
> + }
> +
> + src_svec4::src_svec4(const dst_svec4 ®) :
> + fs_reg(repr(reg)),
> + swizzle(brw_swizzle_for_mask(reg.writemask))
> + {
> + }
> +
> + /**
> + * Vector of scalar FS instructions. It represents a vector operation that
> + * has been expanded to its scalar components. The interface provided
> + * through the exec_*() helpers is intended to be compatible with its VEC4
> + * counterpart in order to enable generic FS/VEC4 programming.
> + */
> + class svec4_inst {
> + private:
> + svec4_inst(const svec4_inst &inst);
> + svec4_inst &
> + operator=(svec4_inst inst);
> +
> + public:
> + DECLARE_RALLOC_CXX_OPERATORS(svec4_inst)
> +
> + svec4_inst() : v()
> + {
> + }
> +
> + fs_inst *v[4];
> + };
> +}
> +
> +#endif
> diff --git a/src/mesa/drivers/dri/i965/brw_ir_vec4.h b/src/mesa/drivers/dri/i965/brw_ir_vec4.h
> index 7bb9459..9deb694 100644
> --- a/src/mesa/drivers/dri/i965/brw_ir_vec4.h
> +++ b/src/mesa/drivers/dri/i965/brw_ir_vec4.h
> @@ -114,6 +114,15 @@ resize(const src_reg ®, unsigned n)
> return swizzle(reg, brw_swizzle_for_size(n));
> }
>
> +/**
> + * Construct a source vector of \p n components starting from \p reg.
> + */
> +static inline src_reg
> +src_vector(const src_reg ®, unsigned n)
> +{
> + return resize(reg, n);
> +}
> +
> static inline bool
> is_uniform(const src_reg ®)
> {
> @@ -188,6 +197,15 @@ resize(const dst_reg ®, unsigned n)
> return writemask(reg, (1 << n) - 1);
> }
>
> +/**
> + * Construct a destination vector of \p n components starting from \p reg.
> + */
> +static inline dst_reg
> +dst_vector(const src_reg ®, unsigned n)
> +{
> + return resize(dst_reg(reg), n);
> +}
> +
> class vec4_instruction : public backend_instruction {
> public:
> DECLARE_RALLOC_CXX_OPERATORS(vec4_instruction)
> --
> 2.3.5
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list