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 or the implementation for all types is identical.
95 # ir_unop_logic_not is an example of the former, and ir_quadop_bitfield_insert
96 # is an example of the latter..
97 constant_template0
= mako
.template
.Template("""\
98 case ${op.get_enum_name()}:
99 % if len(op.source_types) == 1:
100 assert(op[0]->type->base_type == ${op.source_types[0].glsl_type});
102 for (unsigned c = 0; c < op[0]->type->components(); c++)
103 % for dst_type, src_types in op.signatures():
104 % if loop.index == 0:
105 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
110 # This template is for unary operations that can have operands of a several
111 # different types. ir_unop_bit_not is an example.
112 constant_template1
= mako
.template
.Template("""\
113 case ${op.get_enum_name()}:
114 switch (op[0]->type->base_type) {
115 % for dst_type, src_types in op.signatures():
116 case ${src_types[0].glsl_type}:
117 for (unsigned c = 0; c < op[0]->type->components(); c++)
118 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
126 # This template is for unary operations that can have operands of a several
127 # different types, and each type has a different C expression. ir_unop_neg is
129 constant_template3
= mako
.template
.Template("""\
130 case ${op.get_enum_name()}:
131 for (unsigned c = 0; c < op[0]->type->components(); c++) {
132 switch (this->type->base_type) {
133 % for dst_type, src_types in op.signatures():
134 case ${src_types[0].glsl_type}:
135 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
144 # This template is for unary operations that map an operand of one type to an
145 # operand of another type. ir_unop_f2b is an example.
146 constant_template2
= mako
.template
.Template("""\
147 case ${op.get_enum_name()}:
148 assert(op[0]->type->base_type == ${op.source_types[0].glsl_type});
149 for (unsigned c = 0; c < op[0]->type->components(); c++)
150 data.${op.dest_type.union_field}[c] = ${op.get_c_expression(op.source_types)};
153 # This template is for operations with an output type that doesn't match the
155 constant_template5
= mako
.template
.Template("""\
156 case ${op.get_enum_name()}:
157 for (unsigned c = 0; c < components; c++) {
158 switch (op[0]->type->base_type) {
159 % for dst_type, src_types in op.signatures():
160 case ${src_types[0].glsl_type}:
161 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
170 # This template is for binary operations that can operate on some combination
171 # of scalar and vector operands.
172 constant_template_vector_scalar
= mako
.template
.Template("""\
173 case ${op.get_enum_name()}:
174 % if "mixed" in op.flags:
175 % for i in xrange(op.num_operands):
176 assert(op[${i}]->type->base_type == ${op.source_types[0].glsl_type} ||
177 % for src_type in op.source_types[1:-1]:
178 op[${i}]->type->base_type == ${src_type.glsl_type} ||
180 op[${i}]->type->base_type == ${op.source_types[-1].glsl_type});
183 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
185 for (unsigned c = 0, c0 = 0, c1 = 0;
187 c0 += c0_inc, c1 += c1_inc, c++) {
189 switch (op[0]->type->base_type) {
190 % for dst_type, src_types in op.signatures():
191 case ${src_types[0].glsl_type}:
192 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
201 # This template is for multiplication. It is unique because it has to support
202 # matrix * vector and matrix * matrix operations, and those are just different.
203 constant_template_mul
= mako
.template
.Template("""\
204 case ${op.get_enum_name()}:
205 /* Check for equal types, or unequal types involving scalars */
206 if ((op[0]->type == op[1]->type && !op[0]->type->is_matrix())
207 || op0_scalar || op1_scalar) {
208 for (unsigned c = 0, c0 = 0, c1 = 0;
210 c0 += c0_inc, c1 += c1_inc, c++) {
212 switch (op[0]->type->base_type) {
213 % for dst_type, src_types in op.signatures():
214 case ${src_types[0].glsl_type}:
215 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
223 assert(op[0]->type->is_matrix() || op[1]->type->is_matrix());
225 /* Multiply an N-by-M matrix with an M-by-P matrix. Since either
226 * matrix can be a GLSL vector, either N or P can be 1.
228 * For vec*mat, the vector is treated as a row vector. This
229 * means the vector is a 1-row x M-column matrix.
231 * For mat*vec, the vector is treated as a column vector. Since
232 * matrix_columns is 1 for vectors, this just works.
234 const unsigned n = op[0]->type->is_vector()
235 ? 1 : op[0]->type->vector_elements;
236 const unsigned m = op[1]->type->vector_elements;
237 const unsigned p = op[1]->type->matrix_columns;
238 for (unsigned j = 0; j < p; j++) {
239 for (unsigned i = 0; i < n; i++) {
240 for (unsigned k = 0; k < m; k++) {
241 if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
242 data.d[i+n*j] += op[0]->value.d[i+n*k]*op[1]->value.d[k+m*j];
244 data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
251 # This template is for operations that are horizontal and either have only a
252 # single type or the implementation for all types is identical. That is, the
253 # operation consumes a vector and produces a scalar.
254 constant_template_horizontal_single_implementation
= mako
.template
.Template("""\
255 case ${op.get_enum_name()}:
256 data.${op.dest_type.union_field}[0] = ${op.c_expression['default']};
259 # This template is for operations that are horizontal and do not assign the
260 # result. The various unpack operations are examples.
261 constant_template_horizontal_nonassignment
= mako
.template
.Template("""\
262 case ${op.get_enum_name()}:
263 ${op.c_expression['default']};
266 # This template is for binary operations that are horizontal. That is, the
267 # operation consumes a vector and produces a scalar.
268 constant_template_horizontal
= mako
.template
.Template("""\
269 case ${op.get_enum_name()}:
270 switch (op[0]->type->base_type) {
271 % for dst_type, src_types in op.signatures():
272 case ${src_types[0].glsl_type}:
273 data.${dst_type.union_field}[0] = ${op.get_c_expression(src_types)};
281 # This template is for ir_binop_vector_extract.
282 constant_template_vector_extract
= mako
.template
.Template("""\
283 case ${op.get_enum_name()}: {
284 const int c = CLAMP(op[1]->value.i[0], 0,
285 (int) op[0]->type->vector_elements - 1);
287 switch (op[0]->type->base_type) {
288 % for dst_type, src_types in op.signatures():
289 case ${src_types[0].glsl_type}:
290 data.${dst_type.union_field}[0] = op[0]->value.${src_types[0].union_field}[c];
299 # This template is for ir_triop_vector_insert.
300 constant_template_vector_insert
= mako
.template
.Template("""\
301 case ${op.get_enum_name()}: {
302 const unsigned idx = op[2]->value.u[0];
304 memcpy(&data, &op[0]->value, sizeof(data));
306 switch (this->type->base_type) {
307 % for dst_type, src_types in op.signatures():
308 case ${src_types[0].glsl_type}:
309 data.${dst_type.union_field}[idx] = op[1]->value.${src_types[0].union_field}[0];
313 assert(!"Should not get here.");
319 # This template is for ir_quadop_vector.
320 constant_template_vector
= mako
.template
.Template("""\
321 case ${op.get_enum_name()}:
322 for (unsigned c = 0; c < this->type->vector_elements; c++) {
323 switch (this->type->base_type) {
324 % for dst_type, src_types in op.signatures():
325 case ${src_types[0].glsl_type}:
326 data.${dst_type.union_field}[c] = op[c]->value.${src_types[0].union_field}[0];
335 # This template is for ir_triop_lrp.
336 constant_template_lrp
= mako
.template
.Template("""\
337 case ${op.get_enum_name()}: {
338 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT ||
339 op[0]->type->base_type == GLSL_TYPE_DOUBLE);
340 assert(op[1]->type->base_type == GLSL_TYPE_FLOAT ||
341 op[1]->type->base_type == GLSL_TYPE_DOUBLE);
342 assert(op[2]->type->base_type == GLSL_TYPE_FLOAT ||
343 op[2]->type->base_type == GLSL_TYPE_DOUBLE);
345 unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
346 for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
347 switch (this->type->base_type) {
348 % for dst_type, src_types in op.signatures():
349 case ${src_types[0].glsl_type}:
350 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c", "c", "c2"))};
361 vector_scalar_operation
= "vector-scalar"
362 horizontal_operation
= "horizontal"
363 types_identical_operation
= "identical"
364 non_assign_operation
= "nonassign"
365 mixed_type_operation
= "mixed"
367 class operation(object):
368 def __init__(self
, name
, num_operands
, printable_name
= None, source_types
= None, dest_type
= None, c_expression
= None, flags
= None, all_signatures
= None):
370 self
.num_operands
= num_operands
372 if printable_name
is None:
373 self
.printable_name
= name
375 self
.printable_name
= printable_name
377 self
.all_signatures
= all_signatures
379 if source_types
is None:
380 self
.source_types
= tuple()
382 self
.source_types
= source_types
384 self
.dest_type
= dest_type
386 if c_expression
is None:
387 self
.c_expression
= None
388 elif isinstance(c_expression
, str):
389 self
.c_expression
= {'default': c_expression
}
391 self
.c_expression
= c_expression
394 self
.flags
= frozenset()
395 elif isinstance(flags
, str):
396 self
.flags
= frozenset([flags
])
398 self
.flags
= frozenset(flags
)
401 def get_enum_name(self
):
402 return "ir_{}op_{}".format(("un", "bin", "tri", "quad")[self
.num_operands
-1], self
.name
)
405 def get_template(self
):
406 if self
.c_expression
is None:
409 if self
.num_operands
== 1:
410 if horizontal_operation
in self
.flags
and non_assign_operation
in self
.flags
:
411 return constant_template_horizontal_nonassignment
.render(op
=self
)
412 elif horizontal_operation
in self
.flags
:
413 return constant_template_horizontal_single_implementation
.render(op
=self
)
414 elif self
.dest_type
is not None and len(self
.source_types
) == 1:
415 return constant_template2
.render(op
=self
)
416 elif self
.dest_type
is not None:
417 return constant_template5
.render(op
=self
)
418 elif len(self
.source_types
) == 1:
419 return constant_template0
.render(op
=self
)
420 elif len(self
.c_expression
) == 1 and 'default' in self
.c_expression
:
421 return constant_template1
.render(op
=self
)
423 return constant_template3
.render(op
=self
)
424 elif self
.num_operands
== 2:
425 if self
.name
== "mul":
426 return constant_template_mul
.render(op
=self
)
427 elif self
.name
== "vector_extract":
428 return constant_template_vector_extract
.render(op
=self
)
429 elif vector_scalar_operation
in self
.flags
:
430 return constant_template_vector_scalar
.render(op
=self
)
431 elif horizontal_operation
in self
.flags
and types_identical_operation
in self
.flags
:
432 return constant_template_horizontal_single_implementation
.render(op
=self
)
433 elif horizontal_operation
in self
.flags
:
434 return constant_template_horizontal
.render(op
=self
)
435 elif len(self
.source_types
) == 1:
436 return constant_template0
.render(op
=self
)
437 elif self
.dest_type
is not None:
438 return constant_template5
.render(op
=self
)
440 return constant_template3
.render(op
=self
)
441 elif self
.num_operands
== 3:
442 if self
.name
== "vector_insert":
443 return constant_template_vector_insert
.render(op
=self
)
444 elif self
.name
== "lrp":
445 return constant_template_lrp
.render(op
=self
)
447 return constant_template3
.render(op
=self
)
448 elif self
.num_operands
== 4:
449 if self
.name
== "vector":
450 return constant_template_vector
.render(op
=self
)
451 elif types_identical_operation
in self
.flags
:
452 return constant_template0
.render(op
=self
)
457 def get_c_expression(self
, types
, indices
=("c", "c", "c")):
458 src0
= "op[0]->value.{}[{}]".format(types
[0].union_field
, indices
[0])
459 src1
= "op[1]->value.{}[{}]".format(types
[1].union_field
, indices
[1]) if len(types
) >= 2 else "ERROR"
460 src2
= "op[2]->value.{}[{}]".format(types
[2].union_field
, indices
[2]) if len(types
) >= 3 else "ERROR"
461 src3
= "op[3]->value.{}[c]".format(types
[3].union_field
) if len(types
) >= 4 else "ERROR"
463 expr
= self
.c_expression
[types
[0].union_field
] if types
[0].union_field
in self
.c_expression
else self
.c_expression
['default']
465 return expr
.format(src0
=src0
,
471 def signatures(self
):
472 if self
.all_signatures
is not None:
473 return self
.all_signatures
475 return type_signature_iter(self
.dest_type
, self
.source_types
, self
.num_operands
)
478 ir_expression_operation
= [
479 operation("bit_not", 1, printable_name
="~", source_types
=integer_types
, c_expression
="~ {src0}"),
480 operation("logic_not", 1, printable_name
="!", source_types
=(bool_type
,), c_expression
="!{src0}"),
481 operation("neg", 1, source_types
=numeric_types
, c_expression
={'u': "-((int) {src0})", 'default': "-{src0}"}),
482 operation("abs", 1, source_types
=signed_numeric_types
, c_expression
={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({src0})"}),
483 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))"}),
484 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"}),
485 operation("rsq", 1, source_types
=real_types
, c_expression
={'f': "1.0F / sqrtf({src0})", 'd': "1.0 / sqrt({src0})"}),
486 operation("sqrt", 1, source_types
=real_types
, c_expression
={'f': "sqrtf({src0})", 'd': "sqrt({src0})"}),
487 operation("exp", 1, source_types
=(float_type
,), c_expression
="expf({src0})"), # Log base e on gentype
488 operation("log", 1, source_types
=(float_type
,), c_expression
="logf({src0})"), # Natural log on gentype
489 operation("exp2", 1, source_types
=(float_type
,), c_expression
="exp2f({src0})"),
490 operation("log2", 1, source_types
=(float_type
,), c_expression
="log2f({src0})"),
492 # Float-to-integer conversion.
493 operation("f2i", 1, source_types
=(float_type
,), dest_type
=int_type
, c_expression
="(int) {src0}"),
494 # Float-to-unsigned conversion.
495 operation("f2u", 1, source_types
=(float_type
,), dest_type
=uint_type
, c_expression
="(unsigned) {src0}"),
496 # Integer-to-float conversion.
497 operation("i2f", 1, source_types
=(int_type
,), dest_type
=float_type
, c_expression
="(float) {src0}"),
498 # Float-to-boolean conversion
499 operation("f2b", 1, source_types
=(float_type
,), dest_type
=bool_type
, c_expression
="{src0} != 0.0F ? true : false"),
500 # Boolean-to-float conversion
501 operation("b2f", 1, source_types
=(bool_type
,), dest_type
=float_type
, c_expression
="{src0} ? 1.0F : 0.0F"),
502 # int-to-boolean conversion
503 operation("i2b", 1, source_types
=integer_types
, dest_type
=bool_type
, c_expression
="{src0} ? true : false"),
504 # Boolean-to-int conversion
505 operation("b2i", 1, source_types
=(bool_type
,), dest_type
=int_type
, c_expression
="{src0} ? 1 : 0"),
506 # Unsigned-to-float conversion.
507 operation("u2f", 1, source_types
=(uint_type
,), dest_type
=float_type
, c_expression
="(float) {src0}"),
508 # Integer-to-unsigned conversion.
509 operation("i2u", 1, source_types
=(int_type
,), dest_type
=uint_type
, c_expression
="{src0}"),
510 # Unsigned-to-integer conversion.
511 operation("u2i", 1, source_types
=(uint_type
,), dest_type
=int_type
, c_expression
="{src0}"),
512 # Double-to-float conversion.
513 operation("d2f", 1, source_types
=(double_type
,), dest_type
=float_type
, c_expression
="{src0}"),
514 # Float-to-double conversion.
515 operation("f2d", 1, source_types
=(float_type
,), dest_type
=double_type
, c_expression
="{src0}"),
516 # Double-to-integer conversion.
517 operation("d2i", 1, source_types
=(double_type
,), dest_type
=int_type
, c_expression
="{src0}"),
518 # Integer-to-double conversion.
519 operation("i2d", 1, source_types
=(int_type
,), dest_type
=double_type
, c_expression
="{src0}"),
520 # Double-to-unsigned conversion.
521 operation("d2u", 1, source_types
=(double_type
,), dest_type
=uint_type
, c_expression
="{src0}"),
522 # Unsigned-to-double conversion.
523 operation("u2d", 1, source_types
=(uint_type
,), dest_type
=double_type
, c_expression
="{src0}"),
524 # Double-to-boolean conversion.
525 operation("d2b", 1, source_types
=(double_type
,), dest_type
=bool_type
, c_expression
="{src0} != 0.0"),
526 # 'Bit-identical int-to-float "conversion"
527 operation("bitcast_i2f", 1, source_types
=(int_type
,), dest_type
=float_type
, c_expression
="bitcast_u2f({src0})"),
528 # 'Bit-identical float-to-int "conversion"
529 operation("bitcast_f2i", 1, source_types
=(float_type
,), dest_type
=int_type
, c_expression
="bitcast_f2u({src0})"),
530 # 'Bit-identical uint-to-float "conversion"
531 operation("bitcast_u2f", 1, source_types
=(uint_type
,), dest_type
=float_type
, c_expression
="bitcast_u2f({src0})"),
532 # 'Bit-identical float-to-uint "conversion"
533 operation("bitcast_f2u", 1, source_types
=(float_type
,), dest_type
=uint_type
, c_expression
="bitcast_f2u({src0})"),
535 # Unary floating-point rounding operations.
536 operation("trunc", 1, source_types
=real_types
, c_expression
={'f': "truncf({src0})", 'd': "trunc({src0})"}),
537 operation("ceil", 1, source_types
=real_types
, c_expression
={'f': "ceilf({src0})", 'd': "ceil({src0})"}),
538 operation("floor", 1, source_types
=real_types
, c_expression
={'f': "floorf({src0})", 'd': "floor({src0})"}),
539 operation("fract", 1, source_types
=real_types
, c_expression
={'f': "{src0} - floorf({src0})", 'd': "{src0} - floor({src0})"}),
540 operation("round_even", 1, source_types
=real_types
, c_expression
={'f': "_mesa_roundevenf({src0})", 'd': "_mesa_roundeven({src0})"}),
542 # Trigonometric operations.
543 operation("sin", 1, source_types
=(float_type
,), c_expression
="sinf({src0})"),
544 operation("cos", 1, source_types
=(float_type
,), c_expression
="cosf({src0})"),
546 # Partial derivatives.
547 operation("dFdx", 1, source_types
=(float_type
,), c_expression
="0.0f"),
548 operation("dFdx_coarse", 1, printable_name
="dFdxCoarse", source_types
=(float_type
,), c_expression
="0.0f"),
549 operation("dFdx_fine", 1, printable_name
="dFdxFine", source_types
=(float_type
,), c_expression
="0.0f"),
550 operation("dFdy", 1, source_types
=(float_type
,), c_expression
="0.0f"),
551 operation("dFdy_coarse", 1, printable_name
="dFdyCoarse", source_types
=(float_type
,), c_expression
="0.0f"),
552 operation("dFdy_fine", 1, printable_name
="dFdyFine", source_types
=(float_type
,), c_expression
="0.0f"),
554 # Floating point pack and unpack operations.
555 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
),
556 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
),
557 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
),
558 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
),
559 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
),
560 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
))),
561 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
))),
562 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
))),
563 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
))),
564 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
))),
566 # Bit operations, part of ARB_gpu_shader5.
567 operation("bitfield_reverse", 1, source_types
=integer_types
, c_expression
="bitfield_reverse({src0})"),
568 operation("bit_count", 1, source_types
=integer_types
, dest_type
=int_type
, c_expression
="_mesa_bitcount({src0})"),
569 operation("find_msb", 1, source_types
=integer_types
, dest_type
=int_type
, c_expression
={'u': "find_msb_uint({src0})", 'i': "find_msb_int({src0})"}),
570 operation("find_lsb", 1, source_types
=integer_types
, dest_type
=int_type
, c_expression
="find_msb_uint({src0} & -{src0})"),
572 operation("saturate", 1, printable_name
="sat", source_types
=(float_type
,), c_expression
="CLAMP({src0}, 0.0f, 1.0f)"),
574 # Double packing, part of ARB_gpu_shader_fp64.
575 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
))),
576 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
))),
578 operation("frexp_sig", 1),
579 operation("frexp_exp", 1),
581 operation("noise", 1),
583 operation("subroutine_to_int", 1),
585 # Interpolate fs input at centroid
587 # operand0 is the fs input.
588 operation("interpolate_at_centroid", 1),
590 # Ask the driver for the total size of a buffer block.
591 # operand0 is the ir_constant buffer block index in the linked shader.
592 operation("get_buffer_size", 1),
594 # Calculate length of an unsized array inside a buffer block.
595 # This opcode is going to be replaced in a lowering pass inside
598 # operand0 is the unsized array's ir_value for the calculation
600 operation("ssbo_unsized_array_length", 1),
602 # Vote among threads on the value of the boolean argument.
603 operation("vote_any", 1),
604 operation("vote_all", 1),
605 operation("vote_eq", 1),
607 operation("add", 2, printable_name
="+", source_types
=numeric_types
, c_expression
="{src0} + {src1}", flags
=vector_scalar_operation
),
608 operation("sub", 2, printable_name
="-", source_types
=numeric_types
, c_expression
="{src0} - {src1}", flags
=vector_scalar_operation
),
609 # "Floating-point or low 32-bit integer multiply."
610 operation("mul", 2, printable_name
="*", source_types
=numeric_types
, c_expression
="{src0} * {src1}"),
611 operation("imul_high", 2), # Calculates the high 32-bits of a 64-bit multiply.
612 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
),
614 # Returns the carry resulting from the addition of the two arguments.
615 operation("carry", 2),
617 # Returns the borrow resulting from the subtraction of the second argument
618 # from the first argument.
619 operation("borrow", 2),
621 # Either (vector % vector) or (vector % scalar)
623 # We don't use fmod because it rounds toward zero; GLSL specifies the use
625 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
),
627 # Binary comparison operators which return a boolean vector.
628 # The type of both operands must be equal.
629 operation("less", 2, printable_name
="<", source_types
=numeric_types
, dest_type
=bool_type
, c_expression
="{src0} < {src1}"),
630 operation("greater", 2, printable_name
=">", source_types
=numeric_types
, dest_type
=bool_type
, c_expression
="{src0} > {src1}"),
631 operation("lequal", 2, printable_name
="<=", source_types
=numeric_types
, dest_type
=bool_type
, c_expression
="{src0} <= {src1}"),
632 operation("gequal", 2, printable_name
=">=", source_types
=numeric_types
, dest_type
=bool_type
, c_expression
="{src0} >= {src1}"),
633 operation("equal", 2, printable_name
="==", source_types
=all_types
, dest_type
=bool_type
, c_expression
="{src0} == {src1}"),
634 operation("nequal", 2, printable_name
="!=", source_types
=all_types
, dest_type
=bool_type
, c_expression
="{src0} != {src1}"),
636 # Returns single boolean for whether all components of operands[0]
637 # equal the components of operands[1].
638 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
))),
640 # Returns single boolean for whether any component of operands[0]
641 # is not equal to the corresponding component of operands[1].
642 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
))),
644 # Bit-wise binary operations.
645 operation("lshift", 2, printable_name
="<<", source_types
=integer_types
, c_expression
="{src0} << {src1}", flags
=frozenset((vector_scalar_operation
, mixed_type_operation
))),
646 operation("rshift", 2, printable_name
=">>", source_types
=integer_types
, c_expression
="{src0} >> {src1}", flags
=frozenset((vector_scalar_operation
, mixed_type_operation
))),
647 operation("bit_and", 2, printable_name
="&", source_types
=integer_types
, c_expression
="{src0} & {src1}", flags
=vector_scalar_operation
),
648 operation("bit_xor", 2, printable_name
="^", source_types
=integer_types
, c_expression
="{src0} ^ {src1}", flags
=vector_scalar_operation
),
649 operation("bit_or", 2, printable_name
="|", source_types
=integer_types
, c_expression
="{src0} | {src1}", flags
=vector_scalar_operation
),
651 operation("logic_and", 2, printable_name
="&&", source_types
=(bool_type
,), c_expression
="{src0} && {src1}"),
652 operation("logic_xor", 2, printable_name
="^^", source_types
=(bool_type
,), c_expression
="{src0} != {src1}"),
653 operation("logic_or", 2, printable_name
="||", source_types
=(bool_type
,), c_expression
="{src0} || {src1}"),
655 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
),
656 operation("min", 2, source_types
=numeric_types
, c_expression
="MIN2({src0}, {src1})", flags
=vector_scalar_operation
),
657 operation("max", 2, source_types
=numeric_types
, c_expression
="MAX2({src0}, {src1})", flags
=vector_scalar_operation
),
659 operation("pow", 2, source_types
=(float_type
,), c_expression
="powf({src0}, {src1})"),
661 # Load a value the size of a given GLSL type from a uniform block.
663 # operand0 is the ir_constant uniform block index in the linked shader.
664 # operand1 is a byte offset within the uniform block.
665 operation("ubo_load", 2),
667 # Multiplies a number by two to a power, part of ARB_gpu_shader5.
668 operation("ldexp", 2,
669 all_signatures
=((float_type
, (float_type
, int_type
)),
670 (double_type
, (double_type
, int_type
))),
671 c_expression
={'f': "ldexpf_flush_subnormal({src0}, {src1})",
672 'd': "ldexp_flush_subnormal({src0}, {src1})"}),
674 # Extract a scalar from a vector
676 # operand0 is the vector
677 # operand1 is the index of the field to read from operand0
678 operation("vector_extract", 2, source_types
=all_types
, c_expression
="anything-except-None"),
680 # Interpolate fs input at offset
682 # operand0 is the fs input
683 # operand1 is the offset from the pixel center
684 operation("interpolate_at_offset", 2),
686 # Interpolate fs input at sample position
688 # operand0 is the fs input
689 # operand1 is the sample ID
690 operation("interpolate_at_sample", 2),
692 # Fused floating-point multiply-add, part of ARB_gpu_shader5.
693 operation("fma", 3, source_types
=real_types
, c_expression
="{src0} * {src1} + {src2}"),
695 operation("lrp", 3, source_types
=real_types
, c_expression
={'f': "{src0} * (1.0f - {src2}) + ({src1} * {src2})", 'd': "{src0} * (1.0 - {src2}) + ({src1} * {src2})"}),
699 # A vector conditional select instruction (like ?:, but operating per-
700 # component on vectors).
702 # See also lower_instructions_visitor::ldexp_to_arith
703 operation("csel", 3),
705 operation("bitfield_extract", 3,
706 all_signatures
=((int_type
, (uint_type
, int_type
, int_type
)),
707 (int_type
, (int_type
, int_type
, int_type
))),
708 c_expression
={'u': "bitfield_extract_uint({src0}, {src1}, {src2})",
709 'i': "bitfield_extract_int({src0}, {src1}, {src2})"}),
711 # Generate a value with one field of a vector changed
713 # operand0 is the vector
714 # operand1 is the value to write into the vector result
715 # operand2 is the index in operand0 to be modified
716 operation("vector_insert", 3, source_types
=all_types
, c_expression
="anything-except-None"),
718 operation("bitfield_insert", 4,
719 all_signatures
=((uint_type
, (uint_type
, uint_type
, int_type
, int_type
)),
720 (int_type
, (int_type
, int_type
, int_type
, int_type
))),
721 c_expression
="bitfield_insert({src0}, {src1}, {src2}, {src3})",
722 flags
=types_identical_operation
),
724 operation("vector", 4, source_types
=all_types
, c_expression
="anything-except-None"),
728 if __name__
== "__main__":
730 * Copyright (C) 2010 Intel Corporation
732 * Permission is hereby granted, free of charge, to any person obtaining a
733 * copy of this software and associated documentation files (the "Software"),
734 * to deal in the Software without restriction, including without limitation
735 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
736 * and/or sell copies of the Software, and to permit persons to whom the
737 * Software is furnished to do so, subject to the following conditions:
739 * The above copyright notice and this permission notice (including the next
740 * paragraph) shall be included in all copies or substantial portions of the
743 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
744 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
745 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
746 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
747 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
748 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
749 * DEALINGS IN THE SOFTWARE.
752 enum_template
= mako
.template
.Template(copyright
+ """
753 enum ir_expression_operation {
754 % for item in values:
755 ${item.get_enum_name()},
758 /* Sentinels marking the last of each kind of operation. */
760 ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()},
762 ir_last_opcode = ir_quadop_${lasts[3].name}
765 strings_template
= mako
.template
.Template(copyright
+ """
766 const char *const ir_expression_operation_strings[] = {
767 % for item in values:
768 "${item.printable_name}",
772 constant_template
= mako
.template
.Template("""\
773 switch (this->operation) {
775 % if op.c_expression is not None:
781 /* FINISHME: Should handle all expression types. */
786 if sys
.argv
[1] == "enum":
787 lasts
= [None, None, None, None]
788 for item
in reversed(ir_expression_operation
):
789 i
= item
.num_operands
- 1
793 print(enum_template
.render(values
=ir_expression_operation
,
795 elif sys
.argv
[1] == "strings":
796 print(strings_template
.render(values
=ir_expression_operation
))
797 elif sys
.argv
[1] == "constant":
798 print(constant_template
.render(values
=ir_expression_operation
))