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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev