2 * Copyright © 2010 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
21 * DEALINGS IN THE SOFTWARE.
25 * \file ir_constant_expression.cpp
26 * Evaluate and process constant valued expressions
28 * In GLSL, constant valued expressions are used in several places. These
29 * must be processed and evaluated very early in the compilation process.
32 * * Initializers for uniforms
33 * * Initializers for \c const variables
37 #include "main/core.h" /* for MAX2, MIN2, CLAMP */
39 #include "ir_visitor.h"
40 #include "glsl_types.h"
42 /* Using C99 rounding functions for roundToEven() implementation is
43 * difficult, because round(), rint, and nearbyint() are affected by
44 * fesetenv(), which the application may have done for its own
45 * purposes. Mesa's IROUND macro is close to what we want, but it
46 * rounds away from 0 on n + 0.5.
49 round_to_even(float val
)
51 int rounded
= IROUND(val
);
53 if (val
- floor(val
) == 0.5) {
55 rounded
+= val
> 0 ? -1 : 1;
62 dot(ir_constant
*op0
, ir_constant
*op1
)
64 assert(op0
->type
->is_float() && op1
->type
->is_float());
67 for (unsigned c
= 0; c
< op0
->type
->components(); c
++)
68 result
+= op0
->value
.f
[c
] * op1
->value
.f
[c
];
74 ir_expression::constant_expression_value()
76 if (this->type
->is_error())
79 ir_constant
*op
[Elements(this->operands
)] = { NULL
, };
80 ir_constant_data data
;
82 memset(&data
, 0, sizeof(data
));
84 for (unsigned operand
= 0; operand
< this->get_num_operands(); operand
++) {
85 op
[operand
] = this->operands
[operand
]->constant_expression_value();
91 assert(op
[0]->type
->base_type
== op
[1]->type
->base_type
||
92 this->operation
== ir_binop_lshift
||
93 this->operation
== ir_binop_rshift
);
95 bool op0_scalar
= op
[0]->type
->is_scalar();
96 bool op1_scalar
= op
[1] != NULL
&& op
[1]->type
->is_scalar();
98 /* When iterating over a vector or matrix's components, we want to increase
99 * the loop counter. However, for scalars, we want to stay at 0.
101 unsigned c0_inc
= op0_scalar
? 0 : 1;
102 unsigned c1_inc
= op1_scalar
? 0 : 1;
104 if (op1_scalar
|| !op
[1]) {
105 components
= op
[0]->type
->components();
107 components
= op
[1]->type
->components();
110 void *ctx
= ralloc_parent(this);
112 /* Handle array operations here, rather than below. */
113 if (op
[0]->type
->is_array()) {
114 assert(op
[1] != NULL
&& op
[1]->type
->is_array());
115 switch (this->operation
) {
116 case ir_binop_all_equal
:
117 return new(ctx
) ir_constant(op
[0]->has_value(op
[1]));
118 case ir_binop_any_nequal
:
119 return new(ctx
) ir_constant(!op
[0]->has_value(op
[1]));
126 switch (this->operation
) {
127 case ir_unop_bit_not
:
128 switch (op
[0]->type
->base_type
) {
130 for (unsigned c
= 0; c
< components
; c
++)
131 data
.i
[c
] = ~ op
[0]->value
.i
[c
];
134 for (unsigned c
= 0; c
< components
; c
++)
135 data
.u
[c
] = ~ op
[0]->value
.u
[c
];
142 case ir_unop_logic_not
:
143 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
144 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
145 data
.b
[c
] = !op
[0]->value
.b
[c
];
149 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
150 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
151 data
.i
[c
] = (int) op
[0]->value
.f
[c
];
155 assert(op
[0]->type
->base_type
== GLSL_TYPE_INT
);
156 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
157 data
.f
[c
] = (float) op
[0]->value
.i
[c
];
161 assert(op
[0]->type
->base_type
== GLSL_TYPE_UINT
);
162 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
163 data
.f
[c
] = (float) op
[0]->value
.u
[c
];
167 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
168 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
169 data
.f
[c
] = op
[0]->value
.b
[c
] ? 1.0F
: 0.0F
;
173 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
174 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
175 data
.b
[c
] = op
[0]->value
.f
[c
] != 0.0F
? true : false;
179 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
180 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
181 data
.u
[c
] = op
[0]->value
.b
[c
] ? 1 : 0;
185 assert(op
[0]->type
->is_integer());
186 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
187 data
.b
[c
] = op
[0]->value
.u
[c
] ? true : false;
191 assert(op
[0]->type
->base_type
== GLSL_TYPE_UINT
);
192 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
193 data
.i
[c
] = op
[0]->value
.u
[c
];
197 assert(op
[0]->type
->base_type
== GLSL_TYPE_INT
);
198 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
199 data
.u
[c
] = op
[0]->value
.i
[c
];
203 assert(op
[0]->type
->is_boolean());
205 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
206 if (op
[0]->value
.b
[c
])
212 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
213 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
214 data
.f
[c
] = truncf(op
[0]->value
.f
[c
]);
218 case ir_unop_round_even
:
219 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
220 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
221 data
.f
[c
] = round_to_even(op
[0]->value
.f
[c
]);
226 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
227 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
228 data
.f
[c
] = ceilf(op
[0]->value
.f
[c
]);
233 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
234 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
235 data
.f
[c
] = floorf(op
[0]->value
.f
[c
]);
240 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
241 switch (this->type
->base_type
) {
248 case GLSL_TYPE_FLOAT
:
249 data
.f
[c
] = op
[0]->value
.f
[c
] - floor(op
[0]->value
.f
[c
]);
258 case ir_unop_sin_reduced
:
259 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
260 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
261 data
.f
[c
] = sinf(op
[0]->value
.f
[c
]);
266 case ir_unop_cos_reduced
:
267 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
268 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
269 data
.f
[c
] = cosf(op
[0]->value
.f
[c
]);
274 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
275 switch (this->type
->base_type
) {
277 data
.u
[c
] = -((int) op
[0]->value
.u
[c
]);
280 data
.i
[c
] = -op
[0]->value
.i
[c
];
282 case GLSL_TYPE_FLOAT
:
283 data
.f
[c
] = -op
[0]->value
.f
[c
];
292 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
293 switch (this->type
->base_type
) {
295 data
.u
[c
] = op
[0]->value
.u
[c
];
298 data
.i
[c
] = op
[0]->value
.i
[c
];
300 data
.i
[c
] = -data
.i
[c
];
302 case GLSL_TYPE_FLOAT
:
303 data
.f
[c
] = fabs(op
[0]->value
.f
[c
]);
312 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
313 switch (this->type
->base_type
) {
315 data
.u
[c
] = op
[0]->value
.i
[c
] > 0;
318 data
.i
[c
] = (op
[0]->value
.i
[c
] > 0) - (op
[0]->value
.i
[c
] < 0);
320 case GLSL_TYPE_FLOAT
:
321 data
.f
[c
] = float((op
[0]->value
.f
[c
] > 0)-(op
[0]->value
.f
[c
] < 0));
330 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
331 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
332 switch (this->type
->base_type
) {
334 if (op
[0]->value
.u
[c
] != 0.0)
335 data
.u
[c
] = 1 / op
[0]->value
.u
[c
];
338 if (op
[0]->value
.i
[c
] != 0.0)
339 data
.i
[c
] = 1 / op
[0]->value
.i
[c
];
341 case GLSL_TYPE_FLOAT
:
342 if (op
[0]->value
.f
[c
] != 0.0)
343 data
.f
[c
] = 1.0F
/ op
[0]->value
.f
[c
];
352 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
353 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
354 data
.f
[c
] = 1.0F
/ sqrtf(op
[0]->value
.f
[c
]);
359 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
360 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
361 data
.f
[c
] = sqrtf(op
[0]->value
.f
[c
]);
366 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
367 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
368 data
.f
[c
] = expf(op
[0]->value
.f
[c
]);
373 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
374 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
375 data
.f
[c
] = exp2f(op
[0]->value
.f
[c
]);
380 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
381 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
382 data
.f
[c
] = logf(op
[0]->value
.f
[c
]);
387 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
388 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
389 data
.f
[c
] = log2f(op
[0]->value
.f
[c
]);
395 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
396 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
402 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
403 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
404 data
.f
[c
] = powf(op
[0]->value
.f
[c
], op
[1]->value
.f
[c
]);
409 data
.f
[0] = dot(op
[0], op
[1]);
413 assert(op
[0]->type
== op
[1]->type
|| op0_scalar
|| op1_scalar
);
414 for (unsigned c
= 0, c0
= 0, c1
= 0;
416 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
418 switch (op
[0]->type
->base_type
) {
420 data
.u
[c
] = MIN2(op
[0]->value
.u
[c0
], op
[1]->value
.u
[c1
]);
423 data
.i
[c
] = MIN2(op
[0]->value
.i
[c0
], op
[1]->value
.i
[c1
]);
425 case GLSL_TYPE_FLOAT
:
426 data
.f
[c
] = MIN2(op
[0]->value
.f
[c0
], op
[1]->value
.f
[c1
]);
435 assert(op
[0]->type
== op
[1]->type
|| op0_scalar
|| op1_scalar
);
436 for (unsigned c
= 0, c0
= 0, c1
= 0;
438 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
440 switch (op
[0]->type
->base_type
) {
442 data
.u
[c
] = MAX2(op
[0]->value
.u
[c0
], op
[1]->value
.u
[c1
]);
445 data
.i
[c
] = MAX2(op
[0]->value
.i
[c0
], op
[1]->value
.i
[c1
]);
447 case GLSL_TYPE_FLOAT
:
448 data
.f
[c
] = MAX2(op
[0]->value
.f
[c0
], op
[1]->value
.f
[c1
]);
457 assert(op
[0]->type
== op
[1]->type
|| op0_scalar
|| op1_scalar
);
458 for (unsigned c
= 0, c0
= 0, c1
= 0;
460 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
462 switch (op
[0]->type
->base_type
) {
464 data
.u
[c
] = op
[0]->value
.u
[c0
] + op
[1]->value
.u
[c1
];
467 data
.i
[c
] = op
[0]->value
.i
[c0
] + op
[1]->value
.i
[c1
];
469 case GLSL_TYPE_FLOAT
:
470 data
.f
[c
] = op
[0]->value
.f
[c0
] + op
[1]->value
.f
[c1
];
479 assert(op
[0]->type
== op
[1]->type
|| op0_scalar
|| op1_scalar
);
480 for (unsigned c
= 0, c0
= 0, c1
= 0;
482 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
484 switch (op
[0]->type
->base_type
) {
486 data
.u
[c
] = op
[0]->value
.u
[c0
] - op
[1]->value
.u
[c1
];
489 data
.i
[c
] = op
[0]->value
.i
[c0
] - op
[1]->value
.i
[c1
];
491 case GLSL_TYPE_FLOAT
:
492 data
.f
[c
] = op
[0]->value
.f
[c0
] - op
[1]->value
.f
[c1
];
501 /* Check for equal types, or unequal types involving scalars */
502 if ((op
[0]->type
== op
[1]->type
&& !op
[0]->type
->is_matrix())
503 || op0_scalar
|| op1_scalar
) {
504 for (unsigned c
= 0, c0
= 0, c1
= 0;
506 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
508 switch (op
[0]->type
->base_type
) {
510 data
.u
[c
] = op
[0]->value
.u
[c0
] * op
[1]->value
.u
[c1
];
513 data
.i
[c
] = op
[0]->value
.i
[c0
] * op
[1]->value
.i
[c1
];
515 case GLSL_TYPE_FLOAT
:
516 data
.f
[c
] = op
[0]->value
.f
[c0
] * op
[1]->value
.f
[c1
];
523 assert(op
[0]->type
->is_matrix() || op
[1]->type
->is_matrix());
525 /* Multiply an N-by-M matrix with an M-by-P matrix. Since either
526 * matrix can be a GLSL vector, either N or P can be 1.
528 * For vec*mat, the vector is treated as a row vector. This
529 * means the vector is a 1-row x M-column matrix.
531 * For mat*vec, the vector is treated as a column vector. Since
532 * matrix_columns is 1 for vectors, this just works.
534 const unsigned n
= op
[0]->type
->is_vector()
535 ? 1 : op
[0]->type
->vector_elements
;
536 const unsigned m
= op
[1]->type
->vector_elements
;
537 const unsigned p
= op
[1]->type
->matrix_columns
;
538 for (unsigned j
= 0; j
< p
; j
++) {
539 for (unsigned i
= 0; i
< n
; i
++) {
540 for (unsigned k
= 0; k
< m
; k
++) {
541 data
.f
[i
+n
*j
] += op
[0]->value
.f
[i
+n
*k
]*op
[1]->value
.f
[k
+m
*j
];
549 /* FINISHME: Emit warning when division-by-zero is detected. */
550 assert(op
[0]->type
== op
[1]->type
|| op0_scalar
|| op1_scalar
);
551 for (unsigned c
= 0, c0
= 0, c1
= 0;
553 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
555 switch (op
[0]->type
->base_type
) {
557 if (op
[1]->value
.u
[c1
] == 0) {
560 data
.u
[c
] = op
[0]->value
.u
[c0
] / op
[1]->value
.u
[c1
];
564 if (op
[1]->value
.i
[c1
] == 0) {
567 data
.i
[c
] = op
[0]->value
.i
[c0
] / op
[1]->value
.i
[c1
];
570 case GLSL_TYPE_FLOAT
:
571 data
.f
[c
] = op
[0]->value
.f
[c0
] / op
[1]->value
.f
[c1
];
580 /* FINISHME: Emit warning when division-by-zero is detected. */
581 assert(op
[0]->type
== op
[1]->type
|| op0_scalar
|| op1_scalar
);
582 for (unsigned c
= 0, c0
= 0, c1
= 0;
584 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
586 switch (op
[0]->type
->base_type
) {
588 if (op
[1]->value
.u
[c1
] == 0) {
591 data
.u
[c
] = op
[0]->value
.u
[c0
] % op
[1]->value
.u
[c1
];
595 if (op
[1]->value
.i
[c1
] == 0) {
598 data
.i
[c
] = op
[0]->value
.i
[c0
] % op
[1]->value
.i
[c1
];
601 case GLSL_TYPE_FLOAT
:
602 /* We don't use fmod because it rounds toward zero; GLSL specifies
605 data
.f
[c
] = op
[0]->value
.f
[c0
] - op
[1]->value
.f
[c1
]
606 * floorf(op
[0]->value
.f
[c0
] / op
[1]->value
.f
[c1
]);
615 case ir_binop_logic_and
:
616 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
617 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
618 data
.b
[c
] = op
[0]->value
.b
[c
] && op
[1]->value
.b
[c
];
620 case ir_binop_logic_xor
:
621 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
622 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
623 data
.b
[c
] = op
[0]->value
.b
[c
] ^ op
[1]->value
.b
[c
];
625 case ir_binop_logic_or
:
626 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
627 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
628 data
.b
[c
] = op
[0]->value
.b
[c
] || op
[1]->value
.b
[c
];
632 assert(op
[0]->type
== op
[1]->type
);
633 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
634 switch (op
[0]->type
->base_type
) {
636 data
.b
[0] = op
[0]->value
.u
[0] < op
[1]->value
.u
[0];
639 data
.b
[0] = op
[0]->value
.i
[0] < op
[1]->value
.i
[0];
641 case GLSL_TYPE_FLOAT
:
642 data
.b
[0] = op
[0]->value
.f
[0] < op
[1]->value
.f
[0];
649 case ir_binop_greater
:
650 assert(op
[0]->type
== op
[1]->type
);
651 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
652 switch (op
[0]->type
->base_type
) {
654 data
.b
[c
] = op
[0]->value
.u
[c
] > op
[1]->value
.u
[c
];
657 data
.b
[c
] = op
[0]->value
.i
[c
] > op
[1]->value
.i
[c
];
659 case GLSL_TYPE_FLOAT
:
660 data
.b
[c
] = op
[0]->value
.f
[c
] > op
[1]->value
.f
[c
];
667 case ir_binop_lequal
:
668 assert(op
[0]->type
== op
[1]->type
);
669 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
670 switch (op
[0]->type
->base_type
) {
672 data
.b
[0] = op
[0]->value
.u
[0] <= op
[1]->value
.u
[0];
675 data
.b
[0] = op
[0]->value
.i
[0] <= op
[1]->value
.i
[0];
677 case GLSL_TYPE_FLOAT
:
678 data
.b
[0] = op
[0]->value
.f
[0] <= op
[1]->value
.f
[0];
685 case ir_binop_gequal
:
686 assert(op
[0]->type
== op
[1]->type
);
687 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
688 switch (op
[0]->type
->base_type
) {
690 data
.b
[0] = op
[0]->value
.u
[0] >= op
[1]->value
.u
[0];
693 data
.b
[0] = op
[0]->value
.i
[0] >= op
[1]->value
.i
[0];
695 case GLSL_TYPE_FLOAT
:
696 data
.b
[0] = op
[0]->value
.f
[0] >= op
[1]->value
.f
[0];
704 assert(op
[0]->type
== op
[1]->type
);
705 for (unsigned c
= 0; c
< components
; c
++) {
706 switch (op
[0]->type
->base_type
) {
708 data
.b
[c
] = op
[0]->value
.u
[c
] == op
[1]->value
.u
[c
];
711 data
.b
[c
] = op
[0]->value
.i
[c
] == op
[1]->value
.i
[c
];
713 case GLSL_TYPE_FLOAT
:
714 data
.b
[c
] = op
[0]->value
.f
[c
] == op
[1]->value
.f
[c
];
717 data
.b
[c
] = op
[0]->value
.b
[c
] == op
[1]->value
.b
[c
];
724 case ir_binop_nequal
:
725 assert(op
[0]->type
== op
[1]->type
);
726 for (unsigned c
= 0; c
< components
; c
++) {
727 switch (op
[0]->type
->base_type
) {
729 data
.b
[c
] = op
[0]->value
.u
[c
] != op
[1]->value
.u
[c
];
732 data
.b
[c
] = op
[0]->value
.i
[c
] != op
[1]->value
.i
[c
];
734 case GLSL_TYPE_FLOAT
:
735 data
.b
[c
] = op
[0]->value
.f
[c
] != op
[1]->value
.f
[c
];
738 data
.b
[c
] = op
[0]->value
.b
[c
] != op
[1]->value
.b
[c
];
745 case ir_binop_all_equal
:
746 data
.b
[0] = op
[0]->has_value(op
[1]);
748 case ir_binop_any_nequal
:
749 data
.b
[0] = !op
[0]->has_value(op
[1]);
752 case ir_binop_lshift
:
753 for (unsigned c
= 0, c0
= 0, c1
= 0;
755 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
757 if (op
[0]->type
->base_type
== GLSL_TYPE_INT
&&
758 op
[1]->type
->base_type
== GLSL_TYPE_INT
) {
759 data
.i
[c
] = op
[0]->value
.i
[c0
] << op
[1]->value
.i
[c1
];
761 } else if (op
[0]->type
->base_type
== GLSL_TYPE_INT
&&
762 op
[1]->type
->base_type
== GLSL_TYPE_UINT
) {
763 data
.i
[c
] = op
[0]->value
.i
[c0
] << op
[1]->value
.u
[c1
];
765 } else if (op
[0]->type
->base_type
== GLSL_TYPE_UINT
&&
766 op
[1]->type
->base_type
== GLSL_TYPE_INT
) {
767 data
.u
[c
] = op
[0]->value
.u
[c0
] << op
[1]->value
.i
[c1
];
769 } else if (op
[0]->type
->base_type
== GLSL_TYPE_UINT
&&
770 op
[1]->type
->base_type
== GLSL_TYPE_UINT
) {
771 data
.u
[c
] = op
[0]->value
.u
[c0
] << op
[1]->value
.u
[c1
];
776 case ir_binop_rshift
:
777 for (unsigned c
= 0, c0
= 0, c1
= 0;
779 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
781 if (op
[0]->type
->base_type
== GLSL_TYPE_INT
&&
782 op
[1]->type
->base_type
== GLSL_TYPE_INT
) {
783 data
.i
[c
] = op
[0]->value
.i
[c0
] >> op
[1]->value
.i
[c1
];
785 } else if (op
[0]->type
->base_type
== GLSL_TYPE_INT
&&
786 op
[1]->type
->base_type
== GLSL_TYPE_UINT
) {
787 data
.i
[c
] = op
[0]->value
.i
[c0
] >> op
[1]->value
.u
[c1
];
789 } else if (op
[0]->type
->base_type
== GLSL_TYPE_UINT
&&
790 op
[1]->type
->base_type
== GLSL_TYPE_INT
) {
791 data
.u
[c
] = op
[0]->value
.u
[c0
] >> op
[1]->value
.i
[c1
];
793 } else if (op
[0]->type
->base_type
== GLSL_TYPE_UINT
&&
794 op
[1]->type
->base_type
== GLSL_TYPE_UINT
) {
795 data
.u
[c
] = op
[0]->value
.u
[c0
] >> op
[1]->value
.u
[c1
];
800 case ir_binop_bit_and
:
801 for (unsigned c
= 0, c0
= 0, c1
= 0;
803 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
805 switch (op
[0]->type
->base_type
) {
807 data
.i
[c
] = op
[0]->value
.i
[c0
] & op
[1]->value
.i
[c1
];
810 data
.u
[c
] = op
[0]->value
.u
[c0
] & op
[1]->value
.u
[c1
];
818 case ir_binop_bit_or
:
819 for (unsigned c
= 0, c0
= 0, c1
= 0;
821 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
823 switch (op
[0]->type
->base_type
) {
825 data
.i
[c
] = op
[0]->value
.i
[c0
] | op
[1]->value
.i
[c1
];
828 data
.u
[c
] = op
[0]->value
.u
[c0
] | op
[1]->value
.u
[c1
];
836 case ir_binop_bit_xor
:
837 for (unsigned c
= 0, c0
= 0, c1
= 0;
839 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
841 switch (op
[0]->type
->base_type
) {
843 data
.i
[c
] = op
[0]->value
.i
[c0
] ^ op
[1]->value
.i
[c1
];
846 data
.u
[c
] = op
[0]->value
.u
[c0
] ^ op
[1]->value
.u
[c1
];
854 case ir_quadop_vector
:
855 for (unsigned c
= 0; c
< this->type
->vector_elements
; c
++) {
856 switch (this->type
->base_type
) {
858 data
.i
[c
] = op
[c
]->value
.i
[0];
861 data
.u
[c
] = op
[c
]->value
.u
[0];
863 case GLSL_TYPE_FLOAT
:
864 data
.f
[c
] = op
[c
]->value
.f
[0];
873 /* FINISHME: Should handle all expression types. */
877 return new(ctx
) ir_constant(this->type
, &data
);
882 ir_texture::constant_expression_value()
884 /* texture lookups aren't constant expressions */
890 ir_swizzle::constant_expression_value()
892 ir_constant
*v
= this->val
->constant_expression_value();
895 ir_constant_data data
= { { 0 } };
897 const unsigned swiz_idx
[4] = {
898 this->mask
.x
, this->mask
.y
, this->mask
.z
, this->mask
.w
901 for (unsigned i
= 0; i
< this->mask
.num_components
; i
++) {
902 switch (v
->type
->base_type
) {
904 case GLSL_TYPE_INT
: data
.u
[i
] = v
->value
.u
[swiz_idx
[i
]]; break;
905 case GLSL_TYPE_FLOAT
: data
.f
[i
] = v
->value
.f
[swiz_idx
[i
]]; break;
906 case GLSL_TYPE_BOOL
: data
.b
[i
] = v
->value
.b
[swiz_idx
[i
]]; break;
907 default: assert(!"Should not get here."); break;
911 void *ctx
= ralloc_parent(this);
912 return new(ctx
) ir_constant(this->type
, &data
);
919 ir_dereference_variable::constant_expression_value()
921 /* This may occur during compile and var->type is glsl_type::error_type */
925 /* The constant_value of a uniform variable is its initializer,
926 * not the lifetime constant value of the uniform.
928 if (var
->mode
== ir_var_uniform
)
931 if (!var
->constant_value
)
934 return var
->constant_value
->clone(ralloc_parent(var
), NULL
);
939 ir_dereference_array::constant_expression_value()
941 ir_constant
*array
= this->array
->constant_expression_value();
942 ir_constant
*idx
= this->array_index
->constant_expression_value();
944 if ((array
!= NULL
) && (idx
!= NULL
)) {
945 void *ctx
= ralloc_parent(this);
946 if (array
->type
->is_matrix()) {
947 /* Array access of a matrix results in a vector.
949 const unsigned column
= idx
->value
.u
[0];
951 const glsl_type
*const column_type
= array
->type
->column_type();
953 /* Offset in the constant matrix to the first element of the column
956 const unsigned mat_idx
= column
* column_type
->vector_elements
;
958 ir_constant_data data
= { { 0 } };
960 switch (column_type
->base_type
) {
963 for (unsigned i
= 0; i
< column_type
->vector_elements
; i
++)
964 data
.u
[i
] = array
->value
.u
[mat_idx
+ i
];
968 case GLSL_TYPE_FLOAT
:
969 for (unsigned i
= 0; i
< column_type
->vector_elements
; i
++)
970 data
.f
[i
] = array
->value
.f
[mat_idx
+ i
];
975 assert(!"Should not get here.");
979 return new(ctx
) ir_constant(column_type
, &data
);
980 } else if (array
->type
->is_vector()) {
981 const unsigned component
= idx
->value
.u
[0];
983 return new(ctx
) ir_constant(array
, component
);
985 const unsigned index
= idx
->value
.u
[0];
986 return array
->get_array_element(index
)->clone(ctx
, NULL
);
994 ir_dereference_record::constant_expression_value()
996 ir_constant
*v
= this->record
->constant_expression_value();
998 return (v
!= NULL
) ? v
->get_record_field(this->field
) : NULL
;
1003 ir_assignment::constant_expression_value()
1005 /* FINISHME: Handle CEs involving assignment (return RHS) */
1011 ir_constant::constant_expression_value()
1018 ir_call::constant_expression_value()
1020 if (this->type
== glsl_type::error_type
)
1023 /* From the GLSL 1.20 spec, page 23:
1024 * "Function calls to user-defined functions (non-built-in functions)
1025 * cannot be used to form constant expressions."
1027 if (!this->callee
->is_builtin
)
1030 unsigned num_parameters
= 0;
1032 /* Check if all parameters are constant */
1034 foreach_list(n
, &this->actual_parameters
) {
1035 ir_constant
*constant
= ((ir_rvalue
*) n
)->constant_expression_value();
1036 if (constant
== NULL
)
1039 op
[num_parameters
] = constant
;
1041 assert(num_parameters
< 3);
1045 /* Individual cases below can either:
1046 * - Assign "expr" a new ir_expression to evaluate (for basic opcodes)
1047 * - Fill "data" with appopriate constant data
1048 * - Return an ir_constant directly.
1050 void *mem_ctx
= ralloc_parent(this);
1051 ir_expression
*expr
= NULL
;
1053 ir_constant_data data
;
1054 memset(&data
, 0, sizeof(data
));
1056 const char *callee
= this->callee_name();
1057 if (strcmp(callee
, "abs") == 0) {
1058 expr
= new(mem_ctx
) ir_expression(ir_unop_abs
, type
, op
[0], NULL
);
1059 } else if (strcmp(callee
, "all") == 0) {
1060 assert(op
[0]->type
->is_boolean());
1061 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
1062 if (!op
[0]->value
.b
[c
])
1063 return new(mem_ctx
) ir_constant(false);
1065 return new(mem_ctx
) ir_constant(true);
1066 } else if (strcmp(callee
, "any") == 0) {
1067 assert(op
[0]->type
->is_boolean());
1068 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
1069 if (op
[0]->value
.b
[c
])
1070 return new(mem_ctx
) ir_constant(true);
1072 return new(mem_ctx
) ir_constant(false);
1073 } else if (strcmp(callee
, "acos") == 0) {
1074 assert(op
[0]->type
->is_float());
1075 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1076 data
.f
[c
] = acosf(op
[0]->value
.f
[c
]);
1077 } else if (strcmp(callee
, "acosh") == 0) {
1078 assert(op
[0]->type
->is_float());
1079 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1080 data
.f
[c
] = acoshf(op
[0]->value
.f
[c
]);
1081 } else if (strcmp(callee
, "asin") == 0) {
1082 assert(op
[0]->type
->is_float());
1083 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1084 data
.f
[c
] = asinf(op
[0]->value
.f
[c
]);
1085 } else if (strcmp(callee
, "asinh") == 0) {
1086 assert(op
[0]->type
->is_float());
1087 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1088 data
.f
[c
] = asinhf(op
[0]->value
.f
[c
]);
1089 } else if (strcmp(callee
, "atan") == 0) {
1090 assert(op
[0]->type
->is_float());
1091 if (num_parameters
== 2) {
1092 assert(op
[1]->type
->is_float());
1093 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1094 data
.f
[c
] = atan2f(op
[0]->value
.f
[c
], op
[1]->value
.f
[c
]);
1096 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1097 data
.f
[c
] = atanf(op
[0]->value
.f
[c
]);
1099 } else if (strcmp(callee
, "atanh") == 0) {
1100 assert(op
[0]->type
->is_float());
1101 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1102 data
.f
[c
] = atanhf(op
[0]->value
.f
[c
]);
1103 } else if (strcmp(callee
, "dFdx") == 0 || strcmp(callee
, "dFdy") == 0) {
1104 return ir_constant::zero(mem_ctx
, this->type
);
1105 } else if (strcmp(callee
, "ceil") == 0) {
1106 expr
= new(mem_ctx
) ir_expression(ir_unop_ceil
, type
, op
[0], NULL
);
1107 } else if (strcmp(callee
, "clamp") == 0) {
1108 assert(num_parameters
== 3);
1109 unsigned c1_inc
= op
[1]->type
->is_scalar() ? 0 : 1;
1110 unsigned c2_inc
= op
[2]->type
->is_scalar() ? 0 : 1;
1111 for (unsigned c
= 0, c1
= 0, c2
= 0;
1112 c
< op
[0]->type
->components();
1113 c1
+= c1_inc
, c2
+= c2_inc
, c
++) {
1115 switch (op
[0]->type
->base_type
) {
1116 case GLSL_TYPE_UINT
:
1117 data
.u
[c
] = CLAMP(op
[0]->value
.u
[c
], op
[1]->value
.u
[c1
],
1118 op
[2]->value
.u
[c2
]);
1121 data
.i
[c
] = CLAMP(op
[0]->value
.i
[c
], op
[1]->value
.i
[c1
],
1122 op
[2]->value
.i
[c2
]);
1124 case GLSL_TYPE_FLOAT
:
1125 data
.f
[c
] = CLAMP(op
[0]->value
.f
[c
], op
[1]->value
.f
[c1
],
1126 op
[2]->value
.f
[c2
]);
1129 assert(!"Should not get here.");
1132 } else if (strcmp(callee
, "cos") == 0) {
1133 expr
= new(mem_ctx
) ir_expression(ir_unop_cos
, type
, op
[0], NULL
);
1134 } else if (strcmp(callee
, "cosh") == 0) {
1135 assert(op
[0]->type
->is_float());
1136 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1137 data
.f
[c
] = coshf(op
[0]->value
.f
[c
]);
1138 } else if (strcmp(callee
, "cross") == 0) {
1139 assert(op
[0]->type
== glsl_type::vec3_type
);
1140 assert(op
[1]->type
== glsl_type::vec3_type
);
1141 data
.f
[0] = (op
[0]->value
.f
[1] * op
[1]->value
.f
[2] -
1142 op
[1]->value
.f
[1] * op
[0]->value
.f
[2]);
1143 data
.f
[1] = (op
[0]->value
.f
[2] * op
[1]->value
.f
[0] -
1144 op
[1]->value
.f
[2] * op
[0]->value
.f
[0]);
1145 data
.f
[2] = (op
[0]->value
.f
[0] * op
[1]->value
.f
[1] -
1146 op
[1]->value
.f
[0] * op
[0]->value
.f
[1]);
1147 } else if (strcmp(callee
, "degrees") == 0) {
1148 assert(op
[0]->type
->is_float());
1149 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1150 data
.f
[c
] = 180.0F
/ M_PI
* op
[0]->value
.f
[c
];
1151 } else if (strcmp(callee
, "distance") == 0) {
1152 assert(op
[0]->type
->is_float() && op
[1]->type
->is_float());
1153 float length_squared
= 0.0;
1154 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
1155 float t
= op
[0]->value
.f
[c
] - op
[1]->value
.f
[c
];
1156 length_squared
+= t
* t
;
1158 return new(mem_ctx
) ir_constant(sqrtf(length_squared
));
1159 } else if (strcmp(callee
, "dot") == 0) {
1160 return new(mem_ctx
) ir_constant(dot(op
[0], op
[1]));
1161 } else if (strcmp(callee
, "equal") == 0) {
1162 assert(op
[0]->type
->is_vector() && op
[1] && op
[1]->type
->is_vector());
1163 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
1164 switch (op
[0]->type
->base_type
) {
1165 case GLSL_TYPE_UINT
:
1166 data
.b
[c
] = op
[0]->value
.u
[c
] == op
[1]->value
.u
[c
];
1169 data
.b
[c
] = op
[0]->value
.i
[c
] == op
[1]->value
.i
[c
];
1171 case GLSL_TYPE_FLOAT
:
1172 data
.b
[c
] = op
[0]->value
.f
[c
] == op
[1]->value
.f
[c
];
1174 case GLSL_TYPE_BOOL
:
1175 data
.b
[c
] = op
[0]->value
.b
[c
] == op
[1]->value
.b
[c
];
1178 assert(!"Should not get here.");
1181 } else if (strcmp(callee
, "exp") == 0) {
1182 expr
= new(mem_ctx
) ir_expression(ir_unop_exp
, type
, op
[0], NULL
);
1183 } else if (strcmp(callee
, "exp2") == 0) {
1184 expr
= new(mem_ctx
) ir_expression(ir_unop_exp2
, type
, op
[0], NULL
);
1185 } else if (strcmp(callee
, "faceforward") == 0) {
1186 if (dot(op
[2], op
[1]) < 0)
1188 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1189 data
.f
[c
] = -op
[0]->value
.f
[c
];
1190 } else if (strcmp(callee
, "floor") == 0) {
1191 expr
= new(mem_ctx
) ir_expression(ir_unop_floor
, type
, op
[0], NULL
);
1192 } else if (strcmp(callee
, "fract") == 0) {
1193 expr
= new(mem_ctx
) ir_expression(ir_unop_fract
, type
, op
[0], NULL
);
1194 } else if (strcmp(callee
, "fwidth") == 0) {
1195 return ir_constant::zero(mem_ctx
, this->type
);
1196 } else if (strcmp(callee
, "greaterThan") == 0) {
1197 assert(op
[0]->type
->is_vector() && op
[1] && op
[1]->type
->is_vector());
1198 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
1199 switch (op
[0]->type
->base_type
) {
1200 case GLSL_TYPE_UINT
:
1201 data
.b
[c
] = op
[0]->value
.u
[c
] > op
[1]->value
.u
[c
];
1204 data
.b
[c
] = op
[0]->value
.i
[c
] > op
[1]->value
.i
[c
];
1206 case GLSL_TYPE_FLOAT
:
1207 data
.b
[c
] = op
[0]->value
.f
[c
] > op
[1]->value
.f
[c
];
1210 assert(!"Should not get here.");
1213 } else if (strcmp(callee
, "greaterThanEqual") == 0) {
1214 assert(op
[0]->type
->is_vector() && op
[1] && op
[1]->type
->is_vector());
1215 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
1216 switch (op
[0]->type
->base_type
) {
1217 case GLSL_TYPE_UINT
:
1218 data
.b
[c
] = op
[0]->value
.u
[c
] >= op
[1]->value
.u
[c
];
1221 data
.b
[c
] = op
[0]->value
.i
[c
] >= op
[1]->value
.i
[c
];
1223 case GLSL_TYPE_FLOAT
:
1224 data
.b
[c
] = op
[0]->value
.f
[c
] >= op
[1]->value
.f
[c
];
1227 assert(!"Should not get here.");
1230 } else if (strcmp(callee
, "inversesqrt") == 0) {
1231 expr
= new(mem_ctx
) ir_expression(ir_unop_rsq
, type
, op
[0], NULL
);
1232 } else if (strcmp(callee
, "length") == 0) {
1233 return new(mem_ctx
) ir_constant(sqrtf(dot(op
[0], op
[0])));
1234 } else if (strcmp(callee
, "lessThan") == 0) {
1235 assert(op
[0]->type
->is_vector() && op
[1] && op
[1]->type
->is_vector());
1236 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
1237 switch (op
[0]->type
->base_type
) {
1238 case GLSL_TYPE_UINT
:
1239 data
.b
[c
] = op
[0]->value
.u
[c
] < op
[1]->value
.u
[c
];
1242 data
.b
[c
] = op
[0]->value
.i
[c
] < op
[1]->value
.i
[c
];
1244 case GLSL_TYPE_FLOAT
:
1245 data
.b
[c
] = op
[0]->value
.f
[c
] < op
[1]->value
.f
[c
];
1248 assert(!"Should not get here.");
1251 } else if (strcmp(callee
, "lessThanEqual") == 0) {
1252 assert(op
[0]->type
->is_vector() && op
[1] && op
[1]->type
->is_vector());
1253 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
1254 switch (op
[0]->type
->base_type
) {
1255 case GLSL_TYPE_UINT
:
1256 data
.b
[c
] = op
[0]->value
.u
[c
] <= op
[1]->value
.u
[c
];
1259 data
.b
[c
] = op
[0]->value
.i
[c
] <= op
[1]->value
.i
[c
];
1261 case GLSL_TYPE_FLOAT
:
1262 data
.b
[c
] = op
[0]->value
.f
[c
] <= op
[1]->value
.f
[c
];
1265 assert(!"Should not get here.");
1268 } else if (strcmp(callee
, "log") == 0) {
1269 expr
= new(mem_ctx
) ir_expression(ir_unop_log
, type
, op
[0], NULL
);
1270 } else if (strcmp(callee
, "log2") == 0) {
1271 expr
= new(mem_ctx
) ir_expression(ir_unop_log2
, type
, op
[0], NULL
);
1272 } else if (strcmp(callee
, "matrixCompMult") == 0) {
1273 assert(op
[0]->type
->is_float() && op
[1]->type
->is_float());
1274 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1275 data
.f
[c
] = op
[0]->value
.f
[c
] * op
[1]->value
.f
[c
];
1276 } else if (strcmp(callee
, "max") == 0) {
1277 expr
= new(mem_ctx
) ir_expression(ir_binop_max
, type
, op
[0], op
[1]);
1278 } else if (strcmp(callee
, "min") == 0) {
1279 expr
= new(mem_ctx
) ir_expression(ir_binop_min
, type
, op
[0], op
[1]);
1280 } else if (strcmp(callee
, "mix") == 0) {
1281 assert(op
[0]->type
->is_float() && op
[1]->type
->is_float());
1282 if (op
[2]->type
->is_float()) {
1283 unsigned c2_inc
= op
[2]->type
->is_scalar() ? 0 : 1;
1284 unsigned components
= op
[0]->type
->components();
1285 for (unsigned c
= 0, c2
= 0; c
< components
; c2
+= c2_inc
, c
++) {
1286 data
.f
[c
] = op
[0]->value
.f
[c
] * (1 - op
[2]->value
.f
[c2
]) +
1287 op
[1]->value
.f
[c
] * op
[2]->value
.f
[c2
];
1290 assert(op
[2]->type
->is_boolean());
1291 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1292 data
.f
[c
] = op
[op
[2]->value
.b
[c
] ? 1 : 0]->value
.f
[c
];
1294 } else if (strcmp(callee
, "mod") == 0) {
1295 expr
= new(mem_ctx
) ir_expression(ir_binop_mod
, type
, op
[0], op
[1]);
1296 } else if (strcmp(callee
, "normalize") == 0) {
1297 assert(op
[0]->type
->is_float());
1298 float length
= sqrtf(dot(op
[0], op
[0]));
1301 return ir_constant::zero(mem_ctx
, this->type
);
1303 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1304 data
.f
[c
] = op
[0]->value
.f
[c
] / length
;
1305 } else if (strcmp(callee
, "not") == 0) {
1306 expr
= new(mem_ctx
) ir_expression(ir_unop_logic_not
, type
, op
[0], NULL
);
1307 } else if (strcmp(callee
, "notEqual") == 0) {
1308 assert(op
[0]->type
->is_vector() && op
[1] && op
[1]->type
->is_vector());
1309 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++) {
1310 switch (op
[0]->type
->base_type
) {
1311 case GLSL_TYPE_UINT
:
1312 data
.b
[c
] = op
[0]->value
.u
[c
] != op
[1]->value
.u
[c
];
1315 data
.b
[c
] = op
[0]->value
.i
[c
] != op
[1]->value
.i
[c
];
1317 case GLSL_TYPE_FLOAT
:
1318 data
.b
[c
] = op
[0]->value
.f
[c
] != op
[1]->value
.f
[c
];
1320 case GLSL_TYPE_BOOL
:
1321 data
.b
[c
] = op
[0]->value
.b
[c
] != op
[1]->value
.b
[c
];
1324 assert(!"Should not get here.");
1327 } else if (strcmp(callee
, "outerProduct") == 0) {
1328 assert(op
[0]->type
->is_vector() && op
[1]->type
->is_vector());
1329 const unsigned m
= op
[0]->type
->vector_elements
;
1330 const unsigned n
= op
[1]->type
->vector_elements
;
1331 for (unsigned j
= 0; j
< n
; j
++) {
1332 for (unsigned i
= 0; i
< m
; i
++) {
1333 data
.f
[i
+m
*j
] = op
[0]->value
.f
[i
] * op
[1]->value
.f
[j
];
1336 } else if (strcmp(callee
, "pow") == 0) {
1337 expr
= new(mem_ctx
) ir_expression(ir_binop_pow
, type
, op
[0], op
[1]);
1338 } else if (strcmp(callee
, "radians") == 0) {
1339 assert(op
[0]->type
->is_float());
1340 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1341 data
.f
[c
] = M_PI
/ 180.0F
* op
[0]->value
.f
[c
];
1342 } else if (strcmp(callee
, "reflect") == 0) {
1343 assert(op
[0]->type
->is_float());
1344 float dot_NI
= dot(op
[1], op
[0]);
1345 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1346 data
.f
[c
] = op
[0]->value
.f
[c
] - 2 * dot_NI
* op
[1]->value
.f
[c
];
1347 } else if (strcmp(callee
, "refract") == 0) {
1348 const float eta
= op
[2]->value
.f
[0];
1349 const float dot_NI
= dot(op
[1], op
[0]);
1350 const float k
= 1.0F
- eta
* eta
* (1.0F
- dot_NI
* dot_NI
);
1352 return ir_constant::zero(mem_ctx
, this->type
);
1354 for (unsigned c
= 0; c
< type
->components(); c
++) {
1355 data
.f
[c
] = eta
* op
[0]->value
.f
[c
] - (eta
* dot_NI
+ sqrtf(k
))
1356 * op
[1]->value
.f
[c
];
1359 } else if (strcmp(callee
, "round") == 0 ||
1360 strcmp(callee
, "roundEven") == 0) {
1361 expr
= new(mem_ctx
) ir_expression(ir_unop_round_even
, op
[0]);
1362 } else if (strcmp(callee
, "sign") == 0) {
1363 expr
= new(mem_ctx
) ir_expression(ir_unop_sign
, type
, op
[0], NULL
);
1364 } else if (strcmp(callee
, "sin") == 0) {
1365 expr
= new(mem_ctx
) ir_expression(ir_unop_sin
, type
, op
[0], NULL
);
1366 } else if (strcmp(callee
, "sinh") == 0) {
1367 assert(op
[0]->type
->is_float());
1368 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1369 data
.f
[c
] = sinhf(op
[0]->value
.f
[c
]);
1370 } else if (strcmp(callee
, "smoothstep") == 0) {
1371 assert(num_parameters
== 3);
1372 assert(op
[1]->type
== op
[0]->type
);
1373 unsigned edge_inc
= op
[0]->type
->is_scalar() ? 0 : 1;
1374 for (unsigned c
= 0, e
= 0; c
< type
->components(); e
+= edge_inc
, c
++) {
1375 const float edge0
= op
[0]->value
.f
[e
];
1376 const float edge1
= op
[1]->value
.f
[e
];
1377 if (edge0
== edge1
) {
1378 data
.f
[c
] = 0.0; /* Avoid a crash - results are undefined anyway */
1380 const float numerator
= op
[2]->value
.f
[c
] - edge0
;
1381 const float denominator
= edge1
- edge0
;
1382 const float t
= CLAMP(numerator
/denominator
, 0, 1);
1383 data
.f
[c
] = t
* t
* (3 - 2 * t
);
1386 } else if (strcmp(callee
, "sqrt") == 0) {
1387 expr
= new(mem_ctx
) ir_expression(ir_unop_sqrt
, type
, op
[0], NULL
);
1388 } else if (strcmp(callee
, "step") == 0) {
1389 assert(op
[0]->type
->is_float() && op
[1]->type
->is_float());
1390 /* op[0] (edge) may be either a scalar or a vector */
1391 const unsigned c0_inc
= op
[0]->type
->is_scalar() ? 0 : 1;
1392 for (unsigned c
= 0, c0
= 0; c
< type
->components(); c0
+= c0_inc
, c
++)
1393 data
.f
[c
] = (op
[1]->value
.f
[c
] < op
[0]->value
.f
[c0
]) ? 0.0F
: 1.0F
;
1394 } else if (strcmp(callee
, "tan") == 0) {
1395 assert(op
[0]->type
->is_float());
1396 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1397 data
.f
[c
] = tanf(op
[0]->value
.f
[c
]);
1398 } else if (strcmp(callee
, "tanh") == 0) {
1399 assert(op
[0]->type
->is_float());
1400 for (unsigned c
= 0; c
< op
[0]->type
->components(); c
++)
1401 data
.f
[c
] = tanhf(op
[0]->value
.f
[c
]);
1402 } else if (strcmp(callee
, "transpose") == 0) {
1403 assert(op
[0]->type
->is_matrix());
1404 const unsigned n
= op
[0]->type
->vector_elements
;
1405 const unsigned m
= op
[0]->type
->matrix_columns
;
1406 for (unsigned j
= 0; j
< m
; j
++) {
1407 for (unsigned i
= 0; i
< n
; i
++) {
1408 data
.f
[m
*i
+j
] += op
[0]->value
.f
[i
+n
*j
];
1411 } else if (strcmp(callee
, "trunc") == 0) {
1412 expr
= new(mem_ctx
) ir_expression(ir_unop_trunc
, op
[0]);
1414 /* Unsupported builtin - some are not allowed in constant expressions. */
1419 return expr
->constant_expression_value();
1421 return new(mem_ctx
) ir_constant(this->type
, &data
);