glsl: lower mediump temporaries to 16 bits except structures (v2)
[mesa.git] / src / mesa / state_tracker / st_glsl_to_tgsi_private.cpp
1 /*
2 * Copyright © 2010 Intel Corporation
3 * Copyright © 2011 Bryan Cain
4 * Copyright © 2017 Gert Wollny
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "st_glsl_to_tgsi_private.h"
27 #include "tgsi/tgsi_info.h"
28 #include "mesa/program/prog_instruction.h"
29 #include "mesa/program/prog_print.h"
30
31 static int swizzle_for_type(const glsl_type *type, int component = 0)
32 {
33 unsigned num_elements = 4;
34
35 if (type) {
36 type = type->without_array();
37 if (type->is_scalar() || type->is_vector() || type->is_matrix())
38 num_elements = type->vector_elements;
39 }
40
41 int swizzle = swizzle_for_size(num_elements);
42 assert(num_elements + component <= 4);
43
44 swizzle += component * MAKE_SWIZZLE4(1, 1, 1, 1);
45 return swizzle;
46 }
47
48 static st_src_reg *
49 dup_reladdr(const st_src_reg *input)
50 {
51 if (!input)
52 return NULL;
53
54 st_src_reg *reg = ralloc(input, st_src_reg);
55 if (!reg) {
56 assert(!"can't create reladdr, expect shader breakage");
57 return NULL;
58 }
59
60 *reg = *input;
61 return reg;
62 }
63
64 st_src_reg::st_src_reg(gl_register_file file, int index, const glsl_type *type,
65 int component, unsigned array_id)
66 {
67 assert(file != PROGRAM_ARRAY || array_id != 0);
68 this->file = file;
69 this->index = index;
70 this->swizzle = swizzle_for_type(type, component);
71 this->negate = 0;
72 this->abs = 0;
73 this->index2D = 0;
74 this->type = type ? type->base_type : GLSL_TYPE_ERROR;
75 this->reladdr = NULL;
76 this->reladdr2 = NULL;
77 this->has_index2 = false;
78 this->double_reg2 = false;
79 this->array_id = array_id;
80 this->is_double_vertex_input = false;
81 }
82
83 st_src_reg::st_src_reg(gl_register_file file, int index, enum glsl_base_type type)
84 {
85 assert(file != PROGRAM_ARRAY); /* need array_id > 0 */
86 this->type = type;
87 this->file = file;
88 this->index = index;
89 this->index2D = 0;
90 this->swizzle = SWIZZLE_XYZW;
91 this->negate = 0;
92 this->abs = 0;
93 this->reladdr = NULL;
94 this->reladdr2 = NULL;
95 this->has_index2 = false;
96 this->double_reg2 = false;
97 this->array_id = 0;
98 this->is_double_vertex_input = false;
99 }
100
101 st_src_reg::st_src_reg(gl_register_file file, int index, enum glsl_base_type type, int index2D)
102 {
103 assert(file != PROGRAM_ARRAY); /* need array_id > 0 */
104 this->type = type;
105 this->file = file;
106 this->index = index;
107 this->index2D = index2D;
108 this->swizzle = SWIZZLE_XYZW;
109 this->negate = 0;
110 this->abs = 0;
111 this->reladdr = NULL;
112 this->reladdr2 = NULL;
113 this->has_index2 = false;
114 this->double_reg2 = false;
115 this->array_id = 0;
116 this->is_double_vertex_input = false;
117 }
118
119 void st_src_reg::reset()
120 {
121 this->type = GLSL_TYPE_ERROR;
122 this->file = PROGRAM_UNDEFINED;
123 this->index = 0;
124 this->index2D = 0;
125 this->swizzle = 0;
126 this->negate = 0;
127 this->abs = 0;
128 this->reladdr = NULL;
129 this->reladdr2 = NULL;
130 this->has_index2 = false;
131 this->double_reg2 = false;
132 this->array_id = 0;
133 this->is_double_vertex_input = false;
134 }
135
136 st_src_reg::st_src_reg()
137 {
138 reset();
139 }
140
141 st_src_reg::st_src_reg(const st_src_reg &reg)
142 {
143 *this = reg;
144 }
145
146 void st_src_reg::operator=(const st_src_reg &reg)
147 {
148 this->type = reg.type;
149 this->file = reg.file;
150 this->index = reg.index;
151 this->index2D = reg.index2D;
152 this->swizzle = reg.swizzle;
153 this->negate = reg.negate;
154 this->abs = reg.abs;
155 this->reladdr = dup_reladdr(reg.reladdr);
156 this->reladdr2 = dup_reladdr(reg.reladdr2);
157 this->has_index2 = reg.has_index2;
158 this->double_reg2 = reg.double_reg2;
159 this->array_id = reg.array_id;
160 this->is_double_vertex_input = reg.is_double_vertex_input;
161 }
162
163 st_src_reg::st_src_reg(st_dst_reg reg)
164 {
165 this->type = reg.type;
166 this->file = reg.file;
167 this->index = reg.index;
168 this->swizzle = SWIZZLE_XYZW;
169 this->negate = 0;
170 this->abs = 0;
171 this->reladdr = dup_reladdr(reg.reladdr);
172 this->index2D = reg.index2D;
173 this->reladdr2 = dup_reladdr(reg.reladdr2);
174 this->has_index2 = reg.has_index2;
175 this->double_reg2 = false;
176 this->array_id = reg.array_id;
177 this->is_double_vertex_input = false;
178 }
179
180 st_src_reg st_src_reg::get_abs()
181 {
182 st_src_reg reg = *this;
183 reg.negate = 0;
184 reg.abs = 1;
185 return reg;
186 }
187
188 bool operator == (const st_src_reg& lhs, const st_src_reg& rhs)
189 {
190 bool result;
191
192 if (lhs.type != rhs.type ||
193 lhs.file != rhs.file ||
194 lhs.index != rhs.index ||
195 lhs.swizzle != rhs.swizzle ||
196 lhs.index2D != rhs.index2D ||
197 lhs.has_index2 != rhs.has_index2 ||
198 lhs.array_id != rhs.array_id ||
199 lhs.negate != rhs.negate ||
200 lhs.abs != rhs.abs ||
201 lhs.double_reg2 != rhs.double_reg2 ||
202 lhs.is_double_vertex_input != rhs.is_double_vertex_input)
203 return false;
204
205 if (lhs.reladdr) {
206 if (!rhs.reladdr)
207 return false;
208 result = (*lhs.reladdr == *rhs.reladdr);
209 } else {
210 result = !rhs.reladdr;
211 }
212
213 if (lhs.reladdr2) {
214 if (!rhs.reladdr2)
215 return false;
216 result &= (*lhs.reladdr2 == *rhs.reladdr2);
217 } else {
218 result &= !rhs.reladdr2;
219 }
220
221 return result;
222 }
223
224 static const char swz_txt[] = "xyzw";
225
226 std::ostream& operator << (std::ostream& os, const st_src_reg& reg)
227 {
228 if (reg.negate)
229 os << "-";
230 if (reg.abs)
231 os << "|";
232
233 os << _mesa_register_file_name(reg.file);
234
235 if (reg.file == PROGRAM_ARRAY) {
236 os << "(" << reg.array_id << ")";
237 }
238 if (reg.has_index2) {
239 os << "[";
240 if (reg.reladdr2) {
241 os << *reg.reladdr2;
242 }
243 os << "+" << reg.index2D << "]";
244 }
245 os << "[";
246 if (reg.reladdr) {
247 os << *reg.reladdr;
248 }
249 os << reg.index << "].";
250 for (int i = 0; i < 4; ++i) {
251 int swz = GET_SWZ(reg.swizzle, i);
252 if (swz < 4)
253 os << swz_txt[swz];
254 else
255 os << "_";
256 }
257 if (reg.abs)
258 os << "|";
259 return os;
260 }
261
262 st_dst_reg::st_dst_reg(st_src_reg reg)
263 {
264 this->type = reg.type;
265 this->file = reg.file;
266 this->index = reg.index;
267 this->writemask = WRITEMASK_XYZW;
268 this->reladdr = dup_reladdr(reg.reladdr);
269 this->index2D = reg.index2D;
270 this->reladdr2 = dup_reladdr(reg.reladdr2);
271 this->has_index2 = reg.has_index2;
272 this->array_id = reg.array_id;
273 }
274
275 st_dst_reg::st_dst_reg(gl_register_file file, int writemask, enum glsl_base_type type, int index)
276 {
277 assert(file != PROGRAM_ARRAY); /* need array_id > 0 */
278 this->file = file;
279 this->index = index;
280 this->index2D = 0;
281 this->writemask = writemask;
282 this->reladdr = NULL;
283 this->reladdr2 = NULL;
284 this->has_index2 = false;
285 this->type = type;
286 this->array_id = 0;
287 }
288
289 st_dst_reg::st_dst_reg(gl_register_file file, int writemask, enum glsl_base_type type)
290 {
291 assert(file != PROGRAM_ARRAY); /* need array_id > 0 */
292 this->file = file;
293 this->index = 0;
294 this->index2D = 0;
295 this->writemask = writemask;
296 this->reladdr = NULL;
297 this->reladdr2 = NULL;
298 this->has_index2 = false;
299 this->type = type;
300 this->array_id = 0;
301 }
302
303 st_dst_reg::st_dst_reg()
304 {
305 this->type = GLSL_TYPE_ERROR;
306 this->file = PROGRAM_UNDEFINED;
307 this->index = 0;
308 this->index2D = 0;
309 this->writemask = 0;
310 this->reladdr = NULL;
311 this->reladdr2 = NULL;
312 this->has_index2 = false;
313 this->array_id = 0;
314 }
315
316 st_dst_reg::st_dst_reg(const st_dst_reg &reg)
317 {
318 *this = reg;
319 }
320
321 void st_dst_reg::operator=(const st_dst_reg &reg)
322 {
323 this->type = reg.type;
324 this->file = reg.file;
325 this->index = reg.index;
326 this->writemask = reg.writemask;
327 this->reladdr = dup_reladdr(reg.reladdr);
328 this->index2D = reg.index2D;
329 this->reladdr2 = dup_reladdr(reg.reladdr2);
330 this->has_index2 = reg.has_index2;
331 this->array_id = reg.array_id;
332 }
333
334 bool operator == (const st_dst_reg& lhs, const st_dst_reg& rhs)
335 {
336 bool result;
337
338 if (lhs.type != rhs.type ||
339 lhs.file != rhs.file ||
340 lhs.index != rhs.index ||
341 lhs.writemask != rhs.writemask ||
342 lhs.index2D != rhs.index2D ||
343 lhs.has_index2 != rhs.has_index2 ||
344 lhs.array_id != rhs.array_id)
345 return false;
346
347 if (lhs.reladdr) {
348 if (!rhs.reladdr)
349 return false;
350 result = (*lhs.reladdr == *rhs.reladdr);
351 } else {
352 result = !rhs.reladdr;
353 }
354
355 if (lhs.reladdr2) {
356 if (!rhs.reladdr2)
357 return false;
358 result &= (*lhs.reladdr2 == *rhs.reladdr2);
359 } else {
360 result &= !rhs.reladdr2;
361 }
362
363 return result;
364 }
365
366 std::ostream& operator << (std::ostream& os, const st_dst_reg& reg)
367 {
368 os << _mesa_register_file_name(reg.file);
369 if (reg.file == PROGRAM_ARRAY) {
370 os << "(" << reg.array_id << ")";
371 }
372 if (reg.has_index2) {
373 os << "[";
374 if (reg.reladdr2) {
375 os << *reg.reladdr2;
376 }
377 os << "+" << reg.index2D << "]";
378 }
379 os << "[";
380 if (reg.reladdr) {
381 os << *reg.reladdr;
382 }
383 os << reg.index << "].";
384 for (int i = 0; i < 4; ++i) {
385 if (1 << i & reg.writemask)
386 os << swz_txt[i];
387 else
388 os << "_";
389 }
390
391 return os;
392 }
393
394 void glsl_to_tgsi_instruction::print(std::ostream& os) const
395 {
396 os << tgsi_get_opcode_name(info->opcode) << " ";
397
398 bool has_operators = false;
399 for (unsigned j = 0; j < num_inst_dst_regs(this); j++) {
400 has_operators = true;
401 if (j > 0)
402 os << ", ";
403 os << dst[j];
404 }
405
406 if (has_operators)
407 os << " := ";
408
409 for (unsigned j = 0; j < num_inst_src_regs(this); j++) {
410 if (j > 0)
411 os << ", ";
412 os << src[j];
413 }
414
415 if (tex_offset_num_offset > 0) {
416 os << ", TEXOFS: ";
417 for (unsigned j = 0; j < tex_offset_num_offset; j++) {
418 if (j > 0)
419 os << ", ";
420 os << tex_offsets[j];
421 }
422 }
423 }