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