[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 ®, 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
More information about the mesa-dev
mailing list