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