3 # Copyright (C) 2015 Intel Corporation
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:
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
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
28 def __init__(self
, c_type
, union_field
, glsl_type
):
30 self
.union_field
= union_field
31 self
.glsl_type
= glsl_type
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.
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.
47 self
.source_types
= source_types
48 self
.num_operands
= num_operands
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
58 self
.dest_type
= dest_type
59 self
.source_types
= source_types
60 self
.num_operands
= num_operands
67 if self
.i
< len(self
.source_types
):
71 if self
.dest_type
is None:
72 dest_type
= self
.source_types
[i
]
74 dest_type
= self
.dest_type
76 return (dest_type
, self
.num_operands
* (self
.source_types
[i
],))
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")
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
)
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)};
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)};
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
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)};
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)};
145 # This template is for operations with an output type that doesn't match the
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)};
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} ||
172 op[${i}]->type->base_type == ${op.source_types[-1].glsl_type});
175 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
177 for (unsigned c = 0, c0 = 0, c1 = 0;
179 c0 += c0_inc, c1 += c1_inc, c++) {
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"))};
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;
202 c0 += c0_inc, c1 += c1_inc, c++) {
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"))};
215 assert(op[0]->type->is_matrix() || op[1]->type->is_matrix());
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.
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.
223 * For mat*vec, the vector is treated as a column vector. Since
224 * matrix_columns is 1 for vectors, this just works.
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];
236 data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
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']};
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']};
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)};
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"
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):
283 self
.num_operands
= num_operands
285 if printable_name
is None:
286 self
.printable_name
= name
288 self
.printable_name
= printable_name
290 self
.all_signatures
= all_signatures
292 if source_types
is None:
293 self
.source_types
= tuple()
295 self
.source_types
= source_types
297 self
.dest_type
= dest_type
299 if c_expression
is None:
300 self
.c_expression
= None
301 elif isinstance(c_expression
, str):
302 self
.c_expression
= {'default': c_expression
}
304 self
.c_expression
= c_expression
307 self
.flags
= frozenset()
308 elif isinstance(flags
, str):
309 self
.flags
= frozenset([flags
])
311 self
.flags
= frozenset(flags
)
314 def get_enum_name(self
):
315 return "ir_{}op_{}".format(("un", "bin", "tri", "quad")[self
.num_operands
-1], self
.name
)
318 def get_template(self
):
319 if self
.c_expression
is None:
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
)
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
)
351 return constant_template3
.render(op
=self
)
352 elif self
.num_operands
== 3:
353 return constant_template3
.render(op
=self
)
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"
363 expr
= self
.c_expression
[types
[0].union_field
] if types
[0].union_field
in self
.c_expression
else self
.c_expression
['default']
365 return expr
.format(src0
=src0
,
370 def signatures(self
):
371 if self
.all_signatures
is not None:
372 return self
.all_signatures
374 return type_signature_iter(self
.dest_type
, self
.source_types
, self
.num_operands
)
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})"),
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})"),
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})"}),
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})"),
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"),
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
))),
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})"),
471 operation("saturate", 1, printable_name
="sat", source_types
=(float_type
,), c_expression
="CLAMP({src0}, 0.0f, 1.0f)"),
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
))),
477 operation("frexp_sig", 1),
478 operation("frexp_exp", 1),
480 operation("noise", 1),
482 operation("subroutine_to_int", 1),
484 # Interpolate fs input at centroid
486 # operand0 is the fs input.
487 operation("interpolate_at_centroid", 1),
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),
493 # Calculate length of an unsized array inside a buffer block.
494 # This opcode is going to be replaced in a lowering pass inside
497 # operand0 is the unsized array's ir_value for the calculation
499 operation("ssbo_unsized_array_length", 1),
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),
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
),
513 # Returns the carry resulting from the addition of the two arguments.
514 operation("carry", 2),
516 # Returns the borrow resulting from the subtraction of the second argument
517 # from the first argument.
518 operation("borrow", 2),
520 # Either (vector % vector) or (vector % scalar)
522 # We don't use fmod because it rounds toward zero; GLSL specifies the use
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
),
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}"),
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
))),
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
))),
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
),
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}"),
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
),
558 operation("pow", 2, source_types
=(float_type
,), c_expression
="powf({src0}, {src1})"),
560 # Load a value the size of a given GLSL type from a uniform block.
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),
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})"}),
573 # Extract a scalar from a vector
575 # operand0 is the vector
576 # operand1 is the index of the field to read from operand0
577 operation("vector_extract", 2),
579 # Interpolate fs input at offset
581 # operand0 is the fs input
582 # operand1 is the offset from the pixel center
583 operation("interpolate_at_offset", 2),
585 # Interpolate fs input at sample position
587 # operand0 is the fs input
588 # operand1 is the sample ID
589 operation("interpolate_at_sample", 2),
591 # Fused floating-point multiply-add, part of ARB_gpu_shader5.
592 operation("fma", 3, source_types
=real_types
, c_expression
="{src0} * {src1} + {src2}"),
598 # A vector conditional select instruction (like ?:, but operating per-
599 # component on vectors).
601 # See also lower_instructions_visitor::ldexp_to_arith
602 operation("csel", 3),
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})"}),
610 # Generate a value with one field of a vector changed
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),
617 operation("bitfield_insert", 4),
619 operation("vector", 4),
623 if __name__
== "__main__":
625 * Copyright (C) 2010 Intel Corporation
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:
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
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.
647 enum_template
= mako
.template
.Template(copyright
+ """
648 enum ir_expression_operation {
649 % for item in values:
650 ${item.get_enum_name()},
653 /* Sentinels marking the last of each kind of operation. */
655 ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()},
657 ir_last_opcode = ir_quadop_${lasts[3].name}
660 strings_template
= mako
.template
.Template(copyright
+ """
661 const char *const ir_expression_operation_strings[] = {
662 % for item in values:
663 "${item.printable_name}",
667 constant_template
= mako
.template
.Template("""\
668 switch (this->operation) {
670 % if op.c_expression is not None:
676 /* FINISHME: Should handle all expression types. */
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
688 print(enum_template
.render(values
=ir_expression_operation
,
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
))