[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 &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 &reg);
> +
> +      /**
> +       * 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 &reg)
> +      {
> +         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 &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 &reg, 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 &reg, 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 &reg, 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 &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 &reg) :
> +         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 &reg)
> +      {
> +         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 &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 &reg, 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 &reg, 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 &reg) :
> +      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 &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 &reg, unsigned n)
> +{
> +   return resize(reg, n);
> +}
> +
>  static inline bool
>  is_uniform(const src_reg &reg)
>  {
> @@ -188,6 +197,15 @@ resize(const dst_reg &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 &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