2 # Copyright (C) 2015 Intel Corporation
4 # Permission is hereby granted, free of charge, to any person obtaining a
5 # copy of this software and associated documentation files (the "Software"),
6 # to deal in the Software without restriction, including without limitation
7 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 # and/or sell copies of the Software, and to permit persons to whom the
9 # Software is furnished to do so, subject to the following conditions:
11 # The above copyright notice and this permission notice (including the next
12 # paragraph) shall be included in all copies or substantial portions of the
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 def __init__(self
, c_type
, union_field
, glsl_type
):
29 self
.union_field
= union_field
30 self
.glsl_type
= glsl_type
33 class type_signature_iter(object):
34 """Basic iterator for a set of type signatures. Various kinds of sequences of
35 types come in, and an iteration of type_signature objects come out.
39 def __init__(self
, source_types
, num_operands
):
40 """Initialize an iterator from a sequence of input types and a number
41 operands. This is for signatures where all the operands have the same
42 type and the result type of the operation is the same as the input type.
46 self
.source_types
= source_types
47 self
.num_operands
= num_operands
50 def __init__(self
, dest_type
, source_types
, num_operands
):
51 """Initialize an iterator from a result tpye, a sequence of input types and a
52 number operands. This is for signatures where all the operands have the
53 same type but the result type of the operation is different from the
57 self
.dest_type
= dest_type
58 self
.source_types
= source_types
59 self
.num_operands
= num_operands
66 if self
.i
< len(self
.source_types
):
70 if self
.dest_type
is None:
71 dest_type
= self
.source_types
[i
]
73 dest_type
= self
.dest_type
75 return (dest_type
, self
.num_operands
* (self
.source_types
[i
],))
82 uint_type
= type("unsigned", "u", "GLSL_TYPE_UINT")
83 int_type
= type("int", "i", "GLSL_TYPE_INT")
84 uint64_type
= type("uint64_t", "u64", "GLSL_TYPE_UINT64")
85 int64_type
= type("int64_t", "i64", "GLSL_TYPE_INT64")
86 float_type
= type("float", "f", "GLSL_TYPE_FLOAT")
87 double_type
= type("double", "d", "GLSL_TYPE_DOUBLE")
88 bool_type
= type("bool", "b", "GLSL_TYPE_BOOL")
90 all_types
= (uint_type
, int_type
, float_type
, double_type
, uint64_type
, int64_type
, bool_type
)
91 numeric_types
= (uint_type
, int_type
, float_type
, double_type
, uint64_type
, int64_type
)
92 signed_numeric_types
= (int_type
, float_type
, double_type
, int64_type
)
93 integer_types
= (uint_type
, int_type
, uint64_type
, int64_type
)
94 real_types
= (float_type
, double_type
)
96 # This template is for operations that can have operands of a several
97 # different types, and each type may or may not has a different C expression.
98 # This is used by most operations.
99 constant_template_common
= mako
.template
.Template("""\
100 case ${op.get_enum_name()}:
101 for (unsigned c = 0; c < op[0]->type->components(); c++) {
102 switch (op[0]->type->base_type) {
103 % for dst_type, src_types in op.signatures():
104 case ${src_types[0].glsl_type}:
105 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
109 unreachable("invalid type");
114 # This template is for binary operations that can operate on some combination
115 # of scalar and vector operands.
116 constant_template_vector_scalar
= mako
.template
.Template("""\
117 case ${op.get_enum_name()}:
118 % if "mixed" in op.flags:
119 % for i in range(op.num_operands):
120 assert(op[${i}]->type->base_type == ${op.source_types[0].glsl_type} ||
121 % for src_type in op.source_types[1:-1]:
122 op[${i}]->type->base_type == ${src_type.glsl_type} ||
124 op[${i}]->type->base_type == ${op.source_types[-1].glsl_type});
127 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
129 for (unsigned c = 0, c0 = 0, c1 = 0;
131 c0 += c0_inc, c1 += c1_inc, c++) {
133 switch (op[0]->type->base_type) {
134 % for dst_type, src_types in op.signatures():
135 case ${src_types[0].glsl_type}:
136 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
140 unreachable("invalid type");
145 # This template is for multiplication. It is unique because it has to support
146 # matrix * vector and matrix * matrix operations, and those are just different.
147 constant_template_mul
= mako
.template
.Template("""\
148 case ${op.get_enum_name()}:
149 /* Check for equal types, or unequal types involving scalars */
150 if ((op[0]->type == op[1]->type && !op[0]->type->is_matrix())
151 || op0_scalar || op1_scalar) {
152 for (unsigned c = 0, c0 = 0, c1 = 0;
154 c0 += c0_inc, c1 += c1_inc, c++) {
156 switch (op[0]->type->base_type) {
157 % for dst_type, src_types in op.signatures():
158 case ${src_types[0].glsl_type}:
159 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
163 unreachable("invalid type");
167 assert(op[0]->type->is_matrix() || op[1]->type->is_matrix());
169 /* Multiply an N-by-M matrix with an M-by-P matrix. Since either
170 * matrix can be a GLSL vector, either N or P can be 1.
172 * For vec*mat, the vector is treated as a row vector. This
173 * means the vector is a 1-row x M-column matrix.
175 * For mat*vec, the vector is treated as a column vector. Since
176 * matrix_columns is 1 for vectors, this just works.
178 const unsigned n = op[0]->type->is_vector()
179 ? 1 : op[0]->type->vector_elements;
180 const unsigned m = op[1]->type->vector_elements;
181 const unsigned p = op[1]->type->matrix_columns;
182 for (unsigned j = 0; j < p; j++) {
183 for (unsigned i = 0; i < n; i++) {
184 for (unsigned k = 0; k < m; k++) {
185 if (op[0]->type->is_double())
186 data.d[i+n*j] += op[0]->value.d[i+n*k]*op[1]->value.d[k+m*j];
188 data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
195 # This template is for operations that are horizontal and either have only a
196 # single type or the implementation for all types is identical. That is, the
197 # operation consumes a vector and produces a scalar.
198 constant_template_horizontal_single_implementation
= mako
.template
.Template("""\
199 case ${op.get_enum_name()}:
200 data.${op.dest_type.union_field}[0] = ${op.c_expression['default']};
203 # This template is for operations that are horizontal and do not assign the
204 # result. The various unpack operations are examples.
205 constant_template_horizontal_nonassignment
= mako
.template
.Template("""\
206 case ${op.get_enum_name()}:
207 ${op.c_expression['default']};
210 # This template is for binary operations that are horizontal. That is, the
211 # operation consumes a vector and produces a scalar.
212 constant_template_horizontal
= mako
.template
.Template("""\
213 case ${op.get_enum_name()}:
214 switch (op[0]->type->base_type) {
215 % for dst_type, src_types in op.signatures():
216 case ${src_types[0].glsl_type}:
217 data.${dst_type.union_field}[0] = ${op.get_c_expression(src_types)};
221 unreachable("invalid type");
225 # This template is for ir_binop_vector_extract.
226 constant_template_vector_extract
= mako
.template
.Template("""\
227 case ${op.get_enum_name()}: {
228 const int c = CLAMP(op[1]->value.i[0], 0,
229 (int) op[0]->type->vector_elements - 1);
231 switch (op[0]->type->base_type) {
232 % for dst_type, src_types in op.signatures():
233 case ${src_types[0].glsl_type}:
234 data.${dst_type.union_field}[0] = op[0]->value.${src_types[0].union_field}[c];
238 unreachable("invalid type");
243 # This template is for ir_triop_vector_insert.
244 constant_template_vector_insert
= mako
.template
.Template("""\
245 case ${op.get_enum_name()}: {
246 const unsigned idx = op[2]->value.u[0];
248 memcpy(&data, &op[0]->value, sizeof(data));
250 switch (this->type->base_type) {
251 % for dst_type, src_types in op.signatures():
252 case ${src_types[0].glsl_type}:
253 data.${dst_type.union_field}[idx] = op[1]->value.${src_types[0].union_field}[0];
257 unreachable("invalid type");
262 # This template is for ir_quadop_vector.
263 constant_template_vector
= mako
.template
.Template("""\
264 case ${op.get_enum_name()}:
265 for (unsigned c = 0; c < this->type->vector_elements; c++) {
266 switch (this->type->base_type) {
267 % for dst_type, src_types in op.signatures():
268 case ${src_types[0].glsl_type}:
269 data.${dst_type.union_field}[c] = op[c]->value.${src_types[0].union_field}[0];
273 unreachable("invalid type");
278 # This template is for ir_triop_lrp.
279 constant_template_lrp
= mako
.template
.Template("""\
280 case ${op.get_enum_name()}: {
281 assert(op[0]->type->is_float() || op[0]->type->is_double());
282 assert(op[1]->type->is_float() || op[1]->type->is_double());
283 assert(op[2]->type->is_float() || op[2]->type->is_double());
285 unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
286 for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
287 switch (this->type->base_type) {
288 % for dst_type, src_types in op.signatures():
289 case ${src_types[0].glsl_type}:
290 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c", "c", "c2"))};
294 unreachable("invalid type");
300 # This template is for ir_triop_csel. This expression is really unique
301 # because not all of the operands are the same type, and the second operand
302 # determines the type of the expression (instead of the first).
303 constant_template_csel
= mako
.template
.Template("""\
304 case ${op.get_enum_name()}:
305 for (unsigned c = 0; c < components; c++) {
306 switch (this->type->base_type) {
307 % for dst_type, src_types in op.signatures():
308 case ${src_types[1].glsl_type}:
309 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
313 unreachable("invalid type");
319 vector_scalar_operation
= "vector-scalar"
320 horizontal_operation
= "horizontal"
321 types_identical_operation
= "identical"
322 non_assign_operation
= "nonassign"
323 mixed_type_operation
= "mixed"
325 class operation(object):
326 def __init__(self
, name
, num_operands
, printable_name
= None, source_types
= None, dest_type
= None, c_expression
= None, flags
= None, all_signatures
= None):
328 self
.num_operands
= num_operands
330 if printable_name
is None:
331 self
.printable_name
= name
333 self
.printable_name
= printable_name
335 self
.all_signatures
= all_signatures
337 if source_types
is None:
338 self
.source_types
= tuple()
340 self
.source_types
= source_types
342 self
.dest_type
= dest_type
344 if c_expression
is None:
345 self
.c_expression
= None
346 elif isinstance(c_expression
, str):
347 self
.c_expression
= {'default': c_expression
}
349 self
.c_expression
= c_expression
352 self
.flags
= frozenset()
353 elif isinstance(flags
, str):
354 self
.flags
= frozenset([flags
])
356 self
.flags
= frozenset(flags
)
359 def get_enum_name(self
):
360 return "ir_{0}op_{1}".format(("un", "bin", "tri", "quad")[self
.num_operands
-1], self
.name
)
363 def get_template(self
):
364 if self
.c_expression
is None:
367 if horizontal_operation
in self
.flags
:
368 if non_assign_operation
in self
.flags
:
369 return constant_template_horizontal_nonassignment
.render(op
=self
)
370 elif types_identical_operation
in self
.flags
:
371 return constant_template_horizontal_single_implementation
.render(op
=self
)
373 return constant_template_horizontal
.render(op
=self
)
375 if self
.num_operands
== 2:
376 if self
.name
== "mul":
377 return constant_template_mul
.render(op
=self
)
378 elif self
.name
== "vector_extract":
379 return constant_template_vector_extract
.render(op
=self
)
380 elif vector_scalar_operation
in self
.flags
:
381 return constant_template_vector_scalar
.render(op
=self
)
382 elif self
.num_operands
== 3:
383 if self
.name
== "vector_insert":
384 return constant_template_vector_insert
.render(op
=self
)
385 elif self
.name
== "lrp":
386 return constant_template_lrp
.render(op
=self
)
387 elif self
.name
== "csel":
388 return constant_template_csel
.render(op
=self
)
389 elif self
.num_operands
== 4:
390 if self
.name
== "vector":
391 return constant_template_vector
.render(op
=self
)
393 return constant_template_common
.render(op
=self
)
396 def get_c_expression(self
, types
, indices
=("c", "c", "c")):
397 src0
= "op[0]->value.{0}[{1}]".format(types
[0].union_field
, indices
[0])
398 src1
= "op[1]->value.{0}[{1}]".format(types
[1].union_field
, indices
[1]) if len(types
) >= 2 else "ERROR"
399 src2
= "op[2]->value.{0}[{1}]".format(types
[2].union_field
, indices
[2]) if len(types
) >= 3 else "ERROR"
400 src3
= "op[3]->value.{0}[c]".format(types
[3].union_field
) if len(types
) >= 4 else "ERROR"
402 expr
= self
.c_expression
[types
[0].union_field
] if types
[0].union_field
in self
.c_expression
else self
.c_expression
['default']
404 return expr
.format(src0
=src0
,
410 def signatures(self
):
411 if self
.all_signatures
is not None:
412 return self
.all_signatures
414 return type_signature_iter(self
.dest_type
, self
.source_types
, self
.num_operands
)
417 ir_expression_operation
= [
418 operation("bit_not", 1, printable_name
="~", source_types
=integer_types
, c_expression
="~ {src0}"),
419 operation("logic_not", 1, printable_name
="!", source_types
=(bool_type
,), c_expression
="!{src0}"),
420 operation("neg", 1, source_types
=numeric_types
, c_expression
={'u': "-((int) {src0})", 'u64': "-((int64_t) {src0})", 'default': "-{src0}"}),
421 operation("abs", 1, source_types
=signed_numeric_types
, c_expression
={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({src0})", 'i64': "{src0} < 0 ? -{src0} : {src0}"}),
422 operation("sign", 1, source_types
=signed_numeric_types
, c_expression
={'i': "({src0} > 0) - ({src0} < 0)", 'f': "float(({src0} > 0.0F) - ({src0} < 0.0F))", 'd': "double(({src0} > 0.0) - ({src0} < 0.0))", 'i64': "({src0} > 0) - ({src0} < 0)"}),
423 operation("rcp", 1, source_types
=real_types
, c_expression
={'f': "1.0F / {src0}", 'd': "1.0 / {src0}"}),
424 operation("rsq", 1, source_types
=real_types
, c_expression
={'f': "1.0F / sqrtf({src0})", 'd': "1.0 / sqrt({src0})"}),
425 operation("sqrt", 1, source_types
=real_types
, c_expression
={'f': "sqrtf({src0})", 'd': "sqrt({src0})"}),
426 operation("exp", 1, source_types
=(float_type
,), c_expression
="expf({src0})"), # Log base e on gentype
427 operation("log", 1, source_types
=(float_type
,), c_expression
="logf({src0})"), # Natural log on gentype
428 operation("exp2", 1, source_types
=(float_type
,), c_expression
="exp2f({src0})"),
429 operation("log2", 1, source_types
=(float_type
,), c_expression
="log2f({src0})"),
431 # Float-to-integer conversion.
432 operation("f2i", 1, source_types
=(float_type
,), dest_type
=int_type
, c_expression
="(int) {src0}"),
433 # Float-to-unsigned conversion.
434 operation("f2u", 1, source_types
=(float_type
,), dest_type
=uint_type
, c_expression
="(unsigned) {src0}"),
435 # Integer-to-float conversion.
436 operation("i2f", 1, source_types
=(int_type
,), dest_type
=float_type
, c_expression
="(float) {src0}"),
437 # Float-to-boolean conversion
438 operation("f2b", 1, source_types
=(float_type
,), dest_type
=bool_type
, c_expression
="{src0} != 0.0F ? true : false"),
439 # Boolean-to-float conversion
440 operation("b2f", 1, source_types
=(bool_type
,), dest_type
=float_type
, c_expression
="{src0} ? 1.0F : 0.0F"),
441 # int-to-boolean conversion
442 operation("i2b", 1, source_types
=(uint_type
, int_type
), dest_type
=bool_type
, c_expression
="{src0} ? true : false"),
443 # Boolean-to-int conversion
444 operation("b2i", 1, source_types
=(bool_type
,), dest_type
=int_type
, c_expression
="{src0} ? 1 : 0"),
445 # Unsigned-to-float conversion.
446 operation("u2f", 1, source_types
=(uint_type
,), dest_type
=float_type
, c_expression
="(float) {src0}"),
447 # Integer-to-unsigned conversion.
448 operation("i2u", 1, source_types
=(int_type
,), dest_type
=uint_type
, c_expression
="{src0}"),
449 # Unsigned-to-integer conversion.
450 operation("u2i", 1, source_types
=(uint_type
,), dest_type
=int_type
, c_expression
="{src0}"),
451 # Double-to-float conversion.
452 operation("d2f", 1, source_types
=(double_type
,), dest_type
=float_type
, c_expression
="{src0}"),
453 # Float-to-double conversion.
454 operation("f2d", 1, source_types
=(float_type
,), dest_type
=double_type
, c_expression
="{src0}"),
455 # Double-to-integer conversion.
456 operation("d2i", 1, source_types
=(double_type
,), dest_type
=int_type
, c_expression
="{src0}"),
457 # Integer-to-double conversion.
458 operation("i2d", 1, source_types
=(int_type
,), dest_type
=double_type
, c_expression
="{src0}"),
459 # Double-to-unsigned conversion.
460 operation("d2u", 1, source_types
=(double_type
,), dest_type
=uint_type
, c_expression
="{src0}"),
461 # Unsigned-to-double conversion.
462 operation("u2d", 1, source_types
=(uint_type
,), dest_type
=double_type
, c_expression
="{src0}"),
463 # Double-to-boolean conversion.
464 operation("d2b", 1, source_types
=(double_type
,), dest_type
=bool_type
, c_expression
="{src0} != 0.0"),
465 # 'Bit-identical int-to-float "conversion"
466 operation("bitcast_i2f", 1, source_types
=(int_type
,), dest_type
=float_type
, c_expression
="bitcast_u2f({src0})"),
467 # 'Bit-identical float-to-int "conversion"
468 operation("bitcast_f2i", 1, source_types
=(float_type
,), dest_type
=int_type
, c_expression
="bitcast_f2u({src0})"),
469 # 'Bit-identical uint-to-float "conversion"
470 operation("bitcast_u2f", 1, source_types
=(uint_type
,), dest_type
=float_type
, c_expression
="bitcast_u2f({src0})"),
471 # 'Bit-identical float-to-uint "conversion"
472 operation("bitcast_f2u", 1, source_types
=(float_type
,), dest_type
=uint_type
, c_expression
="bitcast_f2u({src0})"),
473 # Bit-identical u64-to-double "conversion"
474 operation("bitcast_u642d", 1, source_types
=(uint64_type
,), dest_type
=double_type
, c_expression
="bitcast_u642d({src0})"),
475 # Bit-identical i64-to-double "conversion"
476 operation("bitcast_i642d", 1, source_types
=(int64_type
,), dest_type
=double_type
, c_expression
="bitcast_i642d({src0})"),
477 # Bit-identical double-to_u64 "conversion"
478 operation("bitcast_d2u64", 1, source_types
=(double_type
,), dest_type
=uint64_type
, c_expression
="bitcast_d2u64({src0})"),
479 # Bit-identical double-to-i64 "conversion"
480 operation("bitcast_d2i64", 1, source_types
=(double_type
,), dest_type
=int64_type
, c_expression
="bitcast_d2i64({src0})"),
481 # i64-to-i32 conversion
482 operation("i642i", 1, source_types
=(int64_type
,), dest_type
=int_type
, c_expression
="{src0}"),
483 # ui64-to-i32 conversion
484 operation("u642i", 1, source_types
=(uint64_type
,), dest_type
=int_type
, c_expression
="{src0}"),
485 operation("i642u", 1, source_types
=(int64_type
,), dest_type
=uint_type
, c_expression
="{src0}"),
486 operation("u642u", 1, source_types
=(uint64_type
,), dest_type
=uint_type
, c_expression
="{src0}"),
487 operation("i642b", 1, source_types
=(int64_type
,), dest_type
=bool_type
, c_expression
="{src0} != 0"),
488 operation("i642f", 1, source_types
=(int64_type
,), dest_type
=float_type
, c_expression
="{src0}"),
489 operation("u642f", 1, source_types
=(uint64_type
,), dest_type
=float_type
, c_expression
="{src0}"),
490 operation("i642d", 1, source_types
=(int64_type
,), dest_type
=double_type
, c_expression
="{src0}"),
491 operation("u642d", 1, source_types
=(uint64_type
,), dest_type
=double_type
, c_expression
="{src0}"),
492 operation("i2i64", 1, source_types
=(int_type
,), dest_type
=int64_type
, c_expression
="{src0}"),
493 operation("u2i64", 1, source_types
=(uint_type
,), dest_type
=int64_type
, c_expression
="{src0}"),
494 operation("b2i64", 1, source_types
=(bool_type
,), dest_type
=int64_type
, c_expression
="{src0}"),
495 operation("f2i64", 1, source_types
=(float_type
,), dest_type
=int64_type
, c_expression
="{src0}"),
496 operation("d2i64", 1, source_types
=(double_type
,), dest_type
=int64_type
, c_expression
="{src0}"),
497 operation("i2u64", 1, source_types
=(int_type
,), dest_type
=uint64_type
, c_expression
="{src0}"),
498 operation("u2u64", 1, source_types
=(uint_type
,), dest_type
=uint64_type
, c_expression
="{src0}"),
499 operation("f2u64", 1, source_types
=(float_type
,), dest_type
=uint64_type
, c_expression
="{src0}"),
500 operation("d2u64", 1, source_types
=(double_type
,), dest_type
=uint64_type
, c_expression
="{src0}"),
501 operation("u642i64", 1, source_types
=(uint64_type
,), dest_type
=int64_type
, c_expression
="{src0}"),
502 operation("i642u64", 1, source_types
=(int64_type
,), dest_type
=uint64_type
, c_expression
="{src0}"),
505 # Unary floating-point rounding operations.
506 operation("trunc", 1, source_types
=real_types
, c_expression
={'f': "truncf({src0})", 'd': "trunc({src0})"}),
507 operation("ceil", 1, source_types
=real_types
, c_expression
={'f': "ceilf({src0})", 'd': "ceil({src0})"}),
508 operation("floor", 1, source_types
=real_types
, c_expression
={'f': "floorf({src0})", 'd': "floor({src0})"}),
509 operation("fract", 1, source_types
=real_types
, c_expression
={'f': "{src0} - floorf({src0})", 'd': "{src0} - floor({src0})"}),
510 operation("round_even", 1, source_types
=real_types
, c_expression
={'f': "_mesa_roundevenf({src0})", 'd': "_mesa_roundeven({src0})"}),
512 # Trigonometric operations.
513 operation("sin", 1, source_types
=(float_type
,), c_expression
="sinf({src0})"),
514 operation("cos", 1, source_types
=(float_type
,), c_expression
="cosf({src0})"),
516 # Partial derivatives.
517 operation("dFdx", 1, source_types
=(float_type
,), c_expression
="0.0f"),
518 operation("dFdx_coarse", 1, printable_name
="dFdxCoarse", source_types
=(float_type
,), c_expression
="0.0f"),
519 operation("dFdx_fine", 1, printable_name
="dFdxFine", source_types
=(float_type
,), c_expression
="0.0f"),
520 operation("dFdy", 1, source_types
=(float_type
,), c_expression
="0.0f"),
521 operation("dFdy_coarse", 1, printable_name
="dFdyCoarse", source_types
=(float_type
,), c_expression
="0.0f"),
522 operation("dFdy_fine", 1, printable_name
="dFdyFine", source_types
=(float_type
,), c_expression
="0.0f"),
524 # Floating point pack and unpack operations.
525 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
),
526 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
),
527 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
),
528 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
),
529 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
),
530 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
))),
531 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
))),
532 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
))),
533 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
))),
534 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
))),
536 # Bit operations, part of ARB_gpu_shader5.
537 operation("bitfield_reverse", 1, source_types
=(uint_type
, int_type
), c_expression
="bitfield_reverse({src0})"),
538 operation("bit_count", 1, source_types
=(uint_type
, int_type
), dest_type
=int_type
, c_expression
="util_bitcount({src0})"),
539 operation("find_msb", 1, source_types
=(uint_type
, int_type
), dest_type
=int_type
, c_expression
={'u': "find_msb_uint({src0})", 'i': "find_msb_int({src0})"}),
540 operation("find_lsb", 1, source_types
=(uint_type
, int_type
), dest_type
=int_type
, c_expression
="find_msb_uint({src0} & -{src0})"),
542 operation("saturate", 1, printable_name
="sat", source_types
=(float_type
,), c_expression
="CLAMP({src0}, 0.0f, 1.0f)"),
544 # Double packing, part of ARB_gpu_shader_fp64.
545 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
))),
546 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
))),
548 # Sampler/Image packing, part of ARB_bindless_texture.
549 operation("pack_sampler_2x32", 1, printable_name
="packSampler2x32", source_types
=(uint_type
,), dest_type
=uint64_type
, c_expression
="memcpy(&data.u64[0], &op[0]->value.u[0], sizeof(uint64_t))", flags
=frozenset((horizontal_operation
, non_assign_operation
))),
550 operation("pack_image_2x32", 1, printable_name
="packImage2x32", source_types
=(uint_type
,), dest_type
=uint64_type
, c_expression
="memcpy(&data.u64[0], &op[0]->value.u[0], sizeof(uint64_t))", flags
=frozenset((horizontal_operation
, non_assign_operation
))),
551 operation("unpack_sampler_2x32", 1, printable_name
="unpackSampler2x32", source_types
=(uint64_type
,), dest_type
=uint_type
, c_expression
="memcpy(&data.u[0], &op[0]->value.u64[0], sizeof(uint64_t))", flags
=frozenset((horizontal_operation
, non_assign_operation
))),
552 operation("unpack_image_2x32", 1, printable_name
="unpackImage2x32", source_types
=(uint64_type
,), dest_type
=uint_type
, c_expression
="memcpy(&data.u[0], &op[0]->value.u64[0], sizeof(uint64_t))", flags
=frozenset((horizontal_operation
, non_assign_operation
))),
554 operation("frexp_sig", 1),
555 operation("frexp_exp", 1),
557 operation("noise", 1),
559 operation("subroutine_to_int", 1),
561 # Interpolate fs input at centroid
563 # operand0 is the fs input.
564 operation("interpolate_at_centroid", 1),
566 # Ask the driver for the total size of a buffer block.
567 # operand0 is the ir_constant buffer block index in the linked shader.
568 operation("get_buffer_size", 1),
570 # Calculate length of an unsized array inside a buffer block.
571 # This opcode is going to be replaced in a lowering pass inside
574 # operand0 is the unsized array's ir_value for the calculation
576 operation("ssbo_unsized_array_length", 1),
578 # 64-bit integer packing ops.
579 operation("pack_int_2x32", 1, printable_name
="packInt2x32", source_types
=(int_type
,), dest_type
=int64_type
, c_expression
="memcpy(&data.i64[0], &op[0]->value.i[0], sizeof(int64_t))", flags
=frozenset((horizontal_operation
, non_assign_operation
))),
580 operation("pack_uint_2x32", 1, printable_name
="packUint2x32", source_types
=(uint_type
,), dest_type
=uint64_type
, c_expression
="memcpy(&data.u64[0], &op[0]->value.u[0], sizeof(uint64_t))", flags
=frozenset((horizontal_operation
, non_assign_operation
))),
581 operation("unpack_int_2x32", 1, printable_name
="unpackInt2x32", source_types
=(int64_type
,), dest_type
=int_type
, c_expression
="memcpy(&data.i[0], &op[0]->value.i64[0], sizeof(int64_t))", flags
=frozenset((horizontal_operation
, non_assign_operation
))),
582 operation("unpack_uint_2x32", 1, printable_name
="unpackUint2x32", source_types
=(uint64_type
,), dest_type
=uint_type
, c_expression
="memcpy(&data.u[0], &op[0]->value.u64[0], sizeof(uint64_t))", flags
=frozenset((horizontal_operation
, non_assign_operation
))),
584 operation("add", 2, printable_name
="+", source_types
=numeric_types
, c_expression
="{src0} + {src1}", flags
=vector_scalar_operation
),
585 operation("sub", 2, printable_name
="-", source_types
=numeric_types
, c_expression
="{src0} - {src1}", flags
=vector_scalar_operation
),
586 # "Floating-point or low 32-bit integer multiply."
587 operation("mul", 2, printable_name
="*", source_types
=numeric_types
, c_expression
="{src0} * {src1}"),
588 operation("imul_high", 2), # Calculates the high 32-bits of a 64-bit multiply.
589 operation("div", 2, printable_name
="/", source_types
=numeric_types
, c_expression
={'u': "{src1} == 0 ? 0 : {src0} / {src1}", 'i': "{src1} == 0 ? 0 : {src0} / {src1}", 'u64': "{src1} == 0 ? 0 : {src0} / {src1}", 'i64': "{src1} == 0 ? 0 : {src0} / {src1}", 'default': "{src0} / {src1}"}, flags
=vector_scalar_operation
),
591 # Returns the carry resulting from the addition of the two arguments.
592 operation("carry", 2),
594 # Returns the borrow resulting from the subtraction of the second argument
595 # from the first argument.
596 operation("borrow", 2),
598 # Either (vector % vector) or (vector % scalar)
600 # We don't use fmod because it rounds toward zero; GLSL specifies the use
602 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})", 'u64': "{src1} == 0 ? 0 : {src0} % {src1}", 'i64': "{src1} == 0 ? 0 : {src0} % {src1}"}, flags
=vector_scalar_operation
),
604 # Binary comparison operators which return a boolean vector.
605 # The type of both operands must be equal.
606 operation("less", 2, printable_name
="<", source_types
=numeric_types
, dest_type
=bool_type
, c_expression
="{src0} < {src1}"),
607 operation("gequal", 2, printable_name
=">=", source_types
=numeric_types
, dest_type
=bool_type
, c_expression
="{src0} >= {src1}"),
608 operation("equal", 2, printable_name
="==", source_types
=all_types
, dest_type
=bool_type
, c_expression
="{src0} == {src1}"),
609 operation("nequal", 2, printable_name
="!=", source_types
=all_types
, dest_type
=bool_type
, c_expression
="{src0} != {src1}"),
611 # Returns single boolean for whether all components of operands[0]
612 # equal the components of operands[1].
613 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
))),
615 # Returns single boolean for whether any component of operands[0]
616 # is not equal to the corresponding component of operands[1].
617 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
))),
619 # Bit-wise binary operations.
620 operation("lshift", 2, printable_name
="<<", source_types
=integer_types
, c_expression
="{src0} << {src1}", flags
=frozenset((vector_scalar_operation
, mixed_type_operation
))),
621 operation("rshift", 2, printable_name
=">>", source_types
=integer_types
, c_expression
="{src0} >> {src1}", flags
=frozenset((vector_scalar_operation
, mixed_type_operation
))),
622 operation("bit_and", 2, printable_name
="&", source_types
=integer_types
, c_expression
="{src0} & {src1}", flags
=vector_scalar_operation
),
623 operation("bit_xor", 2, printable_name
="^", source_types
=integer_types
, c_expression
="{src0} ^ {src1}", flags
=vector_scalar_operation
),
624 operation("bit_or", 2, printable_name
="|", source_types
=integer_types
, c_expression
="{src0} | {src1}", flags
=vector_scalar_operation
),
626 operation("logic_and", 2, printable_name
="&&", source_types
=(bool_type
,), c_expression
="{src0} && {src1}"),
627 operation("logic_xor", 2, printable_name
="^^", source_types
=(bool_type
,), c_expression
="{src0} != {src1}"),
628 operation("logic_or", 2, printable_name
="||", source_types
=(bool_type
,), c_expression
="{src0} || {src1}"),
630 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
),
631 operation("min", 2, source_types
=numeric_types
, c_expression
="MIN2({src0}, {src1})", flags
=vector_scalar_operation
),
632 operation("max", 2, source_types
=numeric_types
, c_expression
="MAX2({src0}, {src1})", flags
=vector_scalar_operation
),
634 operation("pow", 2, source_types
=(float_type
,), c_expression
="powf({src0}, {src1})"),
636 # Load a value the size of a given GLSL type from a uniform block.
638 # operand0 is the ir_constant uniform block index in the linked shader.
639 # operand1 is a byte offset within the uniform block.
640 operation("ubo_load", 2),
642 # Multiplies a number by two to a power, part of ARB_gpu_shader5.
643 operation("ldexp", 2,
644 all_signatures
=((float_type
, (float_type
, int_type
)),
645 (double_type
, (double_type
, int_type
))),
646 c_expression
={'f': "ldexpf_flush_subnormal({src0}, {src1})",
647 'd': "ldexp_flush_subnormal({src0}, {src1})"}),
649 # Extract a scalar from a vector
651 # operand0 is the vector
652 # operand1 is the index of the field to read from operand0
653 operation("vector_extract", 2, source_types
=all_types
, c_expression
="anything-except-None"),
655 # Interpolate fs input at offset
657 # operand0 is the fs input
658 # operand1 is the offset from the pixel center
659 operation("interpolate_at_offset", 2),
661 # Interpolate fs input at sample position
663 # operand0 is the fs input
664 # operand1 is the sample ID
665 operation("interpolate_at_sample", 2),
667 # Fused floating-point multiply-add, part of ARB_gpu_shader5.
668 operation("fma", 3, source_types
=real_types
, c_expression
="{src0} * {src1} + {src2}"),
670 operation("lrp", 3, source_types
=real_types
, c_expression
={'f': "{src0} * (1.0f - {src2}) + ({src1} * {src2})", 'd': "{src0} * (1.0 - {src2}) + ({src1} * {src2})"}),
674 # A vector conditional select instruction (like ?:, but operating per-
675 # component on vectors).
677 # See also lower_instructions_visitor::ldexp_to_arith
679 all_signatures
=zip(all_types
, zip(len(all_types
) * (bool_type
,), all_types
, all_types
)),
680 c_expression
="{src0} ? {src1} : {src2}"),
682 operation("bitfield_extract", 3,
683 all_signatures
=((int_type
, (uint_type
, int_type
, int_type
)),
684 (int_type
, (int_type
, int_type
, int_type
))),
685 c_expression
={'u': "bitfield_extract_uint({src0}, {src1}, {src2})",
686 'i': "bitfield_extract_int({src0}, {src1}, {src2})"}),
688 # Generate a value with one field of a vector changed
690 # operand0 is the vector
691 # operand1 is the value to write into the vector result
692 # operand2 is the index in operand0 to be modified
693 operation("vector_insert", 3, source_types
=all_types
, c_expression
="anything-except-None"),
695 operation("bitfield_insert", 4,
696 all_signatures
=((uint_type
, (uint_type
, uint_type
, int_type
, int_type
)),
697 (int_type
, (int_type
, int_type
, int_type
, int_type
))),
698 c_expression
="bitfield_insert({src0}, {src1}, {src2}, {src3})"),
700 operation("vector", 4, source_types
=all_types
, c_expression
="anything-except-None"),
704 if __name__
== "__main__":
706 * Copyright (C) 2010 Intel Corporation
708 * Permission is hereby granted, free of charge, to any person obtaining a
709 * copy of this software and associated documentation files (the "Software"),
710 * to deal in the Software without restriction, including without limitation
711 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
712 * and/or sell copies of the Software, and to permit persons to whom the
713 * Software is furnished to do so, subject to the following conditions:
715 * The above copyright notice and this permission notice (including the next
716 * paragraph) shall be included in all copies or substantial portions of the
719 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
720 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
721 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
722 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
723 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
724 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
725 * DEALINGS IN THE SOFTWARE.
728 enum_template
= mako
.template
.Template(copyright
+ """
729 enum ir_expression_operation {
730 % for item in values:
731 ${item.get_enum_name()},
734 /* Sentinels marking the last of each kind of operation. */
736 ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()},
738 ir_last_opcode = ir_quadop_${lasts[3].name}
741 strings_template
= mako
.template
.Template(copyright
+ """
742 const char *const ir_expression_operation_strings[] = {
743 % for item in values:
744 "${item.printable_name}",
748 const char *const ir_expression_operation_enum_strings[] = {
749 % for item in values:
754 constant_template
= mako
.template
.Template("""\
755 switch (this->operation) {
757 % if op.c_expression is not None:
763 /* FINISHME: Should handle all expression types. */
768 if sys
.argv
[1] == "enum":
769 lasts
= [None, None, None, None]
770 for item
in reversed(ir_expression_operation
):
771 i
= item
.num_operands
- 1
775 print(enum_template
.render(values
=ir_expression_operation
,
777 elif sys
.argv
[1] == "strings":
778 print(strings_template
.render(values
=ir_expression_operation
))
779 elif sys
.argv
[1] == "constant":
780 print(constant_template
.render(values
=ir_expression_operation
))