5fcc9ee9ab4da5f5af4ccac9d65d5c5b8b98b60f
[mesa.git] / src / compiler / glsl / ir_expression_operation.py
1 #
2 # Copyright (C) 2015 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 import mako.template
24 import sys
25
26 class type(object):
27 def __init__(self, c_type, union_field, glsl_type):
28 self.c_type = c_type
29 self.union_field = union_field
30 self.glsl_type = glsl_type
31
32
33 class type_signature_iter(object):
34 """Basic iterator for a set of type signatures. Various kinds of sequences of
35 types come in, and an iteration of type_signature objects come out.
36
37 """
38
39 def __init__(self, source_types, num_operands):
40 """Initialize an iterator from a sequence of input types and a number
41 operands. This is for signatures where all the operands have the same
42 type and the result type of the operation is the same as the input type.
43
44 """
45 self.dest_type = None
46 self.source_types = source_types
47 self.num_operands = num_operands
48 self.i = 0
49
50 def __init__(self, dest_type, source_types, num_operands):
51 """Initialize an iterator from a result tpye, a sequence of input types and a
52 number operands. This is for signatures where all the operands have the
53 same type but the result type of the operation is different from the
54 input type.
55
56 """
57 self.dest_type = dest_type
58 self.source_types = source_types
59 self.num_operands = num_operands
60 self.i = 0
61
62 def __iter__(self):
63 return self
64
65 def __next__(self):
66 if self.i < len(self.source_types):
67 i = self.i
68 self.i += 1
69
70 if self.dest_type is None:
71 dest_type = self.source_types[i]
72 else:
73 dest_type = self.dest_type
74
75 return (dest_type, self.num_operands * (self.source_types[i],))
76 else:
77 raise StopIteration()
78
79 next = __next__
80
81
82 uint_type = type("unsigned", "u", "GLSL_TYPE_UINT")
83 int_type = type("int", "i", "GLSL_TYPE_INT")
84 uint64_type = type("uint64_t", "u64", "GLSL_TYPE_UINT64")
85 int64_type = type("int64_t", "i64", "GLSL_TYPE_INT64")
86 float_type = type("float", "f", "GLSL_TYPE_FLOAT")
87 double_type = type("double", "d", "GLSL_TYPE_DOUBLE")
88 bool_type = type("bool", "b", "GLSL_TYPE_BOOL")
89
90 all_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type, bool_type)
91 numeric_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type)
92 signed_numeric_types = (int_type, float_type, double_type, int64_type)
93 integer_types = (uint_type, int_type, uint64_type, int64_type)
94 real_types = (float_type, double_type)
95
96 # This template is for operations that can have operands of a several
97 # different types, and each type may or may not has a different C expression.
98 # This is used by most operations.
99 constant_template_common = mako.template.Template("""\
100 case ${op.get_enum_name()}:
101 for (unsigned c = 0; c < op[0]->type->components(); c++) {
102 switch (op[0]->type->base_type) {
103 % for dst_type, src_types in op.signatures():
104 case ${src_types[0].glsl_type}:
105 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
106 break;
107 % endfor
108 default:
109 unreachable("invalid type");
110 }
111 }
112 break;""")
113
114 # This template is for binary operations that can operate on some combination
115 # of scalar and vector operands.
116 constant_template_vector_scalar = mako.template.Template("""\
117 case ${op.get_enum_name()}:
118 % if "mixed" in op.flags:
119 % for i in range(op.num_operands):
120 assert(op[${i}]->type->base_type == ${op.source_types[0].glsl_type} ||
121 % for src_type in op.source_types[1:-1]:
122 op[${i}]->type->base_type == ${src_type.glsl_type} ||
123 % endfor
124 op[${i}]->type->base_type == ${op.source_types[-1].glsl_type});
125 % endfor
126 % else:
127 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
128 % endif
129 for (unsigned c = 0, c0 = 0, c1 = 0;
130 c < components;
131 c0 += c0_inc, c1 += c1_inc, c++) {
132
133 switch (op[0]->type->base_type) {
134 % for dst_type, src_types in op.signatures():
135 case ${src_types[0].glsl_type}:
136 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
137 break;
138 % endfor
139 default:
140 unreachable("invalid type");
141 }
142 }
143 break;""")
144
145 # This template is for multiplication. It is unique because it has to support
146 # matrix * vector and matrix * matrix operations, and those are just different.
147 constant_template_mul = mako.template.Template("""\
148 case ${op.get_enum_name()}:
149 /* Check for equal types, or unequal types involving scalars */
150 if ((op[0]->type == op[1]->type && !op[0]->type->is_matrix())
151 || op0_scalar || op1_scalar) {
152 for (unsigned c = 0, c0 = 0, c1 = 0;
153 c < components;
154 c0 += c0_inc, c1 += c1_inc, c++) {
155
156 switch (op[0]->type->base_type) {
157 % for dst_type, src_types in op.signatures():
158 case ${src_types[0].glsl_type}:
159 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
160 break;
161 % endfor
162 default:
163 unreachable("invalid type");
164 }
165 }
166 } else {
167 assert(op[0]->type->is_matrix() || op[1]->type->is_matrix());
168
169 /* Multiply an N-by-M matrix with an M-by-P matrix. Since either
170 * matrix can be a GLSL vector, either N or P can be 1.
171 *
172 * For vec*mat, the vector is treated as a row vector. This
173 * means the vector is a 1-row x M-column matrix.
174 *
175 * For mat*vec, the vector is treated as a column vector. Since
176 * matrix_columns is 1 for vectors, this just works.
177 */
178 const unsigned n = op[0]->type->is_vector()
179 ? 1 : op[0]->type->vector_elements;
180 const unsigned m = op[1]->type->vector_elements;
181 const unsigned p = op[1]->type->matrix_columns;
182 for (unsigned j = 0; j < p; j++) {
183 for (unsigned i = 0; i < n; i++) {
184 for (unsigned k = 0; k < m; k++) {
185 if (op[0]->type->is_double())
186 data.d[i+n*j] += op[0]->value.d[i+n*k]*op[1]->value.d[k+m*j];
187 else
188 data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
189 }
190 }
191 }
192 }
193 break;""")
194
195 # This template is for operations that are horizontal and either have only a
196 # single type or the implementation for all types is identical. That is, the
197 # operation consumes a vector and produces a scalar.
198 constant_template_horizontal_single_implementation = mako.template.Template("""\
199 case ${op.get_enum_name()}:
200 data.${op.dest_type.union_field}[0] = ${op.c_expression['default']};
201 break;""")
202
203 # This template is for operations that are horizontal and do not assign the
204 # result. The various unpack operations are examples.
205 constant_template_horizontal_nonassignment = mako.template.Template("""\
206 case ${op.get_enum_name()}:
207 ${op.c_expression['default']};
208 break;""")
209
210 # This template is for binary operations that are horizontal. That is, the
211 # operation consumes a vector and produces a scalar.
212 constant_template_horizontal = mako.template.Template("""\
213 case ${op.get_enum_name()}:
214 switch (op[0]->type->base_type) {
215 % for dst_type, src_types in op.signatures():
216 case ${src_types[0].glsl_type}:
217 data.${dst_type.union_field}[0] = ${op.get_c_expression(src_types)};
218 break;
219 % endfor
220 default:
221 unreachable("invalid type");
222 }
223 break;""")
224
225 # This template is for ir_binop_vector_extract.
226 constant_template_vector_extract = mako.template.Template("""\
227 case ${op.get_enum_name()}: {
228 const int c = CLAMP(op[1]->value.i[0], 0,
229 (int) op[0]->type->vector_elements - 1);
230
231 switch (op[0]->type->base_type) {
232 % for dst_type, src_types in op.signatures():
233 case ${src_types[0].glsl_type}:
234 data.${dst_type.union_field}[0] = op[0]->value.${src_types[0].union_field}[c];
235 break;
236 % endfor
237 default:
238 unreachable("invalid type");
239 }
240 break;
241 }""")
242
243 # This template is for ir_triop_vector_insert.
244 constant_template_vector_insert = mako.template.Template("""\
245 case ${op.get_enum_name()}: {
246 const unsigned idx = op[2]->value.u[0];
247
248 memcpy(&data, &op[0]->value, sizeof(data));
249
250 switch (this->type->base_type) {
251 % for dst_type, src_types in op.signatures():
252 case ${src_types[0].glsl_type}:
253 data.${dst_type.union_field}[idx] = op[1]->value.${src_types[0].union_field}[0];
254 break;
255 % endfor
256 default:
257 unreachable("invalid type");
258 }
259 break;
260 }""")
261
262 # This template is for ir_quadop_vector.
263 constant_template_vector = mako.template.Template("""\
264 case ${op.get_enum_name()}:
265 for (unsigned c = 0; c < this->type->vector_elements; c++) {
266 switch (this->type->base_type) {
267 % for dst_type, src_types in op.signatures():
268 case ${src_types[0].glsl_type}:
269 data.${dst_type.union_field}[c] = op[c]->value.${src_types[0].union_field}[0];
270 break;
271 % endfor
272 default:
273 unreachable("invalid type");
274 }
275 }
276 break;""")
277
278 # This template is for ir_triop_lrp.
279 constant_template_lrp = mako.template.Template("""\
280 case ${op.get_enum_name()}: {
281 assert(op[0]->type->is_float() || op[0]->type->is_double());
282 assert(op[1]->type->is_float() || op[1]->type->is_double());
283 assert(op[2]->type->is_float() || op[2]->type->is_double());
284
285 unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
286 for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
287 switch (this->type->base_type) {
288 % for dst_type, src_types in op.signatures():
289 case ${src_types[0].glsl_type}:
290 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c", "c", "c2"))};
291 break;
292 % endfor
293 default:
294 unreachable("invalid type");
295 }
296 }
297 break;
298 }""")
299
300 # This template is for ir_triop_csel. This expression is really unique
301 # because not all of the operands are the same type, and the second operand
302 # determines the type of the expression (instead of the first).
303 constant_template_csel = mako.template.Template("""\
304 case ${op.get_enum_name()}:
305 for (unsigned c = 0; c < components; c++) {
306 switch (this->type->base_type) {
307 % for dst_type, src_types in op.signatures():
308 case ${src_types[1].glsl_type}:
309 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
310 break;
311 % endfor
312 default:
313 unreachable("invalid type");
314 }
315 }
316 break;""")
317
318
319 vector_scalar_operation = "vector-scalar"
320 horizontal_operation = "horizontal"
321 types_identical_operation = "identical"
322 non_assign_operation = "nonassign"
323 mixed_type_operation = "mixed"
324
325 class operation(object):
326 def __init__(self, name, num_operands, printable_name = None, source_types = None, dest_type = None, c_expression = None, flags = None, all_signatures = None):
327 self.name = name
328 self.num_operands = num_operands
329
330 if printable_name is None:
331 self.printable_name = name
332 else:
333 self.printable_name = printable_name
334
335 self.all_signatures = all_signatures
336
337 if source_types is None:
338 self.source_types = tuple()
339 else:
340 self.source_types = source_types
341
342 self.dest_type = dest_type
343
344 if c_expression is None:
345 self.c_expression = None
346 elif isinstance(c_expression, str):
347 self.c_expression = {'default': c_expression}
348 else:
349 self.c_expression = c_expression
350
351 if flags is None:
352 self.flags = frozenset()
353 elif isinstance(flags, str):
354 self.flags = frozenset([flags])
355 else:
356 self.flags = frozenset(flags)
357
358
359 def get_enum_name(self):
360 return "ir_{0}op_{1}".format(("un", "bin", "tri", "quad")[self.num_operands-1], self.name)
361
362
363 def get_template(self):
364 if self.c_expression is None:
365 return None
366
367 if horizontal_operation in self.flags:
368 if non_assign_operation in self.flags:
369 return constant_template_horizontal_nonassignment.render(op=self)
370 elif types_identical_operation in self.flags:
371 return constant_template_horizontal_single_implementation.render(op=self)
372 else:
373 return constant_template_horizontal.render(op=self)
374
375 if self.num_operands == 2:
376 if self.name == "mul":
377 return constant_template_mul.render(op=self)
378 elif self.name == "vector_extract":
379 return constant_template_vector_extract.render(op=self)
380 elif vector_scalar_operation in self.flags:
381 return constant_template_vector_scalar.render(op=self)
382 elif self.num_operands == 3:
383 if self.name == "vector_insert":
384 return constant_template_vector_insert.render(op=self)
385 elif self.name == "lrp":
386 return constant_template_lrp.render(op=self)
387 elif self.name == "csel":
388 return constant_template_csel.render(op=self)
389 elif self.num_operands == 4:
390 if self.name == "vector":
391 return constant_template_vector.render(op=self)
392
393 return constant_template_common.render(op=self)
394
395
396 def get_c_expression(self, types, indices=("c", "c", "c")):
397 src0 = "op[0]->value.{0}[{1}]".format(types[0].union_field, indices[0])
398 src1 = "op[1]->value.{0}[{1}]".format(types[1].union_field, indices[1]) if len(types) >= 2 else "ERROR"
399 src2 = "op[2]->value.{0}[{1}]".format(types[2].union_field, indices[2]) if len(types) >= 3 else "ERROR"
400 src3 = "op[3]->value.{0}[c]".format(types[3].union_field) if len(types) >= 4 else "ERROR"
401
402 expr = self.c_expression[types[0].union_field] if types[0].union_field in self.c_expression else self.c_expression['default']
403
404 return expr.format(src0=src0,
405 src1=src1,
406 src2=src2,
407 src3=src3)
408
409
410 def signatures(self):
411 if self.all_signatures is not None:
412 return self.all_signatures
413 else:
414 return type_signature_iter(self.dest_type, self.source_types, self.num_operands)
415
416
417 ir_expression_operation = [
418 operation("bit_not", 1, printable_name="~", source_types=integer_types, c_expression="~ {src0}"),
419 operation("logic_not", 1, printable_name="!", source_types=(bool_type,), c_expression="!{src0}"),
420 operation("neg", 1, source_types=numeric_types, c_expression={'u': "-((int) {src0})", 'u64': "-((int64_t) {src0})", 'default': "-{src0}"}),
421 operation("abs", 1, source_types=signed_numeric_types, c_expression={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({src0})", 'i64': "{src0} < 0 ? -{src0} : {src0}"}),
422 operation("sign", 1, source_types=signed_numeric_types, c_expression={'i': "({src0} > 0) - ({src0} < 0)", 'f': "float(({src0} > 0.0F) - ({src0} < 0.0F))", 'd': "double(({src0} > 0.0) - ({src0} < 0.0))", 'i64': "({src0} > 0) - ({src0} < 0)"}),
423 operation("rcp", 1, source_types=real_types, c_expression={'f': "1.0F / {src0}", 'd': "1.0 / {src0}"}),
424 operation("rsq", 1, source_types=real_types, c_expression={'f': "1.0F / sqrtf({src0})", 'd': "1.0 / sqrt({src0})"}),
425 operation("sqrt", 1, source_types=real_types, c_expression={'f': "sqrtf({src0})", 'd': "sqrt({src0})"}),
426 operation("exp", 1, source_types=(float_type,), c_expression="expf({src0})"), # Log base e on gentype
427 operation("log", 1, source_types=(float_type,), c_expression="logf({src0})"), # Natural log on gentype
428 operation("exp2", 1, source_types=(float_type,), c_expression="exp2f({src0})"),
429 operation("log2", 1, source_types=(float_type,), c_expression="log2f({src0})"),
430
431 # Float-to-integer conversion.
432 operation("f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="(int) {src0}"),
433 # Float-to-unsigned conversion.
434 operation("f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="(unsigned) {src0}"),
435 # Integer-to-float conversion.
436 operation("i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="(float) {src0}"),
437 # Float-to-boolean conversion
438 operation("f2b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0F ? true : false"),
439 # Boolean-to-float conversion
440 operation("b2f", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"),
441 # Boolean-to-float16 conversion
442 operation("b2f16", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"),
443 # int-to-boolean conversion
444 operation("i2b", 1, source_types=(uint_type, int_type), dest_type=bool_type, c_expression="{src0} ? true : false"),
445 # Boolean-to-int conversion
446 operation("b2i", 1, source_types=(bool_type,), dest_type=int_type, c_expression="{src0} ? 1 : 0"),
447 # Unsigned-to-float conversion.
448 operation("u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="(float) {src0}"),
449 # Integer-to-unsigned conversion.
450 operation("i2u", 1, source_types=(int_type,), dest_type=uint_type, c_expression="{src0}"),
451 # Unsigned-to-integer conversion.
452 operation("u2i", 1, source_types=(uint_type,), dest_type=int_type, c_expression="{src0}"),
453 # Double-to-float conversion.
454 operation("d2f", 1, source_types=(double_type,), dest_type=float_type, c_expression="{src0}"),
455 # Float-to-double conversion.
456 operation("f2d", 1, source_types=(float_type,), dest_type=double_type, c_expression="{src0}"),
457 # Half-float conversions. These all operate on and return float types,
458 # since the framework expands half to full float before calling in. We
459 # still have to handle them here so that we can constant propagate through
460 # them, but they are no-ops.
461 operation("f2f16", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"),
462 operation("f2fmp", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"),
463 operation("f162f", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"),
464 # Double-to-integer conversion.
465 operation("d2i", 1, source_types=(double_type,), dest_type=int_type, c_expression="{src0}"),
466 # Integer-to-double conversion.
467 operation("i2d", 1, source_types=(int_type,), dest_type=double_type, c_expression="{src0}"),
468 # Double-to-unsigned conversion.
469 operation("d2u", 1, source_types=(double_type,), dest_type=uint_type, c_expression="{src0}"),
470 # Unsigned-to-double conversion.
471 operation("u2d", 1, source_types=(uint_type,), dest_type=double_type, c_expression="{src0}"),
472 # Double-to-boolean conversion.
473 operation("d2b", 1, source_types=(double_type,), dest_type=bool_type, c_expression="{src0} != 0.0"),
474 # Float16-to-boolean conversion.
475 operation("f162b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0"),
476 # 'Bit-identical int-to-float "conversion"
477 operation("bitcast_i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
478 # 'Bit-identical float-to-int "conversion"
479 operation("bitcast_f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="bitcast_f2u({src0})"),
480 # 'Bit-identical uint-to-float "conversion"
481 operation("bitcast_u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
482 # 'Bit-identical float-to-uint "conversion"
483 operation("bitcast_f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="bitcast_f2u({src0})"),
484 # Bit-identical u64-to-double "conversion"
485 operation("bitcast_u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="bitcast_u642d({src0})"),
486 # Bit-identical i64-to-double "conversion"
487 operation("bitcast_i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="bitcast_i642d({src0})"),
488 # Bit-identical double-to_u64 "conversion"
489 operation("bitcast_d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="bitcast_d2u64({src0})"),
490 # Bit-identical double-to-i64 "conversion"
491 operation("bitcast_d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="bitcast_d2i64({src0})"),
492 # i64-to-i32 conversion
493 operation("i642i", 1, source_types=(int64_type,), dest_type=int_type, c_expression="{src0}"),
494 # ui64-to-i32 conversion
495 operation("u642i", 1, source_types=(uint64_type,), dest_type=int_type, c_expression="{src0}"),
496 operation("i642u", 1, source_types=(int64_type,), dest_type=uint_type, c_expression="{src0}"),
497 operation("u642u", 1, source_types=(uint64_type,), dest_type=uint_type, c_expression="{src0}"),
498 operation("i642b", 1, source_types=(int64_type,), dest_type=bool_type, c_expression="{src0} != 0"),
499 operation("i642f", 1, source_types=(int64_type,), dest_type=float_type, c_expression="{src0}"),
500 operation("u642f", 1, source_types=(uint64_type,), dest_type=float_type, c_expression="{src0}"),
501 operation("i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="{src0}"),
502 operation("u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="{src0}"),
503 operation("i2i64", 1, source_types=(int_type,), dest_type=int64_type, c_expression="{src0}"),
504 operation("u2i64", 1, source_types=(uint_type,), dest_type=int64_type, c_expression="{src0}"),
505 operation("b2i64", 1, source_types=(bool_type,), dest_type=int64_type, c_expression="{src0}"),
506 operation("f2i64", 1, source_types=(float_type,), dest_type=int64_type, c_expression="{src0}"),
507 operation("d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="{src0}"),
508 operation("i2u64", 1, source_types=(int_type,), dest_type=uint64_type, c_expression="{src0}"),
509 operation("u2u64", 1, source_types=(uint_type,), dest_type=uint64_type, c_expression="{src0}"),
510 operation("f2u64", 1, source_types=(float_type,), dest_type=uint64_type, c_expression="{src0}"),
511 operation("d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="{src0}"),
512 operation("u642i64", 1, source_types=(uint64_type,), dest_type=int64_type, c_expression="{src0}"),
513 operation("i642u64", 1, source_types=(int64_type,), dest_type=uint64_type, c_expression="{src0}"),
514
515
516 # Unary floating-point rounding operations.
517 operation("trunc", 1, source_types=real_types, c_expression={'f': "truncf({src0})", 'd': "trunc({src0})"}),
518 operation("ceil", 1, source_types=real_types, c_expression={'f': "ceilf({src0})", 'd': "ceil({src0})"}),
519 operation("floor", 1, source_types=real_types, c_expression={'f': "floorf({src0})", 'd': "floor({src0})"}),
520 operation("fract", 1, source_types=real_types, c_expression={'f': "{src0} - floorf({src0})", 'd': "{src0} - floor({src0})"}),
521 operation("round_even", 1, source_types=real_types, c_expression={'f': "_mesa_roundevenf({src0})", 'd': "_mesa_roundeven({src0})"}),
522
523 # Trigonometric operations.
524 operation("sin", 1, source_types=(float_type,), c_expression="sinf({src0})"),
525 operation("cos", 1, source_types=(float_type,), c_expression="cosf({src0})"),
526 operation("atan", 1, source_types=(float_type,), c_expression="atan({src0})"),
527
528 # Partial derivatives.
529 operation("dFdx", 1, source_types=(float_type,), c_expression="0.0f"),
530 operation("dFdx_coarse", 1, printable_name="dFdxCoarse", source_types=(float_type,), c_expression="0.0f"),
531 operation("dFdx_fine", 1, printable_name="dFdxFine", source_types=(float_type,), c_expression="0.0f"),
532 operation("dFdy", 1, source_types=(float_type,), c_expression="0.0f"),
533 operation("dFdy_coarse", 1, printable_name="dFdyCoarse", source_types=(float_type,), c_expression="0.0f"),
534 operation("dFdy_fine", 1, printable_name="dFdyFine", source_types=(float_type,), c_expression="0.0f"),
535
536 # Floating point pack and unpack operations.
537 operation("pack_snorm_2x16", 1, printable_name="packSnorm2x16", source_types=(float_type,), dest_type=uint_type, c_expression="pack_2x16(pack_snorm_1x16, op[0]->value.f[0], op[0]->value.f[1])", flags=horizontal_operation),
538 operation("pack_snorm_4x8", 1, printable_name="packSnorm4x8", source_types=(float_type,), dest_type=uint_type, c_expression="pack_4x8(pack_snorm_1x8, op[0]->value.f[0], op[0]->value.f[1], op[0]->value.f[2], op[0]->value.f[3])", flags=horizontal_operation),
539 operation("pack_unorm_2x16", 1, printable_name="packUnorm2x16", source_types=(float_type,), dest_type=uint_type, c_expression="pack_2x16(pack_unorm_1x16, op[0]->value.f[0], op[0]->value.f[1])", flags=horizontal_operation),
540 operation("pack_unorm_4x8", 1, printable_name="packUnorm4x8", source_types=(float_type,), dest_type=uint_type, c_expression="pack_4x8(pack_unorm_1x8, op[0]->value.f[0], op[0]->value.f[1], op[0]->value.f[2], op[0]->value.f[3])", flags=horizontal_operation),
541 operation("pack_half_2x16", 1, printable_name="packHalf2x16", source_types=(float_type,), dest_type=uint_type, c_expression="pack_2x16(pack_half_1x16, op[0]->value.f[0], op[0]->value.f[1])", flags=horizontal_operation),
542 operation("unpack_snorm_2x16", 1, printable_name="unpackSnorm2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_snorm_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
543 operation("unpack_snorm_4x8", 1, printable_name="unpackSnorm4x8", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_4x8(unpack_snorm_1x8, op[0]->value.u[0], &data.f[0], &data.f[1], &data.f[2], &data.f[3])", flags=frozenset((horizontal_operation, non_assign_operation))),
544 operation("unpack_unorm_2x16", 1, printable_name="unpackUnorm2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_unorm_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
545 operation("unpack_unorm_4x8", 1, printable_name="unpackUnorm4x8", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_4x8(unpack_unorm_1x8, op[0]->value.u[0], &data.f[0], &data.f[1], &data.f[2], &data.f[3])", flags=frozenset((horizontal_operation, non_assign_operation))),
546 operation("unpack_half_2x16", 1, printable_name="unpackHalf2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_half_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
547
548 # Bit operations, part of ARB_gpu_shader5.
549 operation("bitfield_reverse", 1, source_types=(uint_type, int_type), c_expression="bitfield_reverse({src0})"),
550 operation("bit_count", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="util_bitcount({src0})"),
551 operation("find_msb", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression={'u': "find_msb_uint({src0})", 'i': "find_msb_int({src0})"}),
552 operation("find_lsb", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="find_msb_uint({src0} & -{src0})"),
553 operation("clz", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="(unsigned)(31 - find_msb_uint({src0}))"),
554
555 operation("saturate", 1, printable_name="sat", source_types=(float_type,), c_expression="CLAMP({src0}, 0.0f, 1.0f)"),
556
557 # Double packing, part of ARB_gpu_shader_fp64.
558 operation("pack_double_2x32", 1, printable_name="packDouble2x32", source_types=(uint_type,), dest_type=double_type, c_expression="memcpy(&data.d[0], &op[0]->value.u[0], sizeof(double))", flags=frozenset((horizontal_operation, non_assign_operation))),
559 operation("unpack_double_2x32", 1, printable_name="unpackDouble2x32", source_types=(double_type,), dest_type=uint_type, c_expression="memcpy(&data.u[0], &op[0]->value.d[0], sizeof(double))", flags=frozenset((horizontal_operation, non_assign_operation))),
560
561 # Sampler/Image packing, part of ARB_bindless_texture.
562 operation("pack_sampler_2x32", 1, printable_name="packSampler2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="memcpy(&data.u64[0], &op[0]->value.u[0], sizeof(uint64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
563 operation("pack_image_2x32", 1, printable_name="packImage2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="memcpy(&data.u64[0], &op[0]->value.u[0], sizeof(uint64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
564 operation("unpack_sampler_2x32", 1, printable_name="unpackSampler2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="memcpy(&data.u[0], &op[0]->value.u64[0], sizeof(uint64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
565 operation("unpack_image_2x32", 1, printable_name="unpackImage2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="memcpy(&data.u[0], &op[0]->value.u64[0], sizeof(uint64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
566
567 operation("frexp_sig", 1),
568 operation("frexp_exp", 1),
569
570 operation("noise", 1),
571
572 operation("subroutine_to_int", 1),
573
574 # Interpolate fs input at centroid
575 #
576 # operand0 is the fs input.
577 operation("interpolate_at_centroid", 1),
578
579 # Ask the driver for the total size of a buffer block.
580 # operand0 is the ir_constant buffer block index in the linked shader.
581 operation("get_buffer_size", 1),
582
583 # Calculate length of an unsized array inside a buffer block.
584 # This opcode is going to be replaced in a lowering pass inside
585 # the linker.
586 #
587 # operand0 is the unsized array's ir_value for the calculation
588 # of its length.
589 operation("ssbo_unsized_array_length", 1),
590
591 # 64-bit integer packing ops.
592 operation("pack_int_2x32", 1, printable_name="packInt2x32", source_types=(int_type,), dest_type=int64_type, c_expression="memcpy(&data.i64[0], &op[0]->value.i[0], sizeof(int64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
593 operation("pack_uint_2x32", 1, printable_name="packUint2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="memcpy(&data.u64[0], &op[0]->value.u[0], sizeof(uint64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
594 operation("unpack_int_2x32", 1, printable_name="unpackInt2x32", source_types=(int64_type,), dest_type=int_type, c_expression="memcpy(&data.i[0], &op[0]->value.i64[0], sizeof(int64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
595 operation("unpack_uint_2x32", 1, printable_name="unpackUint2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="memcpy(&data.u[0], &op[0]->value.u64[0], sizeof(uint64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
596
597 operation("add", 2, printable_name="+", source_types=numeric_types, c_expression="{src0} + {src1}", flags=vector_scalar_operation),
598 operation("sub", 2, printable_name="-", source_types=numeric_types, c_expression="{src0} - {src1}", flags=vector_scalar_operation),
599 operation("add_sat", 2, printable_name="add_sat", source_types=integer_types, c_expression={
600 'u': "({src0} + {src1}) < {src0} ? UINT32_MAX : ({src0} + {src1})",
601 'i': "iadd_saturate({src0}, {src1})",
602 'u64': "({src0} + {src1}) < {src0} ? UINT64_MAX : ({src0} + {src1})",
603 'i64': "iadd64_saturate({src0}, {src1})"
604 }),
605 operation("sub_sat", 2, printable_name="sub_sat", source_types=integer_types, c_expression={
606 'u': "({src1} > {src0}) ? 0 : {src0} - {src1}",
607 'i': "isub_saturate({src0}, {src1})",
608 'u64': "({src1} > {src0}) ? 0 : {src0} - {src1}",
609 'i64': "isub64_saturate({src0}, {src1})"
610 }),
611 operation("abs_sub", 2, printable_name="abs_sub", source_types=integer_types, c_expression={
612 'u': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}",
613 'i': "({src1} > {src0}) ? (unsigned){src1} - (unsigned){src0} : (unsigned){src0} - (unsigned){src1}",
614 'u64': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}",
615 'i64': "({src1} > {src0}) ? (uint64_t){src1} - (uint64_t){src0} : (uint64_t){src0} - (uint64_t){src1}",
616 }),
617 operation("avg", 2, printable_name="average", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} & {src1}) & 1)"),
618 operation("avg_round", 2, printable_name="average_rounded", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} | {src1}) & 1)"),
619
620 # "Floating-point or low 32-bit integer multiply."
621 operation("mul", 2, printable_name="*", source_types=numeric_types, c_expression="{src0} * {src1}"),
622 operation("mul_32x16", 2, printable_name="*", source_types=(uint_type, int_type), c_expression={
623 'u': "{src0} * (uint16_t){src1}",
624 'i': "{src0} * (int16_t){src0}"
625 }),
626 operation("imul_high", 2), # Calculates the high 32-bits of a 64-bit multiply.
627 operation("div", 2, printable_name="/", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} / {src1}", 'i': "{src1} == 0 ? 0 : {src0} / {src1}", 'u64': "{src1} == 0 ? 0 : {src0} / {src1}", 'i64': "{src1} == 0 ? 0 : {src0} / {src1}", 'default': "{src0} / {src1}"}, flags=vector_scalar_operation),
628
629 # Returns the carry resulting from the addition of the two arguments.
630 operation("carry", 2),
631
632 # Returns the borrow resulting from the subtraction of the second argument
633 # from the first argument.
634 operation("borrow", 2),
635
636 # Either (vector % vector) or (vector % scalar)
637 #
638 # We don't use fmod because it rounds toward zero; GLSL specifies the use
639 # of floor.
640 operation("mod", 2, printable_name="%", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} % {src1}", 'i': "{src1} == 0 ? 0 : {src0} % {src1}", 'f': "{src0} - {src1} * floorf({src0} / {src1})", 'd': "{src0} - {src1} * floor({src0} / {src1})", 'u64': "{src1} == 0 ? 0 : {src0} % {src1}", 'i64': "{src1} == 0 ? 0 : {src0} % {src1}"}, flags=vector_scalar_operation),
641
642 # Binary comparison operators which return a boolean vector.
643 # The type of both operands must be equal.
644 operation("less", 2, printable_name="<", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} < {src1}"),
645 operation("gequal", 2, printable_name=">=", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} >= {src1}"),
646 operation("equal", 2, printable_name="==", source_types=all_types, dest_type=bool_type, c_expression="{src0} == {src1}"),
647 operation("nequal", 2, printable_name="!=", source_types=all_types, dest_type=bool_type, c_expression="{src0} != {src1}"),
648
649 # Returns single boolean for whether all components of operands[0]
650 # equal the components of operands[1].
651 operation("all_equal", 2, source_types=all_types, dest_type=bool_type, c_expression="op[0]->has_value(op[1])", flags=frozenset((horizontal_operation, types_identical_operation))),
652
653 # Returns single boolean for whether any component of operands[0]
654 # is not equal to the corresponding component of operands[1].
655 operation("any_nequal", 2, source_types=all_types, dest_type=bool_type, c_expression="!op[0]->has_value(op[1])", flags=frozenset((horizontal_operation, types_identical_operation))),
656
657 # Bit-wise binary operations.
658 operation("lshift", 2, printable_name="<<", source_types=integer_types, c_expression="{src0} << {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
659 operation("rshift", 2, printable_name=">>", source_types=integer_types, c_expression="{src0} >> {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
660 operation("bit_and", 2, printable_name="&", source_types=integer_types, c_expression="{src0} & {src1}", flags=vector_scalar_operation),
661 operation("bit_xor", 2, printable_name="^", source_types=integer_types, c_expression="{src0} ^ {src1}", flags=vector_scalar_operation),
662 operation("bit_or", 2, printable_name="|", source_types=integer_types, c_expression="{src0} | {src1}", flags=vector_scalar_operation),
663
664 operation("logic_and", 2, printable_name="&&", source_types=(bool_type,), c_expression="{src0} && {src1}"),
665 operation("logic_xor", 2, printable_name="^^", source_types=(bool_type,), c_expression="{src0} != {src1}"),
666 operation("logic_or", 2, printable_name="||", source_types=(bool_type,), c_expression="{src0} || {src1}"),
667
668 operation("dot", 2, source_types=real_types, c_expression={'f': "dot_f(op[0], op[1])", 'd': "dot_d(op[0], op[1])"}, flags=horizontal_operation),
669 operation("min", 2, source_types=numeric_types, c_expression="MIN2({src0}, {src1})", flags=vector_scalar_operation),
670 operation("max", 2, source_types=numeric_types, c_expression="MAX2({src0}, {src1})", flags=vector_scalar_operation),
671
672 operation("pow", 2, source_types=(float_type,), c_expression="powf({src0}, {src1})"),
673
674 # Load a value the size of a given GLSL type from a uniform block.
675 #
676 # operand0 is the ir_constant uniform block index in the linked shader.
677 # operand1 is a byte offset within the uniform block.
678 operation("ubo_load", 2),
679
680 # Multiplies a number by two to a power, part of ARB_gpu_shader5.
681 operation("ldexp", 2,
682 all_signatures=((float_type, (float_type, int_type)),
683 (double_type, (double_type, int_type))),
684 c_expression={'f': "ldexpf_flush_subnormal({src0}, {src1})",
685 'd': "ldexp_flush_subnormal({src0}, {src1})"}),
686
687 # Extract a scalar from a vector
688 #
689 # operand0 is the vector
690 # operand1 is the index of the field to read from operand0
691 operation("vector_extract", 2, source_types=all_types, c_expression="anything-except-None"),
692
693 # Interpolate fs input at offset
694 #
695 # operand0 is the fs input
696 # operand1 is the offset from the pixel center
697 operation("interpolate_at_offset", 2),
698
699 # Interpolate fs input at sample position
700 #
701 # operand0 is the fs input
702 # operand1 is the sample ID
703 operation("interpolate_at_sample", 2),
704
705 operation("atan2", 2, source_types=(float_type,), c_expression="atan2({src0}, {src1})"),
706
707 # Fused floating-point multiply-add, part of ARB_gpu_shader5.
708 operation("fma", 3, source_types=real_types, c_expression="{src0} * {src1} + {src2}"),
709
710 operation("lrp", 3, source_types=real_types, c_expression={'f': "{src0} * (1.0f - {src2}) + ({src1} * {src2})", 'd': "{src0} * (1.0 - {src2}) + ({src1} * {src2})"}),
711
712 # Conditional Select
713 #
714 # A vector conditional select instruction (like ?:, but operating per-
715 # component on vectors).
716 #
717 # See also lower_instructions_visitor::ldexp_to_arith
718 operation("csel", 3,
719 all_signatures=zip(all_types, zip(len(all_types) * (bool_type,), all_types, all_types)),
720 c_expression="{src0} ? {src1} : {src2}"),
721
722 operation("bitfield_extract", 3,
723 all_signatures=((int_type, (uint_type, int_type, int_type)),
724 (int_type, (int_type, int_type, int_type))),
725 c_expression={'u': "bitfield_extract_uint({src0}, {src1}, {src2})",
726 'i': "bitfield_extract_int({src0}, {src1}, {src2})"}),
727
728 # Generate a value with one field of a vector changed
729 #
730 # operand0 is the vector
731 # operand1 is the value to write into the vector result
732 # operand2 is the index in operand0 to be modified
733 operation("vector_insert", 3, source_types=all_types, c_expression="anything-except-None"),
734
735 operation("bitfield_insert", 4,
736 all_signatures=((uint_type, (uint_type, uint_type, int_type, int_type)),
737 (int_type, (int_type, int_type, int_type, int_type))),
738 c_expression="bitfield_insert({src0}, {src1}, {src2}, {src3})"),
739
740 operation("vector", 4, source_types=all_types, c_expression="anything-except-None"),
741 ]
742
743
744 if __name__ == "__main__":
745 copyright = """/*
746 * Copyright (C) 2010 Intel Corporation
747 *
748 * Permission is hereby granted, free of charge, to any person obtaining a
749 * copy of this software and associated documentation files (the "Software"),
750 * to deal in the Software without restriction, including without limitation
751 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
752 * and/or sell copies of the Software, and to permit persons to whom the
753 * Software is furnished to do so, subject to the following conditions:
754 *
755 * The above copyright notice and this permission notice (including the next
756 * paragraph) shall be included in all copies or substantial portions of the
757 * Software.
758 *
759 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
760 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
761 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
762 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
763 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
764 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
765 * DEALINGS IN THE SOFTWARE.
766 */
767 """
768 enum_template = mako.template.Template(copyright + """
769 enum ir_expression_operation {
770 % for item in values:
771 ${item.get_enum_name()},
772 % endfor
773
774 /* Sentinels marking the last of each kind of operation. */
775 % for item in lasts:
776 ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()},
777 % endfor
778 ir_last_opcode = ir_quadop_${lasts[3].name}
779 };""")
780
781 strings_template = mako.template.Template(copyright + """
782 const char *const ir_expression_operation_strings[] = {
783 % for item in values:
784 "${item.printable_name}",
785 % endfor
786 };
787
788 const char *const ir_expression_operation_enum_strings[] = {
789 % for item in values:
790 "${item.name}",
791 % endfor
792 };""")
793
794 constant_template = mako.template.Template("""\
795 switch (this->operation) {
796 % for op in values:
797 % if op.c_expression is not None:
798 ${op.get_template()}
799
800 % endif
801 % endfor
802 default:
803 /* FINISHME: Should handle all expression types. */
804 return NULL;
805 }
806 """)
807
808 if sys.argv[1] == "enum":
809 lasts = [None, None, None, None]
810 for item in reversed(ir_expression_operation):
811 i = item.num_operands - 1
812 if lasts[i] is None:
813 lasts[i] = item
814
815 print(enum_template.render(values=ir_expression_operation,
816 lasts=lasts))
817 elif sys.argv[1] == "strings":
818 print(strings_template.render(values=ir_expression_operation))
819 elif sys.argv[1] == "constant":
820 print(constant_template.render(values=ir_expression_operation))