i965/fs: Remove the width field from fs_reg
[mesa.git] / src / mesa / drivers / dri / i965 / brw_ir_fs.h
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
48 bool equals(const fs_reg &r) const;
49 bool is_contiguous() const;
50
51 /** Smear a channel of the reg to all channels. */
52 fs_reg &set_smear(unsigned subreg);
53
54 /**
55 * Offset in bytes from the start of the register. Values up to a
56 * backend_reg::reg_offset unit are valid.
57 */
58 int subreg_offset;
59
60 fs_reg *reladdr;
61
62 /** Register region horizontal stride */
63 uint8_t stride;
64 };
65
66 static inline fs_reg
67 negate(fs_reg reg)
68 {
69 assert(reg.file != HW_REG && reg.file != IMM);
70 reg.negate = !reg.negate;
71 return reg;
72 }
73
74 static inline fs_reg
75 retype(fs_reg reg, enum brw_reg_type type)
76 {
77 reg.fixed_hw_reg.type = reg.type = type;
78 return reg;
79 }
80
81 static inline fs_reg
82 byte_offset(fs_reg reg, unsigned delta)
83 {
84 switch (reg.file) {
85 case BAD_FILE:
86 break;
87 case GRF:
88 case ATTR:
89 reg.reg_offset += delta / 32;
90 break;
91 case MRF:
92 reg.reg += delta / 32;
93 break;
94 default:
95 assert(delta == 0);
96 }
97 reg.subreg_offset += delta % 32;
98 return reg;
99 }
100
101 static inline fs_reg
102 horiz_offset(fs_reg reg, unsigned delta)
103 {
104 switch (reg.file) {
105 case BAD_FILE:
106 case UNIFORM:
107 case IMM:
108 /* These only have a single component that is implicitly splatted. A
109 * horizontal offset should be a harmless no-op.
110 */
111 break;
112 case GRF:
113 case MRF:
114 case ATTR:
115 return byte_offset(reg, delta * reg.stride * type_sz(reg.type));
116 default:
117 assert(delta == 0);
118 }
119 return reg;
120 }
121
122 static inline fs_reg
123 component(fs_reg reg, unsigned idx)
124 {
125 assert(reg.subreg_offset == 0);
126 reg.subreg_offset = idx * type_sz(reg.type);
127 reg.stride = 0;
128 return reg;
129 }
130
131 static inline bool
132 is_uniform(const fs_reg &reg)
133 {
134 return (reg.stride == 0 || reg.is_null()) &&
135 (!reg.reladdr || is_uniform(*reg.reladdr));
136 }
137
138 /**
139 * Get either of the 8-component halves of a 16-component register.
140 *
141 * Note: this also works if \c reg represents a SIMD16 pair of registers.
142 */
143 static inline fs_reg
144 half(fs_reg reg, unsigned idx)
145 {
146 assert(idx < 2);
147
148 switch (reg.file) {
149 case BAD_FILE:
150 case UNIFORM:
151 case IMM:
152 return reg;
153
154 case GRF:
155 case MRF:
156 return horiz_offset(reg, 8 * idx);
157
158 case ATTR:
159 case HW_REG:
160 default:
161 unreachable("Cannot take half of this register type");
162 }
163 return reg;
164 }
165
166 static const fs_reg reg_undef;
167
168 class fs_inst : public backend_instruction {
169 fs_inst &operator=(const fs_inst &);
170
171 void init(enum opcode opcode, uint8_t exec_width, const fs_reg &dst,
172 const fs_reg *src, unsigned sources);
173
174 public:
175 DECLARE_RALLOC_CXX_OPERATORS(fs_inst)
176
177 fs_inst();
178 fs_inst(enum opcode opcode, uint8_t exec_size);
179 fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst);
180 fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
181 const fs_reg &src0);
182 fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
183 const fs_reg &src0, const fs_reg &src1);
184 fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
185 const fs_reg &src0, const fs_reg &src1, const fs_reg &src2);
186 fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
187 const fs_reg src[], unsigned sources);
188 fs_inst(const fs_inst &that);
189 ~fs_inst();
190
191 void resize_sources(uint8_t num_sources);
192
193 bool equals(fs_inst *inst) const;
194 bool overwrites_reg(const fs_reg &reg) const;
195 bool is_send_from_grf() const;
196 bool is_partial_write() const;
197 bool is_copy_payload(const brw::simple_allocator &grf_alloc) const;
198 int regs_read(int arg) const;
199 bool can_do_source_mods(const struct brw_device_info *devinfo);
200 bool has_side_effects() const;
201
202 bool reads_flag() const;
203 bool writes_flag() const;
204
205 fs_reg dst;
206 fs_reg *src;
207
208 uint8_t sources; /**< Number of fs_reg sources. */
209
210 /**
211 * Execution size of the instruction. This is used by the generator to
212 * generate the correct binary for the given fs_inst. Current valid
213 * values are 1, 8, 16.
214 */
215 uint8_t exec_size;
216
217 bool eot:1;
218 bool force_sechalf:1;
219 bool pi_noperspective:1; /**< Pixel interpolator noperspective flag */
220 };
221
222 /**
223 * Set second-half quarter control on \p inst.
224 */
225 static inline fs_inst *
226 set_sechalf(fs_inst *inst)
227 {
228 inst->force_sechalf = true;
229 return inst;
230 }
231
232 /**
233 * Make the execution of \p inst dependent on the evaluation of a possibly
234 * inverted predicate.
235 */
236 static inline fs_inst *
237 set_predicate_inv(enum brw_predicate pred, bool inverse,
238 fs_inst *inst)
239 {
240 inst->predicate = pred;
241 inst->predicate_inverse = inverse;
242 return inst;
243 }
244
245 /**
246 * Make the execution of \p inst dependent on the evaluation of a predicate.
247 */
248 static inline fs_inst *
249 set_predicate(enum brw_predicate pred, fs_inst *inst)
250 {
251 return set_predicate_inv(pred, false, inst);
252 }
253
254 /**
255 * Write the result of evaluating the condition given by \p mod to a flag
256 * register.
257 */
258 static inline fs_inst *
259 set_condmod(enum brw_conditional_mod mod, fs_inst *inst)
260 {
261 inst->conditional_mod = mod;
262 return inst;
263 }
264
265 /**
266 * Clamp the result of \p inst to the saturation range of its destination
267 * datatype.
268 */
269 static inline fs_inst *
270 set_saturate(bool saturate, fs_inst *inst)
271 {
272 inst->saturate = saturate;
273 return inst;
274 }
275
276 #endif