[Mesa-dev] [PATCH 11/21] i965/fs: Define scalarizing VEC4 pseudo-IR.

Francisco Jerez currojerez at riseup.net
Tue Apr 28 10:08:27 PDT 2015


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 {
+   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



More information about the mesa-dev mailing list