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