mesa: flush and wait after creating a fallback texture
[mesa.git] / src / intel / compiler / brw_reg_type.c
1 /*
2 * Copyright © 2017 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "brw_reg.h"
25 #include "brw_eu_defines.h"
26 #include "common/gen_device_info.h"
27
28 #define INVALID (-1)
29
30 enum hw_reg_type {
31 BRW_HW_REG_TYPE_UD = 0,
32 BRW_HW_REG_TYPE_D = 1,
33 BRW_HW_REG_TYPE_UW = 2,
34 BRW_HW_REG_TYPE_W = 3,
35 BRW_HW_REG_TYPE_F = 7,
36 GEN8_HW_REG_TYPE_UQ = 8,
37 GEN8_HW_REG_TYPE_Q = 9,
38
39 BRW_HW_REG_TYPE_UB = 4,
40 BRW_HW_REG_TYPE_B = 5,
41 GEN7_HW_REG_TYPE_DF = 6,
42 GEN8_HW_REG_TYPE_HF = 10,
43 };
44
45 enum hw_imm_type {
46 BRW_HW_IMM_TYPE_UD = 0,
47 BRW_HW_IMM_TYPE_D = 1,
48 BRW_HW_IMM_TYPE_UW = 2,
49 BRW_HW_IMM_TYPE_W = 3,
50 BRW_HW_IMM_TYPE_F = 7,
51 GEN8_HW_IMM_TYPE_UQ = 8,
52 GEN8_HW_IMM_TYPE_Q = 9,
53
54 BRW_HW_IMM_TYPE_UV = 4,
55 BRW_HW_IMM_TYPE_VF = 5,
56 BRW_HW_IMM_TYPE_V = 6,
57 GEN8_HW_IMM_TYPE_DF = 10,
58 GEN8_HW_IMM_TYPE_HF = 11,
59 };
60
61 static const struct {
62 enum hw_reg_type reg_type;
63 enum hw_imm_type imm_type;
64 } gen4_hw_type[] = {
65 [BRW_REGISTER_TYPE_DF] = { GEN7_HW_REG_TYPE_DF, GEN8_HW_IMM_TYPE_DF },
66 [BRW_REGISTER_TYPE_F] = { BRW_HW_REG_TYPE_F, BRW_HW_IMM_TYPE_F },
67 [BRW_REGISTER_TYPE_HF] = { GEN8_HW_REG_TYPE_HF, GEN8_HW_IMM_TYPE_HF },
68 [BRW_REGISTER_TYPE_VF] = { INVALID, BRW_HW_IMM_TYPE_VF },
69
70 [BRW_REGISTER_TYPE_Q] = { GEN8_HW_REG_TYPE_Q, GEN8_HW_IMM_TYPE_Q },
71 [BRW_REGISTER_TYPE_UQ] = { GEN8_HW_REG_TYPE_UQ, GEN8_HW_IMM_TYPE_UQ },
72 [BRW_REGISTER_TYPE_D] = { BRW_HW_REG_TYPE_D, BRW_HW_IMM_TYPE_D },
73 [BRW_REGISTER_TYPE_UD] = { BRW_HW_REG_TYPE_UD, BRW_HW_IMM_TYPE_UD },
74 [BRW_REGISTER_TYPE_W] = { BRW_HW_REG_TYPE_W, BRW_HW_IMM_TYPE_W },
75 [BRW_REGISTER_TYPE_UW] = { BRW_HW_REG_TYPE_UW, BRW_HW_IMM_TYPE_UW },
76 [BRW_REGISTER_TYPE_B] = { BRW_HW_REG_TYPE_B, INVALID },
77 [BRW_REGISTER_TYPE_UB] = { BRW_HW_REG_TYPE_UB, INVALID },
78 [BRW_REGISTER_TYPE_V] = { INVALID, BRW_HW_IMM_TYPE_V },
79 [BRW_REGISTER_TYPE_UV] = { INVALID, BRW_HW_IMM_TYPE_UV },
80 };
81
82 /* SNB adds 3-src instructions (MAD and LRP) that only operate on floats, so
83 * the types were implied. IVB adds BFE and BFI2 that operate on doublewords
84 * and unsigned doublewords, so a new field is also available in the da3src
85 * struct (part of struct brw_instruction.bits1 in brw_structs.h) to select
86 * dst and shared-src types.
87 *
88 * CNL adds support for 3-src instructions in align1 mode, and with it support
89 * for most register types.
90 */
91 enum hw_3src_reg_type {
92 GEN7_3SRC_TYPE_F = 0,
93 GEN7_3SRC_TYPE_D = 1,
94 GEN7_3SRC_TYPE_UD = 2,
95 GEN7_3SRC_TYPE_DF = 3,
96
97 /** When ExecutionDatatype is 1: @{ */
98 GEN10_ALIGN1_3SRC_REG_TYPE_HF = 0b000,
99 GEN10_ALIGN1_3SRC_REG_TYPE_F = 0b001,
100 GEN10_ALIGN1_3SRC_REG_TYPE_DF = 0b010,
101 /** @} */
102
103 /** When ExecutionDatatype is 0: @{ */
104 GEN10_ALIGN1_3SRC_REG_TYPE_UD = 0b000,
105 GEN10_ALIGN1_3SRC_REG_TYPE_D = 0b001,
106 GEN10_ALIGN1_3SRC_REG_TYPE_UW = 0b010,
107 GEN10_ALIGN1_3SRC_REG_TYPE_W = 0b011,
108 GEN10_ALIGN1_3SRC_REG_TYPE_UB = 0b100,
109 GEN10_ALIGN1_3SRC_REG_TYPE_B = 0b101,
110 /** @} */
111 };
112
113 static const struct hw_3src_type {
114 enum hw_3src_reg_type reg_type;
115 enum gen10_align1_3src_exec_type exec_type;
116 } gen7_hw_3src_type[] = {
117 [0 ... BRW_REGISTER_TYPE_LAST] = { INVALID },
118
119 [BRW_REGISTER_TYPE_F] = { GEN7_3SRC_TYPE_F },
120 [BRW_REGISTER_TYPE_D] = { GEN7_3SRC_TYPE_D },
121 [BRW_REGISTER_TYPE_UD] = { GEN7_3SRC_TYPE_UD },
122 [BRW_REGISTER_TYPE_DF] = { GEN7_3SRC_TYPE_DF },
123 }, gen10_hw_3src_align1_type[] = {
124 #define E(x) BRW_ALIGN1_3SRC_EXEC_TYPE_##x
125 [0 ... BRW_REGISTER_TYPE_LAST] = { INVALID },
126
127 [BRW_REGISTER_TYPE_DF] = { GEN10_ALIGN1_3SRC_REG_TYPE_DF, E(FLOAT) },
128 [BRW_REGISTER_TYPE_F] = { GEN10_ALIGN1_3SRC_REG_TYPE_F, E(FLOAT) },
129 [BRW_REGISTER_TYPE_HF] = { GEN10_ALIGN1_3SRC_REG_TYPE_HF, E(FLOAT) },
130
131 [BRW_REGISTER_TYPE_D] = { GEN10_ALIGN1_3SRC_REG_TYPE_D, E(INT) },
132 [BRW_REGISTER_TYPE_UD] = { GEN10_ALIGN1_3SRC_REG_TYPE_UD, E(INT) },
133 [BRW_REGISTER_TYPE_W] = { GEN10_ALIGN1_3SRC_REG_TYPE_W, E(INT) },
134 [BRW_REGISTER_TYPE_UW] = { GEN10_ALIGN1_3SRC_REG_TYPE_UW, E(INT) },
135 [BRW_REGISTER_TYPE_B] = { GEN10_ALIGN1_3SRC_REG_TYPE_B, E(INT) },
136 [BRW_REGISTER_TYPE_UB] = { GEN10_ALIGN1_3SRC_REG_TYPE_UB, E(INT) },
137 #undef E
138 };
139
140 /**
141 * Convert a brw_reg_type enumeration value into the hardware representation.
142 *
143 * The hardware encoding may depend on whether the value is an immediate.
144 */
145 unsigned
146 brw_reg_type_to_hw_type(const struct gen_device_info *devinfo,
147 enum brw_reg_file file,
148 enum brw_reg_type type)
149 {
150 assert(type < ARRAY_SIZE(gen4_hw_type));
151
152 if (file == BRW_IMMEDIATE_VALUE) {
153 assert(gen4_hw_type[type].imm_type != (enum hw_imm_type)INVALID);
154 return gen4_hw_type[type].imm_type;
155 } else {
156 assert(gen4_hw_type[type].reg_type != (enum hw_reg_type)INVALID);
157 return gen4_hw_type[type].reg_type;
158 }
159 }
160
161 /**
162 * Convert the hardware representation into a brw_reg_type enumeration value.
163 *
164 * The hardware encoding may depend on whether the value is an immediate.
165 */
166 enum brw_reg_type
167 brw_hw_type_to_reg_type(const struct gen_device_info *devinfo,
168 enum brw_reg_file file, unsigned hw_type)
169 {
170 if (file == BRW_IMMEDIATE_VALUE) {
171 for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) {
172 if (gen4_hw_type[i].imm_type == (enum hw_imm_type)hw_type) {
173 return i;
174 }
175 }
176 } else {
177 for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) {
178 if (gen4_hw_type[i].reg_type == (enum hw_reg_type)hw_type) {
179 return i;
180 }
181 }
182 }
183 unreachable("not reached");
184 }
185
186 /**
187 * Convert a brw_reg_type enumeration value into the hardware representation
188 * for a 3-src align16 instruction
189 */
190 unsigned
191 brw_reg_type_to_a16_hw_3src_type(const struct gen_device_info *devinfo,
192 enum brw_reg_type type)
193 {
194 assert(type < ARRAY_SIZE(gen7_hw_3src_type));
195 assert(gen7_hw_3src_type[type].reg_type != (enum hw_3src_reg_type)INVALID);
196 return gen7_hw_3src_type[type].reg_type;
197 }
198
199 /**
200 * Convert a brw_reg_type enumeration value into the hardware representation
201 * for a 3-src align1 instruction
202 */
203 unsigned
204 brw_reg_type_to_a1_hw_3src_type(const struct gen_device_info *devinfo,
205 enum brw_reg_type type)
206 {
207 assert(type < ARRAY_SIZE(gen10_hw_3src_align1_type));
208 assert(gen10_hw_3src_align1_type[type].reg_type != (enum hw_3src_reg_type)INVALID);
209 return gen10_hw_3src_align1_type[type].reg_type;
210 }
211
212 /**
213 * Convert the hardware representation for a 3-src align16 instruction into a
214 * brw_reg_type enumeration value.
215 */
216 enum brw_reg_type
217 brw_a16_hw_3src_type_to_reg_type(const struct gen_device_info *devinfo,
218 unsigned hw_type)
219 {
220 for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) {
221 if (gen7_hw_3src_type[i].reg_type == hw_type) {
222 return i;
223 }
224 }
225 unreachable("not reached");
226 }
227
228 /**
229 * Convert the hardware representation for a 3-src align1 instruction into a
230 * brw_reg_type enumeration value.
231 */
232 enum brw_reg_type
233 brw_a1_hw_3src_type_to_reg_type(const struct gen_device_info *devinfo,
234 unsigned hw_type, unsigned exec_type)
235 {
236 for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) {
237 if (gen10_hw_3src_align1_type[i].reg_type == hw_type &&
238 gen10_hw_3src_align1_type[i].exec_type == exec_type) {
239 return i;
240 }
241 }
242 unreachable("not reached");
243 }
244
245 /**
246 * Return the element size given a register type.
247 */
248 unsigned
249 brw_reg_type_to_size(enum brw_reg_type type)
250 {
251 static const unsigned type_size[] = {
252 [BRW_REGISTER_TYPE_DF] = 8,
253 [BRW_REGISTER_TYPE_F] = 4,
254 [BRW_REGISTER_TYPE_HF] = 2,
255 [BRW_REGISTER_TYPE_VF] = 4,
256
257 [BRW_REGISTER_TYPE_Q] = 8,
258 [BRW_REGISTER_TYPE_UQ] = 8,
259 [BRW_REGISTER_TYPE_D] = 4,
260 [BRW_REGISTER_TYPE_UD] = 4,
261 [BRW_REGISTER_TYPE_W] = 2,
262 [BRW_REGISTER_TYPE_UW] = 2,
263 [BRW_REGISTER_TYPE_B] = 1,
264 [BRW_REGISTER_TYPE_UB] = 1,
265 [BRW_REGISTER_TYPE_V] = 2,
266 [BRW_REGISTER_TYPE_UV] = 2,
267 };
268 return type_size[type];
269 }
270
271 /**
272 * Converts a BRW_REGISTER_TYPE_* enum to a short string (F, UD, and so on).
273 *
274 * This is different than reg_encoding from brw_disasm.c in that it operates
275 * on the abstract enum values, rather than the generation-specific encoding.
276 */
277 const char *
278 brw_reg_type_to_letters(enum brw_reg_type type)
279 {
280 static const char letters[][3] = {
281 [BRW_REGISTER_TYPE_DF] = "DF",
282 [BRW_REGISTER_TYPE_F] = "F",
283 [BRW_REGISTER_TYPE_HF] = "HF",
284 [BRW_REGISTER_TYPE_VF] = "VF",
285
286 [BRW_REGISTER_TYPE_Q] = "Q",
287 [BRW_REGISTER_TYPE_UQ] = "UQ",
288 [BRW_REGISTER_TYPE_D] = "D",
289 [BRW_REGISTER_TYPE_UD] = "UD",
290 [BRW_REGISTER_TYPE_W] = "W",
291 [BRW_REGISTER_TYPE_UW] = "UW",
292 [BRW_REGISTER_TYPE_B] = "B",
293 [BRW_REGISTER_TYPE_UB] = "UB",
294 [BRW_REGISTER_TYPE_V] = "V",
295 [BRW_REGISTER_TYPE_UV] = "UV",
296 };
297 assert(type < ARRAY_SIZE(letters));
298 return letters[type];
299 }