Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- c++ -*- */
  2. /*
  3.  * Copyright © 2010-2015 Intel Corporation
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9.  * and/or sell copies of the Software, and to permit persons to whom the
  10.  * Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22.  * IN THE SOFTWARE.
  23.  */
  24.  
  25. #ifndef BRW_IR_FS_H
  26. #define BRW_IR_FS_H
  27.  
  28. #include "brw_shader.h"
  29.  
  30. class fs_inst;
  31.  
  32. class fs_reg : public backend_reg {
  33. public:
  34.    DECLARE_RALLOC_CXX_OPERATORS(fs_reg)
  35.  
  36.    void init();
  37.  
  38.    fs_reg();
  39.    explicit fs_reg(float f);
  40.    explicit fs_reg(int32_t i);
  41.    explicit fs_reg(uint32_t u);
  42.    explicit fs_reg(uint8_t vf[4]);
  43.    explicit fs_reg(uint8_t vf0, uint8_t vf1, uint8_t vf2, uint8_t vf3);
  44.    fs_reg(struct brw_reg fixed_hw_reg);
  45.    fs_reg(enum register_file file, int reg);
  46.    fs_reg(enum register_file file, int reg, enum brw_reg_type type);
  47.    fs_reg(enum register_file file, int reg, enum brw_reg_type type, uint8_t width);
  48.  
  49.    bool equals(const fs_reg &r) const;
  50.    bool is_contiguous() const;
  51.  
  52.    /** Smear a channel of the reg to all channels. */
  53.    fs_reg &set_smear(unsigned subreg);
  54.  
  55.    /**
  56.     * Offset in bytes from the start of the register.  Values up to a
  57.     * backend_reg::reg_offset unit are valid.
  58.     */
  59.    int subreg_offset;
  60.  
  61.    fs_reg *reladdr;
  62.  
  63.    /**
  64.     * The register width.  This indicates how many hardware values are
  65.     * represented by each virtual value.  Valid values are 1, 8, or 16.
  66.     * For immediate values, this is 1.  Most of the rest of the time, it
  67.     * will be equal to the dispatch width.
  68.     */
  69.    uint8_t width;
  70.  
  71.    /** Register region horizontal stride */
  72.    uint8_t stride;
  73. };
  74.  
  75. static inline fs_reg
  76. negate(fs_reg reg)
  77. {
  78.    assert(reg.file != HW_REG && reg.file != IMM);
  79.    reg.negate = !reg.negate;
  80.    return reg;
  81. }
  82.  
  83. static inline fs_reg
  84. retype(fs_reg reg, enum brw_reg_type type)
  85. {
  86.    reg.fixed_hw_reg.type = reg.type = type;
  87.    return reg;
  88. }
  89.  
  90. static inline fs_reg
  91. byte_offset(fs_reg reg, unsigned delta)
  92. {
  93.    switch (reg.file) {
  94.    case BAD_FILE:
  95.       break;
  96.    case GRF:
  97.    case ATTR:
  98.       reg.reg_offset += delta / 32;
  99.       break;
  100.    case MRF:
  101.       reg.reg += delta / 32;
  102.       break;
  103.    default:
  104.       assert(delta == 0);
  105.    }
  106.    reg.subreg_offset += delta % 32;
  107.    return reg;
  108. }
  109.  
  110. static inline fs_reg
  111. horiz_offset(fs_reg reg, unsigned delta)
  112. {
  113.    switch (reg.file) {
  114.    case BAD_FILE:
  115.    case UNIFORM:
  116.    case IMM:
  117.       /* These only have a single component that is implicitly splatted.  A
  118.        * horizontal offset should be a harmless no-op.
  119.        */
  120.       break;
  121.    case GRF:
  122.    case MRF:
  123.    case ATTR:
  124.       return byte_offset(reg, delta * reg.stride * type_sz(reg.type));
  125.    default:
  126.       assert(delta == 0);
  127.    }
  128.    return reg;
  129. }
  130.  
  131. static inline fs_reg
  132. offset(fs_reg reg, unsigned delta)
  133. {
  134.    switch (reg.file) {
  135.    case BAD_FILE:
  136.       break;
  137.    case GRF:
  138.    case MRF:
  139.    case ATTR:
  140.       return byte_offset(reg,
  141.                          delta * MAX2(reg.width * reg.stride, 1) *
  142.                          type_sz(reg.type));
  143.    case UNIFORM:
  144.       reg.reg_offset += delta;
  145.       break;
  146.    default:
  147.       assert(delta == 0);
  148.    }
  149.    return reg;
  150. }
  151.  
  152. static inline fs_reg
  153. component(fs_reg reg, unsigned idx)
  154. {
  155.    assert(reg.subreg_offset == 0);
  156.    assert(idx < reg.width);
  157.    reg.subreg_offset = idx * type_sz(reg.type);
  158.    reg.width = 1;
  159.    reg.stride = 0;
  160.    return reg;
  161. }
  162.  
  163. static inline bool
  164. is_uniform(const fs_reg &reg)
  165. {
  166.    return (reg.width == 1 || reg.stride == 0 || reg.is_null()) &&
  167.           (!reg.reladdr || is_uniform(*reg.reladdr));
  168. }
  169.  
  170. /**
  171.  * Get either of the 8-component halves of a 16-component register.
  172.  *
  173.  * Note: this also works if \c reg represents a SIMD16 pair of registers.
  174.  */
  175. static inline fs_reg
  176. half(fs_reg reg, unsigned idx)
  177. {
  178.    assert(idx < 2);
  179.  
  180.    switch (reg.file) {
  181.    case BAD_FILE:
  182.    case UNIFORM:
  183.    case IMM:
  184.       return reg;
  185.  
  186.    case GRF:
  187.    case MRF:
  188.       assert(reg.width == 16);
  189.       reg.width = 8;
  190.       return horiz_offset(reg, 8 * idx);
  191.  
  192.    case ATTR:
  193.    case HW_REG:
  194.    default:
  195.       unreachable("Cannot take half of this register type");
  196.    }
  197.    return reg;
  198. }
  199.  
  200. static const fs_reg reg_undef;
  201.  
  202. class fs_inst : public backend_instruction {
  203.    fs_inst &operator=(const fs_inst &);
  204.  
  205.    void init(enum opcode opcode, uint8_t exec_width, const fs_reg &dst,
  206.              const fs_reg *src, unsigned sources);
  207.  
  208. public:
  209.    DECLARE_RALLOC_CXX_OPERATORS(fs_inst)
  210.  
  211.    fs_inst();
  212.    fs_inst(enum opcode opcode, uint8_t exec_size);
  213.    fs_inst(enum opcode opcode, const fs_reg &dst);
  214.    fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
  215.            const fs_reg &src0);
  216.    fs_inst(enum opcode opcode, const fs_reg &dst, const fs_reg &src0);
  217.    fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
  218.            const fs_reg &src0, const fs_reg &src1);
  219.    fs_inst(enum opcode opcode, const fs_reg &dst, const fs_reg &src0,
  220.            const fs_reg &src1);
  221.    fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
  222.            const fs_reg &src0, const fs_reg &src1, const fs_reg &src2);
  223.    fs_inst(enum opcode opcode, const fs_reg &dst, const fs_reg &src0,
  224.            const fs_reg &src1, const fs_reg &src2);
  225.    fs_inst(enum opcode opcode, const fs_reg &dst, const fs_reg src[],
  226.            unsigned sources);
  227.    fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
  228.            const fs_reg src[], unsigned sources);
  229.    fs_inst(const fs_inst &that);
  230.    ~fs_inst();
  231.  
  232.    void resize_sources(uint8_t num_sources);
  233.  
  234.    bool equals(fs_inst *inst) const;
  235.    bool overwrites_reg(const fs_reg &reg) const;
  236.    bool is_send_from_grf() const;
  237.    bool is_partial_write() const;
  238.    bool is_copy_payload(const brw::simple_allocator &grf_alloc) const;
  239.    int regs_read(int arg) const;
  240.    bool can_do_source_mods(const struct brw_device_info *devinfo);
  241.    bool has_side_effects() const;
  242.  
  243.    bool reads_flag() const;
  244.    bool writes_flag() const;
  245.  
  246.    fs_reg dst;
  247.    fs_reg *src;
  248.  
  249.    uint8_t sources; /**< Number of fs_reg sources. */
  250.  
  251.    /**
  252.     * Execution size of the instruction.  This is used by the generator to
  253.     * generate the correct binary for the given fs_inst.  Current valid
  254.     * values are 1, 8, 16.
  255.     */
  256.    uint8_t exec_size;
  257.  
  258.    bool eot:1;
  259.    bool force_uncompressed:1;
  260.    bool force_sechalf:1;
  261.    bool pi_noperspective:1;   /**< Pixel interpolator noperspective flag */
  262. };
  263.  
  264. /**
  265.  * Set second-half quarter control on \p inst.
  266.  */
  267. static inline fs_inst *
  268. set_sechalf(fs_inst *inst)
  269. {
  270.    inst->force_sechalf = true;
  271.    return inst;
  272. }
  273.  
  274. #endif
  275.