43ba46e4086b9ebfd00671de12235361c7773ead
[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 unreachable("invalid type");
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 unreachable("invalid type");
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 unreachable("invalid type");
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 unreachable("invalid type");
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 unreachable("invalid type");
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 unreachable("invalid type");
255 }
256 break;
257 }""")
258
259 # This template is for ir_quadop_vector.
260 constant_template_vector = mako.template.Template("""\
261 case ${op.get_enum_name()}:
262 for (unsigned c = 0; c < this->type->vector_elements; c++) {
263 switch (this->type->base_type) {
264 % for dst_type, src_types in op.signatures():
265 case ${src_types[0].glsl_type}:
266 data.${dst_type.union_field}[c] = op[c]->value.${src_types[0].union_field}[0];
267 break;
268 % endfor
269 default:
270 unreachable("invalid type");
271 }
272 }
273 break;""")
274
275 # This template is for ir_triop_lrp.
276 constant_template_lrp = mako.template.Template("""\
277 case ${op.get_enum_name()}: {
278 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT ||
279 op[0]->type->base_type == GLSL_TYPE_DOUBLE);
280 assert(op[1]->type->base_type == GLSL_TYPE_FLOAT ||
281 op[1]->type->base_type == GLSL_TYPE_DOUBLE);
282 assert(op[2]->type->base_type == GLSL_TYPE_FLOAT ||
283 op[2]->type->base_type == GLSL_TYPE_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_{}op_{}".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.{}[{}]".format(types[0].union_field, indices[0])
398 src1 = "op[1]->value.{}[{}]".format(types[1].union_field, indices[1]) if len(types) >= 2 else "ERROR"
399 src2 = "op[2]->value.{}[{}]".format(types[2].union_field, indices[2]) if len(types) >= 3 else "ERROR"
400 src3 = "op[3]->value.{}[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})", 'default': "-{src0}"}),
421 operation("abs", 1, source_types=signed_numeric_types, c_expression={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({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))"}),
423 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"}),
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 # int-to-boolean conversion
442 operation("i2b", 1, source_types=integer_types, dest_type=bool_type, c_expression="{src0} ? true : false"),
443 # Boolean-to-int conversion
444 operation("b2i", 1, source_types=(bool_type,), dest_type=int_type, c_expression="{src0} ? 1 : 0"),
445 # Unsigned-to-float conversion.
446 operation("u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="(float) {src0}"),
447 # Integer-to-unsigned conversion.
448 operation("i2u", 1, source_types=(int_type,), dest_type=uint_type, c_expression="{src0}"),
449 # Unsigned-to-integer conversion.
450 operation("u2i", 1, source_types=(uint_type,), dest_type=int_type, c_expression="{src0}"),
451 # Double-to-float conversion.
452 operation("d2f", 1, source_types=(double_type,), dest_type=float_type, c_expression="{src0}"),
453 # Float-to-double conversion.
454 operation("f2d", 1, source_types=(float_type,), dest_type=double_type, c_expression="{src0}"),
455 # Double-to-integer conversion.
456 operation("d2i", 1, source_types=(double_type,), dest_type=int_type, c_expression="{src0}"),
457 # Integer-to-double conversion.
458 operation("i2d", 1, source_types=(int_type,), dest_type=double_type, c_expression="{src0}"),
459 # Double-to-unsigned conversion.
460 operation("d2u", 1, source_types=(double_type,), dest_type=uint_type, c_expression="{src0}"),
461 # Unsigned-to-double conversion.
462 operation("u2d", 1, source_types=(uint_type,), dest_type=double_type, c_expression="{src0}"),
463 # Double-to-boolean conversion.
464 operation("d2b", 1, source_types=(double_type,), dest_type=bool_type, c_expression="{src0} != 0.0"),
465 # 'Bit-identical int-to-float "conversion"
466 operation("bitcast_i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
467 # 'Bit-identical float-to-int "conversion"
468 operation("bitcast_f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="bitcast_f2u({src0})"),
469 # 'Bit-identical uint-to-float "conversion"
470 operation("bitcast_u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
471 # 'Bit-identical float-to-uint "conversion"
472 operation("bitcast_f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="bitcast_f2u({src0})"),
473
474 # Unary floating-point rounding operations.
475 operation("trunc", 1, source_types=real_types, c_expression={'f': "truncf({src0})", 'd': "trunc({src0})"}),
476 operation("ceil", 1, source_types=real_types, c_expression={'f': "ceilf({src0})", 'd': "ceil({src0})"}),
477 operation("floor", 1, source_types=real_types, c_expression={'f': "floorf({src0})", 'd': "floor({src0})"}),
478 operation("fract", 1, source_types=real_types, c_expression={'f': "{src0} - floorf({src0})", 'd': "{src0} - floor({src0})"}),
479 operation("round_even", 1, source_types=real_types, c_expression={'f': "_mesa_roundevenf({src0})", 'd': "_mesa_roundeven({src0})"}),
480
481 # Trigonometric operations.
482 operation("sin", 1, source_types=(float_type,), c_expression="sinf({src0})"),
483 operation("cos", 1, source_types=(float_type,), c_expression="cosf({src0})"),
484
485 # Partial derivatives.
486 operation("dFdx", 1, source_types=(float_type,), c_expression="0.0f"),
487 operation("dFdx_coarse", 1, printable_name="dFdxCoarse", source_types=(float_type,), c_expression="0.0f"),
488 operation("dFdx_fine", 1, printable_name="dFdxFine", source_types=(float_type,), c_expression="0.0f"),
489 operation("dFdy", 1, source_types=(float_type,), c_expression="0.0f"),
490 operation("dFdy_coarse", 1, printable_name="dFdyCoarse", source_types=(float_type,), c_expression="0.0f"),
491 operation("dFdy_fine", 1, printable_name="dFdyFine", source_types=(float_type,), c_expression="0.0f"),
492
493 # Floating point pack and unpack operations.
494 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),
495 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),
496 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),
497 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),
498 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),
499 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))),
500 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))),
501 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))),
502 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))),
503 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))),
504
505 # Bit operations, part of ARB_gpu_shader5.
506 operation("bitfield_reverse", 1, source_types=integer_types, c_expression="bitfield_reverse({src0})"),
507 operation("bit_count", 1, source_types=integer_types, dest_type=int_type, c_expression="_mesa_bitcount({src0})"),
508 operation("find_msb", 1, source_types=integer_types, dest_type=int_type, c_expression={'u': "find_msb_uint({src0})", 'i': "find_msb_int({src0})"}),
509 operation("find_lsb", 1, source_types=integer_types, dest_type=int_type, c_expression="find_msb_uint({src0} & -{src0})"),
510
511 operation("saturate", 1, printable_name="sat", source_types=(float_type,), c_expression="CLAMP({src0}, 0.0f, 1.0f)"),
512
513 # Double packing, part of ARB_gpu_shader_fp64.
514 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))),
515 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))),
516
517 operation("frexp_sig", 1),
518 operation("frexp_exp", 1),
519
520 operation("noise", 1),
521
522 operation("subroutine_to_int", 1),
523
524 # Interpolate fs input at centroid
525 #
526 # operand0 is the fs input.
527 operation("interpolate_at_centroid", 1),
528
529 # Ask the driver for the total size of a buffer block.
530 # operand0 is the ir_constant buffer block index in the linked shader.
531 operation("get_buffer_size", 1),
532
533 # Calculate length of an unsized array inside a buffer block.
534 # This opcode is going to be replaced in a lowering pass inside
535 # the linker.
536 #
537 # operand0 is the unsized array's ir_value for the calculation
538 # of its length.
539 operation("ssbo_unsized_array_length", 1),
540
541 # Vote among threads on the value of the boolean argument.
542 operation("vote_any", 1),
543 operation("vote_all", 1),
544 operation("vote_eq", 1),
545
546 operation("add", 2, printable_name="+", source_types=numeric_types, c_expression="{src0} + {src1}", flags=vector_scalar_operation),
547 operation("sub", 2, printable_name="-", source_types=numeric_types, c_expression="{src0} - {src1}", flags=vector_scalar_operation),
548 # "Floating-point or low 32-bit integer multiply."
549 operation("mul", 2, printable_name="*", source_types=numeric_types, c_expression="{src0} * {src1}"),
550 operation("imul_high", 2), # Calculates the high 32-bits of a 64-bit multiply.
551 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),
552
553 # Returns the carry resulting from the addition of the two arguments.
554 operation("carry", 2),
555
556 # Returns the borrow resulting from the subtraction of the second argument
557 # from the first argument.
558 operation("borrow", 2),
559
560 # Either (vector % vector) or (vector % scalar)
561 #
562 # We don't use fmod because it rounds toward zero; GLSL specifies the use
563 # of floor.
564 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),
565
566 # Binary comparison operators which return a boolean vector.
567 # The type of both operands must be equal.
568 operation("less", 2, printable_name="<", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} < {src1}"),
569 operation("greater", 2, printable_name=">", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} > {src1}"),
570 operation("lequal", 2, printable_name="<=", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} <= {src1}"),
571 operation("gequal", 2, printable_name=">=", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} >= {src1}"),
572 operation("equal", 2, printable_name="==", source_types=all_types, dest_type=bool_type, c_expression="{src0} == {src1}"),
573 operation("nequal", 2, printable_name="!=", source_types=all_types, dest_type=bool_type, c_expression="{src0} != {src1}"),
574
575 # Returns single boolean for whether all components of operands[0]
576 # equal the components of operands[1].
577 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))),
578
579 # Returns single boolean for whether any component of operands[0]
580 # is not equal to the corresponding component of operands[1].
581 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))),
582
583 # Bit-wise binary operations.
584 operation("lshift", 2, printable_name="<<", source_types=integer_types, c_expression="{src0} << {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
585 operation("rshift", 2, printable_name=">>", source_types=integer_types, c_expression="{src0} >> {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
586 operation("bit_and", 2, printable_name="&", source_types=integer_types, c_expression="{src0} & {src1}", flags=vector_scalar_operation),
587 operation("bit_xor", 2, printable_name="^", source_types=integer_types, c_expression="{src0} ^ {src1}", flags=vector_scalar_operation),
588 operation("bit_or", 2, printable_name="|", source_types=integer_types, c_expression="{src0} | {src1}", flags=vector_scalar_operation),
589
590 operation("logic_and", 2, printable_name="&&", source_types=(bool_type,), c_expression="{src0} && {src1}"),
591 operation("logic_xor", 2, printable_name="^^", source_types=(bool_type,), c_expression="{src0} != {src1}"),
592 operation("logic_or", 2, printable_name="||", source_types=(bool_type,), c_expression="{src0} || {src1}"),
593
594 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),
595 operation("min", 2, source_types=numeric_types, c_expression="MIN2({src0}, {src1})", flags=vector_scalar_operation),
596 operation("max", 2, source_types=numeric_types, c_expression="MAX2({src0}, {src1})", flags=vector_scalar_operation),
597
598 operation("pow", 2, source_types=(float_type,), c_expression="powf({src0}, {src1})"),
599
600 # Load a value the size of a given GLSL type from a uniform block.
601 #
602 # operand0 is the ir_constant uniform block index in the linked shader.
603 # operand1 is a byte offset within the uniform block.
604 operation("ubo_load", 2),
605
606 # Multiplies a number by two to a power, part of ARB_gpu_shader5.
607 operation("ldexp", 2,
608 all_signatures=((float_type, (float_type, int_type)),
609 (double_type, (double_type, int_type))),
610 c_expression={'f': "ldexpf_flush_subnormal({src0}, {src1})",
611 'd': "ldexp_flush_subnormal({src0}, {src1})"}),
612
613 # Extract a scalar from a vector
614 #
615 # operand0 is the vector
616 # operand1 is the index of the field to read from operand0
617 operation("vector_extract", 2, source_types=all_types, c_expression="anything-except-None"),
618
619 # Interpolate fs input at offset
620 #
621 # operand0 is the fs input
622 # operand1 is the offset from the pixel center
623 operation("interpolate_at_offset", 2),
624
625 # Interpolate fs input at sample position
626 #
627 # operand0 is the fs input
628 # operand1 is the sample ID
629 operation("interpolate_at_sample", 2),
630
631 # Fused floating-point multiply-add, part of ARB_gpu_shader5.
632 operation("fma", 3, source_types=real_types, c_expression="{src0} * {src1} + {src2}"),
633
634 operation("lrp", 3, source_types=real_types, c_expression={'f': "{src0} * (1.0f - {src2}) + ({src1} * {src2})", 'd': "{src0} * (1.0 - {src2}) + ({src1} * {src2})"}),
635
636 # Conditional Select
637 #
638 # A vector conditional select instruction (like ?:, but operating per-
639 # component on vectors).
640 #
641 # See also lower_instructions_visitor::ldexp_to_arith
642 operation("csel", 3,
643 all_signatures=zip(all_types, zip(len(all_types) * (bool_type,), all_types, all_types)),
644 c_expression="{src0} ? {src1} : {src2}"),
645
646 operation("bitfield_extract", 3,
647 all_signatures=((int_type, (uint_type, int_type, int_type)),
648 (int_type, (int_type, int_type, int_type))),
649 c_expression={'u': "bitfield_extract_uint({src0}, {src1}, {src2})",
650 'i': "bitfield_extract_int({src0}, {src1}, {src2})"}),
651
652 # Generate a value with one field of a vector changed
653 #
654 # operand0 is the vector
655 # operand1 is the value to write into the vector result
656 # operand2 is the index in operand0 to be modified
657 operation("vector_insert", 3, source_types=all_types, c_expression="anything-except-None"),
658
659 operation("bitfield_insert", 4,
660 all_signatures=((uint_type, (uint_type, uint_type, int_type, int_type)),
661 (int_type, (int_type, int_type, int_type, int_type))),
662 c_expression="bitfield_insert({src0}, {src1}, {src2}, {src3})"),
663
664 operation("vector", 4, source_types=all_types, c_expression="anything-except-None"),
665 ]
666
667
668 if __name__ == "__main__":
669 copyright = """/*
670 * Copyright (C) 2010 Intel Corporation
671 *
672 * Permission is hereby granted, free of charge, to any person obtaining a
673 * copy of this software and associated documentation files (the "Software"),
674 * to deal in the Software without restriction, including without limitation
675 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
676 * and/or sell copies of the Software, and to permit persons to whom the
677 * Software is furnished to do so, subject to the following conditions:
678 *
679 * The above copyright notice and this permission notice (including the next
680 * paragraph) shall be included in all copies or substantial portions of the
681 * Software.
682 *
683 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
684 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
685 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
686 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
687 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
688 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
689 * DEALINGS IN THE SOFTWARE.
690 */
691 """
692 enum_template = mako.template.Template(copyright + """
693 enum ir_expression_operation {
694 % for item in values:
695 ${item.get_enum_name()},
696 % endfor
697
698 /* Sentinels marking the last of each kind of operation. */
699 % for item in lasts:
700 ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()},
701 % endfor
702 ir_last_opcode = ir_quadop_${lasts[3].name}
703 };""")
704
705 strings_template = mako.template.Template(copyright + """
706 const char *const ir_expression_operation_strings[] = {
707 % for item in values:
708 "${item.printable_name}",
709 % endfor
710 };""")
711
712 constant_template = mako.template.Template("""\
713 switch (this->operation) {
714 % for op in values:
715 % if op.c_expression is not None:
716 ${op.get_template()}
717
718 % endif
719 % endfor
720 default:
721 /* FINISHME: Should handle all expression types. */
722 return NULL;
723 }
724 """)
725
726 if sys.argv[1] == "enum":
727 lasts = [None, None, None, None]
728 for item in reversed(ir_expression_operation):
729 i = item.num_operands - 1
730 if lasts[i] is None:
731 lasts[i] = item
732
733 print(enum_template.render(values=ir_expression_operation,
734 lasts=lasts))
735 elif sys.argv[1] == "strings":
736 print(strings_template.render(values=ir_expression_operation))
737 elif sys.argv[1] == "constant":
738 print(constant_template.render(values=ir_expression_operation))