Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Copyright © 2010 Intel Corporation |
||
3 | * |
||
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: |
||
10 | * |
||
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 |
||
13 | * Software. |
||
14 | * |
||
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. |
||
22 | */ |
||
23 | |||
24 | #include "glsl_symbol_table.h" |
||
25 | #include "ast.h" |
||
26 | #include "glsl_types.h" |
||
27 | #include "ir.h" |
||
28 | #include "main/core.h" /* for MIN2 */ |
||
29 | |||
30 | static ir_rvalue * |
||
31 | convert_component(ir_rvalue *src, const glsl_type *desired_type); |
||
32 | |||
33 | bool |
||
34 | apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, |
||
35 | struct _mesa_glsl_parse_state *state); |
||
36 | |||
37 | static unsigned |
||
38 | process_parameters(exec_list *instructions, exec_list *actual_parameters, |
||
39 | exec_list *parameters, |
||
40 | struct _mesa_glsl_parse_state *state) |
||
41 | { |
||
42 | unsigned count = 0; |
||
43 | |||
44 | foreach_list (n, parameters) { |
||
45 | ast_node *const ast = exec_node_data(ast_node, n, link); |
||
46 | ir_rvalue *result = ast->hir(instructions, state); |
||
47 | |||
48 | ir_constant *const constant = result->constant_expression_value(); |
||
49 | if (constant != NULL) |
||
50 | result = constant; |
||
51 | |||
52 | actual_parameters->push_tail(result); |
||
53 | count++; |
||
54 | } |
||
55 | |||
56 | return count; |
||
57 | } |
||
58 | |||
59 | |||
60 | /** |
||
61 | * Generate a source prototype for a function signature |
||
62 | * |
||
63 | * \param return_type Return type of the function. May be \c NULL. |
||
64 | * \param name Name of the function. |
||
65 | * \param parameters List of \c ir_instruction nodes representing the |
||
66 | * parameter list for the function. This may be either a |
||
67 | * formal (\c ir_variable) or actual (\c ir_rvalue) |
||
68 | * parameter list. Only the type is used. |
||
69 | * |
||
70 | * \return |
||
71 | * A ralloced string representing the prototype of the function. |
||
72 | */ |
||
73 | char * |
||
74 | prototype_string(const glsl_type *return_type, const char *name, |
||
75 | exec_list *parameters) |
||
76 | { |
||
77 | char *str = NULL; |
||
78 | |||
79 | if (return_type != NULL) |
||
80 | str = ralloc_asprintf(NULL, "%s ", return_type->name); |
||
81 | |||
82 | ralloc_asprintf_append(&str, "%s(", name); |
||
83 | |||
84 | const char *comma = ""; |
||
85 | foreach_list(node, parameters) { |
||
86 | const ir_variable *const param = (ir_variable *) node; |
||
87 | |||
88 | ralloc_asprintf_append(&str, "%s%s", comma, param->type->name); |
||
89 | comma = ", "; |
||
90 | } |
||
91 | |||
92 | ralloc_strcat(&str, ")"); |
||
93 | return str; |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * Verify that 'out' and 'inout' actual parameters are lvalues. Also, verify |
||
98 | * that 'const_in' formal parameters (an extension in our IR) correspond to |
||
99 | * ir_constant actual parameters. |
||
100 | */ |
||
101 | static bool |
||
102 | verify_parameter_modes(_mesa_glsl_parse_state *state, |
||
103 | ir_function_signature *sig, |
||
104 | exec_list &actual_ir_parameters, |
||
105 | exec_list &actual_ast_parameters) |
||
106 | { |
||
107 | exec_node *actual_ir_node = actual_ir_parameters.head; |
||
108 | exec_node *actual_ast_node = actual_ast_parameters.head; |
||
109 | |||
110 | foreach_list(formal_node, &sig->parameters) { |
||
111 | /* The lists must be the same length. */ |
||
112 | assert(!actual_ir_node->is_tail_sentinel()); |
||
113 | assert(!actual_ast_node->is_tail_sentinel()); |
||
114 | |||
115 | const ir_variable *const formal = (ir_variable *) formal_node; |
||
116 | const ir_rvalue *const actual = (ir_rvalue *) actual_ir_node; |
||
117 | const ast_expression *const actual_ast = |
||
118 | exec_node_data(ast_expression, actual_ast_node, link); |
||
119 | |||
120 | /* FIXME: 'loc' is incorrect (as of 2011-01-21). It is always |
||
121 | * FIXME: 0:0(0). |
||
122 | */ |
||
123 | YYLTYPE loc = actual_ast->get_location(); |
||
124 | |||
125 | /* Verify that 'const_in' parameters are ir_constants. */ |
||
126 | if (formal->mode == ir_var_const_in && |
||
127 | actual->ir_type != ir_type_constant) { |
||
128 | _mesa_glsl_error(&loc, state, |
||
129 | "parameter `in %s' must be a constant expression", |
||
130 | formal->name); |
||
131 | return false; |
||
132 | } |
||
133 | |||
134 | /* Verify that 'out' and 'inout' actual parameters are lvalues. */ |
||
135 | if (formal->mode == ir_var_function_out |
||
136 | || formal->mode == ir_var_function_inout) { |
||
137 | const char *mode = NULL; |
||
138 | switch (formal->mode) { |
||
139 | case ir_var_function_out: mode = "out"; break; |
||
140 | case ir_var_function_inout: mode = "inout"; break; |
||
141 | default: assert(false); break; |
||
142 | } |
||
143 | |||
144 | /* This AST-based check catches errors like f(i++). The IR-based |
||
145 | * is_lvalue() is insufficient because the actual parameter at the |
||
146 | * IR-level is just a temporary value, which is an l-value. |
||
147 | */ |
||
148 | if (actual_ast->non_lvalue_description != NULL) { |
||
149 | _mesa_glsl_error(&loc, state, |
||
150 | "function parameter '%s %s' references a %s", |
||
151 | mode, formal->name, |
||
152 | actual_ast->non_lvalue_description); |
||
153 | return false; |
||
154 | } |
||
155 | |||
156 | ir_variable *var = actual->variable_referenced(); |
||
157 | if (var) |
||
158 | var->assigned = true; |
||
159 | |||
160 | if (var && var->read_only) { |
||
161 | _mesa_glsl_error(&loc, state, |
||
162 | "function parameter '%s %s' references the " |
||
163 | "read-only variable '%s'", |
||
164 | mode, formal->name, |
||
165 | actual->variable_referenced()->name); |
||
166 | return false; |
||
167 | } else if (!actual->is_lvalue()) { |
||
168 | /* Even though ir_binop_vector_extract is not an l-value, let it |
||
169 | * slop through. generate_call will handle it correctly. |
||
170 | */ |
||
171 | ir_expression *const expr = ((ir_rvalue *) actual)->as_expression(); |
||
172 | if (expr == NULL |
||
173 | || expr->operation != ir_binop_vector_extract |
||
174 | || !expr->operands[0]->is_lvalue()) { |
||
175 | _mesa_glsl_error(&loc, state, |
||
176 | "function parameter '%s %s' is not an lvalue", |
||
177 | mode, formal->name); |
||
178 | return false; |
||
179 | } |
||
180 | } |
||
181 | } |
||
182 | |||
183 | actual_ir_node = actual_ir_node->next; |
||
184 | actual_ast_node = actual_ast_node->next; |
||
185 | } |
||
186 | return true; |
||
187 | } |
||
188 | |||
189 | static void |
||
190 | fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type, |
||
191 | exec_list *before_instructions, exec_list *after_instructions, |
||
192 | bool parameter_is_inout) |
||
193 | { |
||
194 | ir_expression *const expr = actual->as_expression(); |
||
195 | |||
196 | /* If the types match exactly and the parameter is not a vector-extract, |
||
197 | * nothing needs to be done to fix the parameter. |
||
198 | */ |
||
199 | if (formal_type == actual->type |
||
200 | && (expr == NULL || expr->operation != ir_binop_vector_extract)) |
||
201 | return; |
||
202 | |||
203 | /* To convert an out parameter, we need to create a temporary variable to |
||
204 | * hold the value before conversion, and then perform the conversion after |
||
205 | * the function call returns. |
||
206 | * |
||
207 | * This has the effect of transforming code like this: |
||
208 | * |
||
209 | * void f(out int x); |
||
210 | * float value; |
||
211 | * f(value); |
||
212 | * |
||
213 | * Into IR that's equivalent to this: |
||
214 | * |
||
215 | * void f(out int x); |
||
216 | * float value; |
||
217 | * int out_parameter_conversion; |
||
218 | * f(out_parameter_conversion); |
||
219 | * value = float(out_parameter_conversion); |
||
220 | * |
||
221 | * If the parameter is an ir_expression of ir_binop_vector_extract, |
||
222 | * additional conversion is needed in the post-call re-write. |
||
223 | */ |
||
224 | ir_variable *tmp = |
||
225 | new(mem_ctx) ir_variable(formal_type, "inout_tmp", ir_var_temporary); |
||
226 | |||
227 | before_instructions->push_tail(tmp); |
||
228 | |||
229 | /* If the parameter is an inout parameter, copy the value of the actual |
||
230 | * parameter to the new temporary. Note that no type conversion is allowed |
||
231 | * here because inout parameters must match types exactly. |
||
232 | */ |
||
233 | if (parameter_is_inout) { |
||
234 | /* Inout parameters should never require conversion, since that would |
||
235 | * require an implicit conversion to exist both to and from the formal |
||
236 | * parameter type, and there are no bidirectional implicit conversions. |
||
237 | */ |
||
238 | assert (actual->type == formal_type); |
||
239 | |||
240 | ir_dereference_variable *const deref_tmp_1 = |
||
241 | new(mem_ctx) ir_dereference_variable(tmp); |
||
242 | ir_assignment *const assignment = |
||
243 | new(mem_ctx) ir_assignment(deref_tmp_1, actual); |
||
244 | before_instructions->push_tail(assignment); |
||
245 | } |
||
246 | |||
247 | /* Replace the parameter in the call with a dereference of the new |
||
248 | * temporary. |
||
249 | */ |
||
250 | ir_dereference_variable *const deref_tmp_2 = |
||
251 | new(mem_ctx) ir_dereference_variable(tmp); |
||
252 | actual->replace_with(deref_tmp_2); |
||
253 | |||
254 | |||
255 | /* Copy the temporary variable to the actual parameter with optional |
||
256 | * type conversion applied. |
||
257 | */ |
||
258 | ir_rvalue *rhs = new(mem_ctx) ir_dereference_variable(tmp); |
||
259 | if (actual->type != formal_type) |
||
260 | rhs = convert_component(rhs, actual->type); |
||
261 | |||
262 | ir_rvalue *lhs = actual; |
||
263 | if (expr != NULL && expr->operation == ir_binop_vector_extract) { |
||
264 | rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert, |
||
265 | expr->operands[0]->type, |
||
266 | expr->operands[0]->clone(mem_ctx, NULL), |
||
267 | rhs, |
||
268 | expr->operands[1]->clone(mem_ctx, NULL)); |
||
269 | lhs = expr->operands[0]->clone(mem_ctx, NULL); |
||
270 | } |
||
271 | |||
272 | ir_assignment *const assignment_2 = new(mem_ctx) ir_assignment(lhs, rhs); |
||
273 | after_instructions->push_tail(assignment_2); |
||
274 | } |
||
275 | |||
276 | /** |
||
277 | * If a function call is generated, \c call_ir will point to it on exit. |
||
278 | * Otherwise \c call_ir will be set to \c NULL. |
||
279 | */ |
||
280 | static ir_rvalue * |
||
281 | generate_call(exec_list *instructions, ir_function_signature *sig, |
||
282 | exec_list *actual_parameters, |
||
283 | ir_call **call_ir, |
||
284 | struct _mesa_glsl_parse_state *state) |
||
285 | { |
||
286 | void *ctx = state; |
||
287 | exec_list post_call_conversions; |
||
288 | |||
289 | *call_ir = NULL; |
||
290 | |||
291 | /* Perform implicit conversion of arguments. For out parameters, we need |
||
292 | * to place them in a temporary variable and do the conversion after the |
||
293 | * call takes place. Since we haven't emitted the call yet, we'll place |
||
294 | * the post-call conversions in a temporary exec_list, and emit them later. |
||
295 | */ |
||
296 | exec_list_iterator actual_iter = actual_parameters->iterator(); |
||
297 | exec_list_iterator formal_iter = sig->parameters.iterator(); |
||
298 | |||
299 | while (actual_iter.has_next()) { |
||
300 | ir_rvalue *actual = (ir_rvalue *) actual_iter.get(); |
||
301 | ir_variable *formal = (ir_variable *) formal_iter.get(); |
||
302 | |||
303 | assert(actual != NULL); |
||
304 | assert(formal != NULL); |
||
305 | |||
306 | if (formal->type->is_numeric() || formal->type->is_boolean()) { |
||
307 | switch (formal->mode) { |
||
308 | case ir_var_const_in: |
||
309 | case ir_var_function_in: { |
||
310 | ir_rvalue *converted |
||
311 | = convert_component(actual, formal->type); |
||
312 | actual->replace_with(converted); |
||
313 | break; |
||
314 | } |
||
315 | case ir_var_function_out: |
||
316 | case ir_var_function_inout: |
||
317 | fix_parameter(ctx, actual, formal->type, |
||
318 | instructions, &post_call_conversions, |
||
319 | formal->mode == ir_var_function_inout); |
||
320 | break; |
||
321 | default: |
||
322 | assert (!"Illegal formal parameter mode"); |
||
323 | break; |
||
324 | } |
||
325 | } |
||
326 | |||
327 | actual_iter.next(); |
||
328 | formal_iter.next(); |
||
329 | } |
||
330 | |||
331 | /* If the function call is a constant expression, don't generate any |
||
332 | * instructions; just generate an ir_constant. |
||
333 | * |
||
334 | * Function calls were first allowed to be constant expressions in GLSL |
||
335 | * 1.20 and GLSL ES 3.00. |
||
336 | */ |
||
337 | if (state->is_version(120, 300)) { |
||
338 | ir_constant *value = sig->constant_expression_value(actual_parameters, NULL); |
||
339 | if (value != NULL) { |
||
340 | return value; |
||
341 | } |
||
342 | } |
||
343 | |||
344 | ir_dereference_variable *deref = NULL; |
||
345 | if (!sig->return_type->is_void()) { |
||
346 | /* Create a new temporary to hold the return value. */ |
||
347 | ir_variable *var; |
||
348 | |||
349 | var = new(ctx) ir_variable(sig->return_type, |
||
350 | ralloc_asprintf(ctx, "%s_retval", |
||
351 | sig->function_name()), |
||
352 | ir_var_temporary); |
||
353 | instructions->push_tail(var); |
||
354 | |||
355 | deref = new(ctx) ir_dereference_variable(var); |
||
356 | } |
||
357 | ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters); |
||
358 | instructions->push_tail(call); |
||
359 | |||
360 | /* Also emit any necessary out-parameter conversions. */ |
||
361 | instructions->append_list(&post_call_conversions); |
||
362 | |||
363 | return deref ? deref->clone(ctx, NULL) : NULL; |
||
364 | } |
||
365 | |||
366 | /** |
||
367 | * Given a function name and parameter list, find the matching signature. |
||
368 | */ |
||
369 | static ir_function_signature * |
||
370 | match_function_by_name(const char *name, |
||
371 | exec_list *actual_parameters, |
||
372 | struct _mesa_glsl_parse_state *state) |
||
373 | { |
||
374 | void *ctx = state; |
||
375 | ir_function *f = state->symbols->get_function(name); |
||
376 | ir_function_signature *local_sig = NULL; |
||
377 | ir_function_signature *sig = NULL; |
||
378 | |||
379 | /* Is the function hidden by a record type constructor? */ |
||
380 | if (state->symbols->get_type(name)) |
||
381 | goto done; /* no match */ |
||
382 | |||
383 | /* Is the function hidden by a variable (impossible in 1.10)? */ |
||
384 | if (!state->symbols->separate_function_namespace |
||
385 | && state->symbols->get_variable(name)) |
||
386 | goto done; /* no match */ |
||
387 | |||
388 | if (f != NULL) { |
||
389 | /* Look for a match in the local shader. If exact, we're done. */ |
||
390 | bool is_exact = false; |
||
391 | sig = local_sig = f->matching_signature(actual_parameters, &is_exact); |
||
392 | if (is_exact) |
||
393 | goto done; |
||
394 | |||
395 | if (!state->es_shader && f->has_user_signature()) { |
||
396 | /* In desktop GL, the presence of a user-defined signature hides any |
||
397 | * built-in signatures, so we must ignore them. In contrast, in ES2 |
||
398 | * user-defined signatures add new overloads, so we must proceed. |
||
399 | */ |
||
400 | goto done; |
||
401 | } |
||
402 | } |
||
403 | |||
404 | /* Local shader has no exact candidates; check the built-ins. */ |
||
405 | _mesa_glsl_initialize_functions(state); |
||
406 | for (unsigned i = 0; i < state->num_builtins_to_link; i++) { |
||
407 | ir_function *builtin = |
||
408 | state->builtins_to_link[i]->symbols->get_function(name); |
||
409 | if (builtin == NULL) |
||
410 | continue; |
||
411 | |||
412 | bool is_exact = false; |
||
413 | ir_function_signature *builtin_sig = |
||
414 | builtin->matching_signature(actual_parameters, &is_exact); |
||
415 | |||
416 | if (builtin_sig == NULL) |
||
417 | continue; |
||
418 | |||
419 | /* If the built-in signature is exact, we can stop. */ |
||
420 | if (is_exact) { |
||
421 | sig = builtin_sig; |
||
422 | goto done; |
||
423 | } |
||
424 | |||
425 | if (sig == NULL) { |
||
426 | /* We found an inexact match, which is better than nothing. However, |
||
427 | * we should keep searching for an exact match. |
||
428 | */ |
||
429 | sig = builtin_sig; |
||
430 | } |
||
431 | } |
||
432 | |||
433 | done: |
||
434 | if (sig != NULL) { |
||
435 | /* If the match is from a linked built-in shader, import the prototype. */ |
||
436 | if (sig != local_sig) { |
||
437 | if (f == NULL) { |
||
438 | f = new(ctx) ir_function(name); |
||
439 | state->symbols->add_global_function(f); |
||
440 | emit_function(state, f); |
||
441 | } |
||
442 | f->add_signature(sig->clone_prototype(f, NULL)); |
||
443 | } |
||
444 | } |
||
445 | return sig; |
||
446 | } |
||
447 | |||
448 | /** |
||
449 | * Raise a "no matching function" error, listing all possible overloads the |
||
450 | * compiler considered so developers can figure out what went wrong. |
||
451 | */ |
||
452 | static void |
||
453 | no_matching_function_error(const char *name, |
||
454 | YYLTYPE *loc, |
||
455 | exec_list *actual_parameters, |
||
456 | _mesa_glsl_parse_state *state) |
||
457 | { |
||
458 | char *str = prototype_string(NULL, name, actual_parameters); |
||
459 | _mesa_glsl_error(loc, state, "no matching function for call to `%s'", str); |
||
460 | ralloc_free(str); |
||
461 | |||
462 | const char *prefix = "candidates are: "; |
||
463 | |||
464 | for (int i = -1; i < (int) state->num_builtins_to_link; i++) { |
||
465 | glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols |
||
466 | : state->symbols; |
||
467 | ir_function *f = syms->get_function(name); |
||
468 | if (f == NULL) |
||
469 | continue; |
||
470 | |||
471 | foreach_list (node, &f->signatures) { |
||
472 | ir_function_signature *sig = (ir_function_signature *) node; |
||
473 | |||
474 | str = prototype_string(sig->return_type, f->name, &sig->parameters); |
||
475 | _mesa_glsl_error(loc, state, "%s%s", prefix, str); |
||
476 | ralloc_free(str); |
||
477 | |||
478 | prefix = " "; |
||
479 | } |
||
480 | } |
||
481 | } |
||
482 | |||
483 | /** |
||
484 | * Perform automatic type conversion of constructor parameters |
||
485 | * |
||
486 | * This implements the rules in the "Conversion and Scalar Constructors" |
||
487 | * section (GLSL 1.10 section 5.4.1), not the "Implicit Conversions" rules. |
||
488 | */ |
||
489 | static ir_rvalue * |
||
490 | convert_component(ir_rvalue *src, const glsl_type *desired_type) |
||
491 | { |
||
492 | void *ctx = ralloc_parent(src); |
||
493 | const unsigned a = desired_type->base_type; |
||
494 | const unsigned b = src->type->base_type; |
||
495 | ir_expression *result = NULL; |
||
496 | |||
497 | if (src->type->is_error()) |
||
498 | return src; |
||
499 | |||
500 | assert(a <= GLSL_TYPE_BOOL); |
||
501 | assert(b <= GLSL_TYPE_BOOL); |
||
502 | |||
503 | if (a == b) |
||
504 | return src; |
||
505 | |||
506 | switch (a) { |
||
507 | case GLSL_TYPE_UINT: |
||
508 | switch (b) { |
||
509 | case GLSL_TYPE_INT: |
||
510 | result = new(ctx) ir_expression(ir_unop_i2u, src); |
||
511 | break; |
||
512 | case GLSL_TYPE_FLOAT: |
||
513 | result = new(ctx) ir_expression(ir_unop_f2u, src); |
||
514 | break; |
||
515 | case GLSL_TYPE_BOOL: |
||
516 | result = new(ctx) ir_expression(ir_unop_i2u, |
||
517 | new(ctx) ir_expression(ir_unop_b2i, src)); |
||
518 | break; |
||
519 | } |
||
520 | break; |
||
521 | case GLSL_TYPE_INT: |
||
522 | switch (b) { |
||
523 | case GLSL_TYPE_UINT: |
||
524 | result = new(ctx) ir_expression(ir_unop_u2i, src); |
||
525 | break; |
||
526 | case GLSL_TYPE_FLOAT: |
||
527 | result = new(ctx) ir_expression(ir_unop_f2i, src); |
||
528 | break; |
||
529 | case GLSL_TYPE_BOOL: |
||
530 | result = new(ctx) ir_expression(ir_unop_b2i, src); |
||
531 | break; |
||
532 | } |
||
533 | break; |
||
534 | case GLSL_TYPE_FLOAT: |
||
535 | switch (b) { |
||
536 | case GLSL_TYPE_UINT: |
||
537 | result = new(ctx) ir_expression(ir_unop_u2f, desired_type, src, NULL); |
||
538 | break; |
||
539 | case GLSL_TYPE_INT: |
||
540 | result = new(ctx) ir_expression(ir_unop_i2f, desired_type, src, NULL); |
||
541 | break; |
||
542 | case GLSL_TYPE_BOOL: |
||
543 | result = new(ctx) ir_expression(ir_unop_b2f, desired_type, src, NULL); |
||
544 | break; |
||
545 | } |
||
546 | break; |
||
547 | case GLSL_TYPE_BOOL: |
||
548 | switch (b) { |
||
549 | case GLSL_TYPE_UINT: |
||
550 | result = new(ctx) ir_expression(ir_unop_i2b, |
||
551 | new(ctx) ir_expression(ir_unop_u2i, src)); |
||
552 | break; |
||
553 | case GLSL_TYPE_INT: |
||
554 | result = new(ctx) ir_expression(ir_unop_i2b, desired_type, src, NULL); |
||
555 | break; |
||
556 | case GLSL_TYPE_FLOAT: |
||
557 | result = new(ctx) ir_expression(ir_unop_f2b, desired_type, src, NULL); |
||
558 | break; |
||
559 | } |
||
560 | break; |
||
561 | } |
||
562 | |||
563 | assert(result != NULL); |
||
564 | assert(result->type == desired_type); |
||
565 | |||
566 | /* Try constant folding; it may fold in the conversion we just added. */ |
||
567 | ir_constant *const constant = result->constant_expression_value(); |
||
568 | return (constant != NULL) ? (ir_rvalue *) constant : (ir_rvalue *) result; |
||
569 | } |
||
570 | |||
571 | /** |
||
572 | * Dereference a specific component from a scalar, vector, or matrix |
||
573 | */ |
||
574 | static ir_rvalue * |
||
575 | dereference_component(ir_rvalue *src, unsigned component) |
||
576 | { |
||
577 | void *ctx = ralloc_parent(src); |
||
578 | assert(component < src->type->components()); |
||
579 | |||
580 | /* If the source is a constant, just create a new constant instead of a |
||
581 | * dereference of the existing constant. |
||
582 | */ |
||
583 | ir_constant *constant = src->as_constant(); |
||
584 | if (constant) |
||
585 | return new(ctx) ir_constant(constant, component); |
||
586 | |||
587 | if (src->type->is_scalar()) { |
||
588 | return src; |
||
589 | } else if (src->type->is_vector()) { |
||
590 | return new(ctx) ir_swizzle(src, component, 0, 0, 0, 1); |
||
591 | } else { |
||
592 | assert(src->type->is_matrix()); |
||
593 | |||
594 | /* Dereference a row of the matrix, then call this function again to get |
||
595 | * a specific element from that row. |
||
596 | */ |
||
597 | const int c = component / src->type->column_type()->vector_elements; |
||
598 | const int r = component % src->type->column_type()->vector_elements; |
||
599 | ir_constant *const col_index = new(ctx) ir_constant(c); |
||
600 | ir_dereference *const col = new(ctx) ir_dereference_array(src, col_index); |
||
601 | |||
602 | col->type = src->type->column_type(); |
||
603 | |||
604 | return dereference_component(col, r); |
||
605 | } |
||
606 | |||
607 | assert(!"Should not get here."); |
||
608 | return NULL; |
||
609 | } |
||
610 | |||
611 | |||
612 | static ir_rvalue * |
||
613 | process_vec_mat_constructor(exec_list *instructions, |
||
614 | const glsl_type *constructor_type, |
||
615 | YYLTYPE *loc, exec_list *parameters, |
||
616 | struct _mesa_glsl_parse_state *state) |
||
617 | { |
||
618 | void *ctx = state; |
||
619 | |||
620 | /* The ARB_shading_language_420pack spec says: |
||
621 | * |
||
622 | * "If an initializer is a list of initializers enclosed in curly braces, |
||
623 | * the variable being declared must be a vector, a matrix, an array, or a |
||
624 | * structure. |
||
625 | * |
||
626 | * int i = { 1 }; // illegal, i is not an aggregate" |
||
627 | */ |
||
628 | if (constructor_type->vector_elements <= 1) { |
||
629 | _mesa_glsl_error(loc, state, "Aggregates can only initialize vectors, " |
||
630 | "matrices, arrays, and structs"); |
||
631 | return ir_rvalue::error_value(ctx); |
||
632 | } |
||
633 | |||
634 | exec_list actual_parameters; |
||
635 | const unsigned parameter_count = |
||
636 | process_parameters(instructions, &actual_parameters, parameters, state); |
||
637 | |||
638 | if (parameter_count == 0 |
||
639 | || (constructor_type->is_vector() && |
||
640 | constructor_type->vector_elements != parameter_count) |
||
641 | || (constructor_type->is_matrix() && |
||
642 | constructor_type->matrix_columns != parameter_count)) { |
||
643 | _mesa_glsl_error(loc, state, "%s constructor must have %u parameters", |
||
644 | constructor_type->is_vector() ? "vector" : "matrix", |
||
645 | constructor_type->vector_elements); |
||
646 | return ir_rvalue::error_value(ctx); |
||
647 | } |
||
648 | |||
649 | bool all_parameters_are_constant = true; |
||
650 | |||
651 | /* Type cast each parameter and, if possible, fold constants. */ |
||
652 | foreach_list_safe(n, &actual_parameters) { |
||
653 | ir_rvalue *ir = (ir_rvalue *) n; |
||
654 | ir_rvalue *result = ir; |
||
655 | |||
656 | /* Apply implicit conversions (not the scalar constructor rules!). See |
||
657 | * the spec quote above. */ |
||
658 | if (constructor_type->is_float()) { |
||
659 | const glsl_type *desired_type = |
||
660 | glsl_type::get_instance(GLSL_TYPE_FLOAT, |
||
661 | ir->type->vector_elements, |
||
662 | ir->type->matrix_columns); |
||
663 | if (result->type->can_implicitly_convert_to(desired_type)) { |
||
664 | /* Even though convert_component() implements the constructor |
||
665 | * conversion rules (not the implicit conversion rules), its safe |
||
666 | * to use it here because we already checked that the implicit |
||
667 | * conversion is legal. |
||
668 | */ |
||
669 | result = convert_component(ir, desired_type); |
||
670 | } |
||
671 | } |
||
672 | |||
673 | if (constructor_type->is_matrix()) { |
||
674 | if (result->type != constructor_type->column_type()) { |
||
675 | _mesa_glsl_error(loc, state, "type error in matrix constructor: " |
||
676 | "expected: %s, found %s", |
||
677 | constructor_type->column_type()->name, |
||
678 | result->type->name); |
||
679 | return ir_rvalue::error_value(ctx); |
||
680 | } |
||
681 | } else if (result->type != constructor_type->get_scalar_type()) { |
||
682 | _mesa_glsl_error(loc, state, "type error in vector constructor: " |
||
683 | "expected: %s, found %s", |
||
684 | constructor_type->get_scalar_type()->name, |
||
685 | result->type->name); |
||
686 | return ir_rvalue::error_value(ctx); |
||
687 | } |
||
688 | |||
689 | /* Attempt to convert the parameter to a constant valued expression. |
||
690 | * After doing so, track whether or not all the parameters to the |
||
691 | * constructor are trivially constant valued expressions. |
||
692 | */ |
||
693 | ir_rvalue *const constant = result->constant_expression_value(); |
||
694 | |||
695 | if (constant != NULL) |
||
696 | result = constant; |
||
697 | else |
||
698 | all_parameters_are_constant = false; |
||
699 | |||
700 | ir->replace_with(result); |
||
701 | } |
||
702 | |||
703 | if (all_parameters_are_constant) |
||
704 | return new(ctx) ir_constant(constructor_type, &actual_parameters); |
||
705 | |||
706 | ir_variable *var = new(ctx) ir_variable(constructor_type, "vec_mat_ctor", |
||
707 | ir_var_temporary); |
||
708 | instructions->push_tail(var); |
||
709 | |||
710 | int i = 0; |
||
711 | foreach_list(node, &actual_parameters) { |
||
712 | ir_rvalue *rhs = (ir_rvalue *) node; |
||
713 | ir_rvalue *lhs = new(ctx) ir_dereference_array(var, |
||
714 | new(ctx) ir_constant(i)); |
||
715 | |||
716 | ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL); |
||
717 | instructions->push_tail(assignment); |
||
718 | |||
719 | i++; |
||
720 | } |
||
721 | |||
722 | return new(ctx) ir_dereference_variable(var); |
||
723 | } |
||
724 | |||
725 | |||
726 | static ir_rvalue * |
||
727 | process_array_constructor(exec_list *instructions, |
||
728 | const glsl_type *constructor_type, |
||
729 | YYLTYPE *loc, exec_list *parameters, |
||
730 | struct _mesa_glsl_parse_state *state) |
||
731 | { |
||
732 | void *ctx = state; |
||
733 | /* Array constructors come in two forms: sized and unsized. Sized array |
||
734 | * constructors look like 'vec4[2](a, b)', where 'a' and 'b' are vec4 |
||
735 | * variables. In this case the number of parameters must exactly match the |
||
736 | * specified size of the array. |
||
737 | * |
||
738 | * Unsized array constructors look like 'vec4[](a, b)', where 'a' and 'b' |
||
739 | * are vec4 variables. In this case the size of the array being constructed |
||
740 | * is determined by the number of parameters. |
||
741 | * |
||
742 | * From page 52 (page 58 of the PDF) of the GLSL 1.50 spec: |
||
743 | * |
||
744 | * "There must be exactly the same number of arguments as the size of |
||
745 | * the array being constructed. If no size is present in the |
||
746 | * constructor, then the array is explicitly sized to the number of |
||
747 | * arguments provided. The arguments are assigned in order, starting at |
||
748 | * element 0, to the elements of the constructed array. Each argument |
||
749 | * must be the same type as the element type of the array, or be a type |
||
750 | * that can be converted to the element type of the array according to |
||
751 | * Section 4.1.10 "Implicit Conversions."" |
||
752 | */ |
||
753 | exec_list actual_parameters; |
||
754 | const unsigned parameter_count = |
||
755 | process_parameters(instructions, &actual_parameters, parameters, state); |
||
756 | |||
757 | if ((parameter_count == 0) |
||
758 | || ((constructor_type->length != 0) |
||
759 | && (constructor_type->length != parameter_count))) { |
||
760 | const unsigned min_param = (constructor_type->length == 0) |
||
761 | ? 1 : constructor_type->length; |
||
762 | |||
763 | _mesa_glsl_error(loc, state, "array constructor must have %s %u " |
||
764 | "parameter%s", |
||
765 | (constructor_type->length == 0) ? "at least" : "exactly", |
||
766 | min_param, (min_param <= 1) ? "" : "s"); |
||
767 | return ir_rvalue::error_value(ctx); |
||
768 | } |
||
769 | |||
770 | if (constructor_type->length == 0) { |
||
771 | constructor_type = |
||
772 | glsl_type::get_array_instance(constructor_type->element_type(), |
||
773 | parameter_count); |
||
774 | assert(constructor_type != NULL); |
||
775 | assert(constructor_type->length == parameter_count); |
||
776 | } |
||
777 | |||
778 | bool all_parameters_are_constant = true; |
||
779 | |||
780 | /* Type cast each parameter and, if possible, fold constants. */ |
||
781 | foreach_list_safe(n, &actual_parameters) { |
||
782 | ir_rvalue *ir = (ir_rvalue *) n; |
||
783 | ir_rvalue *result = ir; |
||
784 | |||
785 | /* Apply implicit conversions (not the scalar constructor rules!). See |
||
786 | * the spec quote above. */ |
||
787 | if (constructor_type->element_type()->is_float()) { |
||
788 | const glsl_type *desired_type = |
||
789 | glsl_type::get_instance(GLSL_TYPE_FLOAT, |
||
790 | ir->type->vector_elements, |
||
791 | ir->type->matrix_columns); |
||
792 | if (result->type->can_implicitly_convert_to(desired_type)) { |
||
793 | /* Even though convert_component() implements the constructor |
||
794 | * conversion rules (not the implicit conversion rules), its safe |
||
795 | * to use it here because we already checked that the implicit |
||
796 | * conversion is legal. |
||
797 | */ |
||
798 | result = convert_component(ir, desired_type); |
||
799 | } |
||
800 | } |
||
801 | |||
802 | if (result->type != constructor_type->element_type()) { |
||
803 | _mesa_glsl_error(loc, state, "type error in array constructor: " |
||
804 | "expected: %s, found %s", |
||
805 | constructor_type->element_type()->name, |
||
806 | result->type->name); |
||
807 | return ir_rvalue::error_value(ctx); |
||
808 | } |
||
809 | |||
810 | /* Attempt to convert the parameter to a constant valued expression. |
||
811 | * After doing so, track whether or not all the parameters to the |
||
812 | * constructor are trivially constant valued expressions. |
||
813 | */ |
||
814 | ir_rvalue *const constant = result->constant_expression_value(); |
||
815 | |||
816 | if (constant != NULL) |
||
817 | result = constant; |
||
818 | else |
||
819 | all_parameters_are_constant = false; |
||
820 | |||
821 | ir->replace_with(result); |
||
822 | } |
||
823 | |||
824 | if (all_parameters_are_constant) |
||
825 | return new(ctx) ir_constant(constructor_type, &actual_parameters); |
||
826 | |||
827 | ir_variable *var = new(ctx) ir_variable(constructor_type, "array_ctor", |
||
828 | ir_var_temporary); |
||
829 | instructions->push_tail(var); |
||
830 | |||
831 | int i = 0; |
||
832 | foreach_list(node, &actual_parameters) { |
||
833 | ir_rvalue *rhs = (ir_rvalue *) node; |
||
834 | ir_rvalue *lhs = new(ctx) ir_dereference_array(var, |
||
835 | new(ctx) ir_constant(i)); |
||
836 | |||
837 | ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL); |
||
838 | instructions->push_tail(assignment); |
||
839 | |||
840 | i++; |
||
841 | } |
||
842 | |||
843 | return new(ctx) ir_dereference_variable(var); |
||
844 | } |
||
845 | |||
846 | |||
847 | /** |
||
848 | * Try to convert a record constructor to a constant expression |
||
849 | */ |
||
850 | static ir_constant * |
||
851 | constant_record_constructor(const glsl_type *constructor_type, |
||
852 | exec_list *parameters, void *mem_ctx) |
||
853 | { |
||
854 | foreach_list(node, parameters) { |
||
855 | ir_constant *constant = ((ir_instruction *) node)->as_constant(); |
||
856 | if (constant == NULL) |
||
857 | return NULL; |
||
858 | node->replace_with(constant); |
||
859 | } |
||
860 | |||
861 | return new(mem_ctx) ir_constant(constructor_type, parameters); |
||
862 | } |
||
863 | |||
864 | |||
865 | /** |
||
866 | * Determine if a list consists of a single scalar r-value |
||
867 | */ |
||
868 | bool |
||
869 | single_scalar_parameter(exec_list *parameters) |
||
870 | { |
||
871 | const ir_rvalue *const p = (ir_rvalue *) parameters->head; |
||
872 | assert(((ir_rvalue *)p)->as_rvalue() != NULL); |
||
873 | |||
874 | return (p->type->is_scalar() && p->next->is_tail_sentinel()); |
||
875 | } |
||
876 | |||
877 | |||
878 | /** |
||
879 | * Generate inline code for a vector constructor |
||
880 | * |
||
881 | * The generated constructor code will consist of a temporary variable |
||
882 | * declaration of the same type as the constructor. A sequence of assignments |
||
883 | * from constructor parameters to the temporary will follow. |
||
884 | * |
||
885 | * \return |
||
886 | * An \c ir_dereference_variable of the temprorary generated in the constructor |
||
887 | * body. |
||
888 | */ |
||
889 | ir_rvalue * |
||
890 | emit_inline_vector_constructor(const glsl_type *type, |
||
891 | exec_list *instructions, |
||
892 | exec_list *parameters, |
||
893 | void *ctx) |
||
894 | { |
||
895 | assert(!parameters->is_empty()); |
||
896 | |||
897 | ir_variable *var = new(ctx) ir_variable(type, "vec_ctor", ir_var_temporary); |
||
898 | instructions->push_tail(var); |
||
899 | |||
900 | /* There are two kinds of vector constructors. |
||
901 | * |
||
902 | * - Construct a vector from a single scalar by replicating that scalar to |
||
903 | * all components of the vector. |
||
904 | * |
||
905 | * - Construct a vector from an arbirary combination of vectors and |
||
906 | * scalars. The components of the constructor parameters are assigned |
||
907 | * to the vector in order until the vector is full. |
||
908 | */ |
||
909 | const unsigned lhs_components = type->components(); |
||
910 | if (single_scalar_parameter(parameters)) { |
||
911 | ir_rvalue *first_param = (ir_rvalue *)parameters->head; |
||
912 | ir_rvalue *rhs = new(ctx) ir_swizzle(first_param, 0, 0, 0, 0, |
||
913 | lhs_components); |
||
914 | ir_dereference_variable *lhs = new(ctx) ir_dereference_variable(var); |
||
915 | const unsigned mask = (1U << lhs_components) - 1; |
||
916 | |||
917 | assert(rhs->type == lhs->type); |
||
918 | |||
919 | ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL, mask); |
||
920 | instructions->push_tail(inst); |
||
921 | } else { |
||
922 | unsigned base_component = 0; |
||
923 | unsigned base_lhs_component = 0; |
||
924 | ir_constant_data data; |
||
925 | unsigned constant_mask = 0, constant_components = 0; |
||
926 | |||
927 | memset(&data, 0, sizeof(data)); |
||
928 | |||
929 | foreach_list(node, parameters) { |
||
930 | ir_rvalue *param = (ir_rvalue *) node; |
||
931 | unsigned rhs_components = param->type->components(); |
||
932 | |||
933 | /* Do not try to assign more components to the vector than it has! |
||
934 | */ |
||
935 | if ((rhs_components + base_lhs_component) > lhs_components) { |
||
936 | rhs_components = lhs_components - base_lhs_component; |
||
937 | } |
||
938 | |||
939 | const ir_constant *const c = param->as_constant(); |
||
940 | if (c != NULL) { |
||
941 | for (unsigned i = 0; i < rhs_components; i++) { |
||
942 | switch (c->type->base_type) { |
||
943 | case GLSL_TYPE_UINT: |
||
944 | data.u[i + base_component] = c->get_uint_component(i); |
||
945 | break; |
||
946 | case GLSL_TYPE_INT: |
||
947 | data.i[i + base_component] = c->get_int_component(i); |
||
948 | break; |
||
949 | case GLSL_TYPE_FLOAT: |
||
950 | data.f[i + base_component] = c->get_float_component(i); |
||
951 | break; |
||
952 | case GLSL_TYPE_BOOL: |
||
953 | data.b[i + base_component] = c->get_bool_component(i); |
||
954 | break; |
||
955 | default: |
||
956 | assert(!"Should not get here."); |
||
957 | break; |
||
958 | } |
||
959 | } |
||
960 | |||
961 | /* Mask of fields to be written in the assignment. |
||
962 | */ |
||
963 | constant_mask |= ((1U << rhs_components) - 1) << base_lhs_component; |
||
964 | constant_components += rhs_components; |
||
965 | |||
966 | base_component += rhs_components; |
||
967 | } |
||
968 | /* Advance the component index by the number of components |
||
969 | * that were just assigned. |
||
970 | */ |
||
971 | base_lhs_component += rhs_components; |
||
972 | } |
||
973 | |||
974 | if (constant_mask != 0) { |
||
975 | ir_dereference *lhs = new(ctx) ir_dereference_variable(var); |
||
976 | const glsl_type *rhs_type = glsl_type::get_instance(var->type->base_type, |
||
977 | constant_components, |
||
978 | 1); |
||
979 | ir_rvalue *rhs = new(ctx) ir_constant(rhs_type, &data); |
||
980 | |||
981 | ir_instruction *inst = |
||
982 | new(ctx) ir_assignment(lhs, rhs, NULL, constant_mask); |
||
983 | instructions->push_tail(inst); |
||
984 | } |
||
985 | |||
986 | base_component = 0; |
||
987 | foreach_list(node, parameters) { |
||
988 | ir_rvalue *param = (ir_rvalue *) node; |
||
989 | unsigned rhs_components = param->type->components(); |
||
990 | |||
991 | /* Do not try to assign more components to the vector than it has! |
||
992 | */ |
||
993 | if ((rhs_components + base_component) > lhs_components) { |
||
994 | rhs_components = lhs_components - base_component; |
||
995 | } |
||
996 | |||
997 | const ir_constant *const c = param->as_constant(); |
||
998 | if (c == NULL) { |
||
999 | /* Mask of fields to be written in the assignment. |
||
1000 | */ |
||
1001 | const unsigned write_mask = ((1U << rhs_components) - 1) |
||
1002 | << base_component; |
||
1003 | |||
1004 | ir_dereference *lhs = new(ctx) ir_dereference_variable(var); |
||
1005 | |||
1006 | /* Generate a swizzle so that LHS and RHS sizes match. |
||
1007 | */ |
||
1008 | ir_rvalue *rhs = |
||
1009 | new(ctx) ir_swizzle(param, 0, 1, 2, 3, rhs_components); |
||
1010 | |||
1011 | ir_instruction *inst = |
||
1012 | new(ctx) ir_assignment(lhs, rhs, NULL, write_mask); |
||
1013 | instructions->push_tail(inst); |
||
1014 | } |
||
1015 | |||
1016 | /* Advance the component index by the number of components that were |
||
1017 | * just assigned. |
||
1018 | */ |
||
1019 | base_component += rhs_components; |
||
1020 | } |
||
1021 | } |
||
1022 | return new(ctx) ir_dereference_variable(var); |
||
1023 | } |
||
1024 | |||
1025 | |||
1026 | /** |
||
1027 | * Generate assignment of a portion of a vector to a portion of a matrix column |
||
1028 | * |
||
1029 | * \param src_base First component of the source to be used in assignment |
||
1030 | * \param column Column of destination to be assiged |
||
1031 | * \param row_base First component of the destination column to be assigned |
||
1032 | * \param count Number of components to be assigned |
||
1033 | * |
||
1034 | * \note |
||
1035 | * \c src_base + \c count must be less than or equal to the number of components |
||
1036 | * in the source vector. |
||
1037 | */ |
||
1038 | ir_instruction * |
||
1039 | assign_to_matrix_column(ir_variable *var, unsigned column, unsigned row_base, |
||
1040 | ir_rvalue *src, unsigned src_base, unsigned count, |
||
1041 | void *mem_ctx) |
||
1042 | { |
||
1043 | ir_constant *col_idx = new(mem_ctx) ir_constant(column); |
||
1044 | ir_dereference *column_ref = new(mem_ctx) ir_dereference_array(var, col_idx); |
||
1045 | |||
1046 | assert(column_ref->type->components() >= (row_base + count)); |
||
1047 | assert(src->type->components() >= (src_base + count)); |
||
1048 | |||
1049 | /* Generate a swizzle that extracts the number of components from the source |
||
1050 | * that are to be assigned to the column of the matrix. |
||
1051 | */ |
||
1052 | if (count < src->type->vector_elements) { |
||
1053 | src = new(mem_ctx) ir_swizzle(src, |
||
1054 | src_base + 0, src_base + 1, |
||
1055 | src_base + 2, src_base + 3, |
||
1056 | count); |
||
1057 | } |
||
1058 | |||
1059 | /* Mask of fields to be written in the assignment. |
||
1060 | */ |
||
1061 | const unsigned write_mask = ((1U << count) - 1) << row_base; |
||
1062 | |||
1063 | return new(mem_ctx) ir_assignment(column_ref, src, NULL, write_mask); |
||
1064 | } |
||
1065 | |||
1066 | |||
1067 | /** |
||
1068 | * Generate inline code for a matrix constructor |
||
1069 | * |
||
1070 | * The generated constructor code will consist of a temporary variable |
||
1071 | * declaration of the same type as the constructor. A sequence of assignments |
||
1072 | * from constructor parameters to the temporary will follow. |
||
1073 | * |
||
1074 | * \return |
||
1075 | * An \c ir_dereference_variable of the temprorary generated in the constructor |
||
1076 | * body. |
||
1077 | */ |
||
1078 | ir_rvalue * |
||
1079 | emit_inline_matrix_constructor(const glsl_type *type, |
||
1080 | exec_list *instructions, |
||
1081 | exec_list *parameters, |
||
1082 | void *ctx) |
||
1083 | { |
||
1084 | assert(!parameters->is_empty()); |
||
1085 | |||
1086 | ir_variable *var = new(ctx) ir_variable(type, "mat_ctor", ir_var_temporary); |
||
1087 | instructions->push_tail(var); |
||
1088 | |||
1089 | /* There are three kinds of matrix constructors. |
||
1090 | * |
||
1091 | * - Construct a matrix from a single scalar by replicating that scalar to |
||
1092 | * along the diagonal of the matrix and setting all other components to |
||
1093 | * zero. |
||
1094 | * |
||
1095 | * - Construct a matrix from an arbirary combination of vectors and |
||
1096 | * scalars. The components of the constructor parameters are assigned |
||
1097 | * to the matrix in colum-major order until the matrix is full. |
||
1098 | * |
||
1099 | * - Construct a matrix from a single matrix. The source matrix is copied |
||
1100 | * to the upper left portion of the constructed matrix, and the remaining |
||
1101 | * elements take values from the identity matrix. |
||
1102 | */ |
||
1103 | ir_rvalue *const first_param = (ir_rvalue *) parameters->head; |
||
1104 | if (single_scalar_parameter(parameters)) { |
||
1105 | /* Assign the scalar to the X component of a vec4, and fill the remaining |
||
1106 | * components with zero. |
||
1107 | */ |
||
1108 | ir_variable *rhs_var = |
||
1109 | new(ctx) ir_variable(glsl_type::vec4_type, "mat_ctor_vec", |
||
1110 | ir_var_temporary); |
||
1111 | instructions->push_tail(rhs_var); |
||
1112 | |||
1113 | ir_constant_data zero; |
||
1114 | zero.f[0] = 0.0; |
||
1115 | zero.f[1] = 0.0; |
||
1116 | zero.f[2] = 0.0; |
||
1117 | zero.f[3] = 0.0; |
||
1118 | |||
1119 | ir_instruction *inst = |
||
1120 | new(ctx) ir_assignment(new(ctx) ir_dereference_variable(rhs_var), |
||
1121 | new(ctx) ir_constant(rhs_var->type, &zero), |
||
1122 | NULL); |
||
1123 | instructions->push_tail(inst); |
||
1124 | |||
1125 | ir_dereference *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var); |
||
1126 | |||
1127 | inst = new(ctx) ir_assignment(rhs_ref, first_param, NULL, 0x01); |
||
1128 | instructions->push_tail(inst); |
||
1129 | |||
1130 | /* Assign the temporary vector to each column of the destination matrix |
||
1131 | * with a swizzle that puts the X component on the diagonal of the |
||
1132 | * matrix. In some cases this may mean that the X component does not |
||
1133 | * get assigned into the column at all (i.e., when the matrix has more |
||
1134 | * columns than rows). |
||
1135 | */ |
||
1136 | static const unsigned rhs_swiz[4][4] = { |
||
1137 | { 0, 1, 1, 1 }, |
||
1138 | { 1, 0, 1, 1 }, |
||
1139 | { 1, 1, 0, 1 }, |
||
1140 | { 1, 1, 1, 0 } |
||
1141 | }; |
||
1142 | |||
1143 | const unsigned cols_to_init = MIN2(type->matrix_columns, |
||
1144 | type->vector_elements); |
||
1145 | for (unsigned i = 0; i < cols_to_init; i++) { |
||
1146 | ir_constant *const col_idx = new(ctx) ir_constant(i); |
||
1147 | ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var, col_idx); |
||
1148 | |||
1149 | ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var); |
||
1150 | ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, rhs_swiz[i], |
||
1151 | type->vector_elements); |
||
1152 | |||
1153 | inst = new(ctx) ir_assignment(col_ref, rhs, NULL); |
||
1154 | instructions->push_tail(inst); |
||
1155 | } |
||
1156 | |||
1157 | for (unsigned i = cols_to_init; i < type->matrix_columns; i++) { |
||
1158 | ir_constant *const col_idx = new(ctx) ir_constant(i); |
||
1159 | ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var, col_idx); |
||
1160 | |||
1161 | ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var); |
||
1162 | ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, 1, 1, 1, 1, |
||
1163 | type->vector_elements); |
||
1164 | |||
1165 | inst = new(ctx) ir_assignment(col_ref, rhs, NULL); |
||
1166 | instructions->push_tail(inst); |
||
1167 | } |
||
1168 | } else if (first_param->type->is_matrix()) { |
||
1169 | /* From page 50 (56 of the PDF) of the GLSL 1.50 spec: |
||
1170 | * |
||
1171 | * "If a matrix is constructed from a matrix, then each component |
||
1172 | * (column i, row j) in the result that has a corresponding |
||
1173 | * component (column i, row j) in the argument will be initialized |
||
1174 | * from there. All other components will be initialized to the |
||
1175 | * identity matrix. If a matrix argument is given to a matrix |
||
1176 | * constructor, it is an error to have any other arguments." |
||
1177 | */ |
||
1178 | assert(first_param->next->is_tail_sentinel()); |
||
1179 | ir_rvalue *const src_matrix = first_param; |
||
1180 | |||
1181 | /* If the source matrix is smaller, pre-initialize the relavent parts of |
||
1182 | * the destination matrix to the identity matrix. |
||
1183 | */ |
||
1184 | if ((src_matrix->type->matrix_columns < var->type->matrix_columns) |
||
1185 | || (src_matrix->type->vector_elements < var->type->vector_elements)) { |
||
1186 | |||
1187 | /* If the source matrix has fewer rows, every column of the destination |
||
1188 | * must be initialized. Otherwise only the columns in the destination |
||
1189 | * that do not exist in the source must be initialized. |
||
1190 | */ |
||
1191 | unsigned col = |
||
1192 | (src_matrix->type->vector_elements < var->type->vector_elements) |
||
1193 | ? 0 : src_matrix->type->matrix_columns; |
||
1194 | |||
1195 | const glsl_type *const col_type = var->type->column_type(); |
||
1196 | for (/* empty */; col < var->type->matrix_columns; col++) { |
||
1197 | ir_constant_data ident; |
||
1198 | |||
1199 | ident.f[0] = 0.0; |
||
1200 | ident.f[1] = 0.0; |
||
1201 | ident.f[2] = 0.0; |
||
1202 | ident.f[3] = 0.0; |
||
1203 | |||
1204 | ident.f[col] = 1.0; |
||
1205 | |||
1206 | ir_rvalue *const rhs = new(ctx) ir_constant(col_type, &ident); |
||
1207 | |||
1208 | ir_rvalue *const lhs = |
||
1209 | new(ctx) ir_dereference_array(var, new(ctx) ir_constant(col)); |
||
1210 | |||
1211 | ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL); |
||
1212 | instructions->push_tail(inst); |
||
1213 | } |
||
1214 | } |
||
1215 | |||
1216 | /* Assign columns from the source matrix to the destination matrix. |
||
1217 | * |
||
1218 | * Since the parameter will be used in the RHS of multiple assignments, |
||
1219 | * generate a temporary and copy the paramter there. |
||
1220 | */ |
||
1221 | ir_variable *const rhs_var = |
||
1222 | new(ctx) ir_variable(first_param->type, "mat_ctor_mat", |
||
1223 | ir_var_temporary); |
||
1224 | instructions->push_tail(rhs_var); |
||
1225 | |||
1226 | ir_dereference *const rhs_var_ref = |
||
1227 | new(ctx) ir_dereference_variable(rhs_var); |
||
1228 | ir_instruction *const inst = |
||
1229 | new(ctx) ir_assignment(rhs_var_ref, first_param, NULL); |
||
1230 | instructions->push_tail(inst); |
||
1231 | |||
1232 | const unsigned last_row = MIN2(src_matrix->type->vector_elements, |
||
1233 | var->type->vector_elements); |
||
1234 | const unsigned last_col = MIN2(src_matrix->type->matrix_columns, |
||
1235 | var->type->matrix_columns); |
||
1236 | |||
1237 | unsigned swiz[4] = { 0, 0, 0, 0 }; |
||
1238 | for (unsigned i = 1; i < last_row; i++) |
||
1239 | swiz[i] = i; |
||
1240 | |||
1241 | const unsigned write_mask = (1U << last_row) - 1; |
||
1242 | |||
1243 | for (unsigned i = 0; i < last_col; i++) { |
||
1244 | ir_dereference *const lhs = |
||
1245 | new(ctx) ir_dereference_array(var, new(ctx) ir_constant(i)); |
||
1246 | ir_rvalue *const rhs_col = |
||
1247 | new(ctx) ir_dereference_array(rhs_var, new(ctx) ir_constant(i)); |
||
1248 | |||
1249 | /* If one matrix has columns that are smaller than the columns of the |
||
1250 | * other matrix, wrap the column access of the larger with a swizzle |
||
1251 | * so that the LHS and RHS of the assignment have the same size (and |
||
1252 | * therefore have the same type). |
||
1253 | * |
||
1254 | * It would be perfectly valid to unconditionally generate the |
||
1255 | * swizzles, this this will typically result in a more compact IR tree. |
||
1256 | */ |
||
1257 | ir_rvalue *rhs; |
||
1258 | if (lhs->type->vector_elements != rhs_col->type->vector_elements) { |
||
1259 | rhs = new(ctx) ir_swizzle(rhs_col, swiz, last_row); |
||
1260 | } else { |
||
1261 | rhs = rhs_col; |
||
1262 | } |
||
1263 | |||
1264 | ir_instruction *inst = |
||
1265 | new(ctx) ir_assignment(lhs, rhs, NULL, write_mask); |
||
1266 | instructions->push_tail(inst); |
||
1267 | } |
||
1268 | } else { |
||
1269 | const unsigned cols = type->matrix_columns; |
||
1270 | const unsigned rows = type->vector_elements; |
||
1271 | unsigned col_idx = 0; |
||
1272 | unsigned row_idx = 0; |
||
1273 | |||
1274 | foreach_list (node, parameters) { |
||
1275 | ir_rvalue *const rhs = (ir_rvalue *) node; |
||
1276 | const unsigned components_remaining_this_column = rows - row_idx; |
||
1277 | unsigned rhs_components = rhs->type->components(); |
||
1278 | unsigned rhs_base = 0; |
||
1279 | |||
1280 | /* Since the parameter might be used in the RHS of two assignments, |
||
1281 | * generate a temporary and copy the paramter there. |
||
1282 | */ |
||
1283 | ir_variable *rhs_var = |
||
1284 | new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary); |
||
1285 | instructions->push_tail(rhs_var); |
||
1286 | |||
1287 | ir_dereference *rhs_var_ref = |
||
1288 | new(ctx) ir_dereference_variable(rhs_var); |
||
1289 | ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL); |
||
1290 | instructions->push_tail(inst); |
||
1291 | |||
1292 | /* Assign the current parameter to as many components of the matrix |
||
1293 | * as it will fill. |
||
1294 | * |
||
1295 | * NOTE: A single vector parameter can span two matrix columns. A |
||
1296 | * single vec4, for example, can completely fill a mat2. |
||
1297 | */ |
||
1298 | if (rhs_components >= components_remaining_this_column) { |
||
1299 | const unsigned count = MIN2(rhs_components, |
||
1300 | components_remaining_this_column); |
||
1301 | |||
1302 | rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var); |
||
1303 | |||
1304 | ir_instruction *inst = assign_to_matrix_column(var, col_idx, |
||
1305 | row_idx, |
||
1306 | rhs_var_ref, 0, |
||
1307 | count, ctx); |
||
1308 | instructions->push_tail(inst); |
||
1309 | |||
1310 | rhs_base = count; |
||
1311 | |||
1312 | col_idx++; |
||
1313 | row_idx = 0; |
||
1314 | } |
||
1315 | |||
1316 | /* If there is data left in the parameter and components left to be |
||
1317 | * set in the destination, emit another assignment. It is possible |
||
1318 | * that the assignment could be of a vec4 to the last element of the |
||
1319 | * matrix. In this case col_idx==cols, but there is still data |
||
1320 | * left in the source parameter. Obviously, don't emit an assignment |
||
1321 | * to data outside the destination matrix. |
||
1322 | */ |
||
1323 | if ((col_idx < cols) && (rhs_base < rhs_components)) { |
||
1324 | const unsigned count = rhs_components - rhs_base; |
||
1325 | |||
1326 | rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var); |
||
1327 | |||
1328 | ir_instruction *inst = assign_to_matrix_column(var, col_idx, |
||
1329 | row_idx, |
||
1330 | rhs_var_ref, |
||
1331 | rhs_base, |
||
1332 | count, ctx); |
||
1333 | instructions->push_tail(inst); |
||
1334 | |||
1335 | row_idx += count; |
||
1336 | } |
||
1337 | } |
||
1338 | } |
||
1339 | |||
1340 | return new(ctx) ir_dereference_variable(var); |
||
1341 | } |
||
1342 | |||
1343 | |||
1344 | ir_rvalue * |
||
1345 | emit_inline_record_constructor(const glsl_type *type, |
||
1346 | exec_list *instructions, |
||
1347 | exec_list *parameters, |
||
1348 | void *mem_ctx) |
||
1349 | { |
||
1350 | ir_variable *const var = |
||
1351 | new(mem_ctx) ir_variable(type, "record_ctor", ir_var_temporary); |
||
1352 | ir_dereference_variable *const d = new(mem_ctx) ir_dereference_variable(var); |
||
1353 | |||
1354 | instructions->push_tail(var); |
||
1355 | |||
1356 | exec_node *node = parameters->head; |
||
1357 | for (unsigned i = 0; i < type->length; i++) { |
||
1358 | assert(!node->is_tail_sentinel()); |
||
1359 | |||
1360 | ir_dereference *const lhs = |
||
1361 | new(mem_ctx) ir_dereference_record(d->clone(mem_ctx, NULL), |
||
1362 | type->fields.structure[i].name); |
||
1363 | |||
1364 | ir_rvalue *const rhs = ((ir_instruction *) node)->as_rvalue(); |
||
1365 | assert(rhs != NULL); |
||
1366 | |||
1367 | ir_instruction *const assign = new(mem_ctx) ir_assignment(lhs, rhs, NULL); |
||
1368 | |||
1369 | instructions->push_tail(assign); |
||
1370 | node = node->next; |
||
1371 | } |
||
1372 | |||
1373 | return d; |
||
1374 | } |
||
1375 | |||
1376 | |||
1377 | static ir_rvalue * |
||
1378 | process_record_constructor(exec_list *instructions, |
||
1379 | const glsl_type *constructor_type, |
||
1380 | YYLTYPE *loc, exec_list *parameters, |
||
1381 | struct _mesa_glsl_parse_state *state) |
||
1382 | { |
||
1383 | void *ctx = state; |
||
1384 | exec_list actual_parameters; |
||
1385 | |||
1386 | process_parameters(instructions, &actual_parameters, |
||
1387 | parameters, state); |
||
1388 | |||
1389 | exec_node *node = actual_parameters.head; |
||
1390 | for (unsigned i = 0; i < constructor_type->length; i++) { |
||
1391 | ir_rvalue *ir = (ir_rvalue *) node; |
||
1392 | |||
1393 | if (node->is_tail_sentinel()) { |
||
1394 | _mesa_glsl_error(loc, state, |
||
1395 | "insufficient parameters to constructor for `%s'", |
||
1396 | constructor_type->name); |
||
1397 | return ir_rvalue::error_value(ctx); |
||
1398 | } |
||
1399 | |||
1400 | if (apply_implicit_conversion(constructor_type->fields.structure[i].type, |
||
1401 | ir, state)) { |
||
1402 | node->replace_with(ir); |
||
1403 | } else { |
||
1404 | _mesa_glsl_error(loc, state, |
||
1405 | "parameter type mismatch in constructor for `%s.%s' " |
||
1406 | "(%s vs %s)", |
||
1407 | constructor_type->name, |
||
1408 | constructor_type->fields.structure[i].name, |
||
1409 | ir->type->name, |
||
1410 | constructor_type->fields.structure[i].type->name); |
||
1411 | return ir_rvalue::error_value(ctx);; |
||
1412 | } |
||
1413 | |||
1414 | node = node->next; |
||
1415 | } |
||
1416 | |||
1417 | if (!node->is_tail_sentinel()) { |
||
1418 | _mesa_glsl_error(loc, state, "too many parameters in constructor " |
||
1419 | "for `%s'", constructor_type->name); |
||
1420 | return ir_rvalue::error_value(ctx); |
||
1421 | } |
||
1422 | |||
1423 | ir_rvalue *const constant = |
||
1424 | constant_record_constructor(constructor_type, &actual_parameters, |
||
1425 | state); |
||
1426 | |||
1427 | return (constant != NULL) |
||
1428 | ? constant |
||
1429 | : emit_inline_record_constructor(constructor_type, instructions, |
||
1430 | &actual_parameters, state); |
||
1431 | } |
||
1432 | |||
1433 | |||
1434 | ir_rvalue * |
||
1435 | ast_function_expression::hir(exec_list *instructions, |
||
1436 | struct _mesa_glsl_parse_state *state) |
||
1437 | { |
||
1438 | void *ctx = state; |
||
1439 | /* There are three sorts of function calls. |
||
1440 | * |
||
1441 | * 1. constructors - The first subexpression is an ast_type_specifier. |
||
1442 | * 2. methods - Only the .length() method of array types. |
||
1443 | * 3. functions - Calls to regular old functions. |
||
1444 | * |
||
1445 | * Method calls are actually detected when the ast_field_selection |
||
1446 | * expression is handled. |
||
1447 | */ |
||
1448 | if (is_constructor()) { |
||
1449 | const ast_type_specifier *type = (ast_type_specifier *) subexpressions[0]; |
||
1450 | YYLTYPE loc = type->get_location(); |
||
1451 | const char *name; |
||
1452 | |||
1453 | const glsl_type *const constructor_type = type->glsl_type(& name, state); |
||
1454 | |||
1455 | /* constructor_type can be NULL if a variable with the same name as the |
||
1456 | * structure has come into scope. |
||
1457 | */ |
||
1458 | if (constructor_type == NULL) { |
||
1459 | _mesa_glsl_error(& loc, state, "unknown type `%s' (structure name " |
||
1460 | "may be shadowed by a variable with the same name)", |
||
1461 | type->type_name); |
||
1462 | return ir_rvalue::error_value(ctx); |
||
1463 | } |
||
1464 | |||
1465 | |||
1466 | /* Constructors for samplers are illegal. |
||
1467 | */ |
||
1468 | if (constructor_type->is_sampler()) { |
||
1469 | _mesa_glsl_error(& loc, state, "cannot construct sampler type `%s'", |
||
1470 | constructor_type->name); |
||
1471 | return ir_rvalue::error_value(ctx); |
||
1472 | } |
||
1473 | |||
1474 | if (constructor_type->is_array()) { |
||
1475 | if (!state->check_version(120, 300, &loc, |
||
1476 | "array constructors forbidden")) { |
||
1477 | return ir_rvalue::error_value(ctx); |
||
1478 | } |
||
1479 | |||
1480 | return process_array_constructor(instructions, constructor_type, |
||
1481 | & loc, &this->expressions, state); |
||
1482 | } |
||
1483 | |||
1484 | |||
1485 | /* There are two kinds of constructor calls. Constructors for arrays and |
||
1486 | * structures must have the exact number of arguments with matching types |
||
1487 | * in the correct order. These constructors follow essentially the same |
||
1488 | * type matching rules as functions. |
||
1489 | * |
||
1490 | * Constructors for built-in language types, such as mat4 and vec2, are |
||
1491 | * free form. The only requirements are that the parameters must provide |
||
1492 | * enough values of the correct scalar type and that no arguments are |
||
1493 | * given past the last used argument. |
||
1494 | * |
||
1495 | * When using the C-style initializer syntax from GLSL 4.20, constructors |
||
1496 | * must have the exact number of arguments with matching types in the |
||
1497 | * correct order. |
||
1498 | */ |
||
1499 | if (constructor_type->is_record()) { |
||
1500 | return process_record_constructor(instructions, constructor_type, |
||
1501 | &loc, &this->expressions, |
||
1502 | state); |
||
1503 | } |
||
1504 | |||
1505 | if (!constructor_type->is_numeric() && !constructor_type->is_boolean()) |
||
1506 | return ir_rvalue::error_value(ctx); |
||
1507 | |||
1508 | /* Total number of components of the type being constructed. */ |
||
1509 | const unsigned type_components = constructor_type->components(); |
||
1510 | |||
1511 | /* Number of components from parameters that have actually been |
||
1512 | * consumed. This is used to perform several kinds of error checking. |
||
1513 | */ |
||
1514 | unsigned components_used = 0; |
||
1515 | |||
1516 | unsigned matrix_parameters = 0; |
||
1517 | unsigned nonmatrix_parameters = 0; |
||
1518 | exec_list actual_parameters; |
||
1519 | |||
1520 | foreach_list (n, &this->expressions) { |
||
1521 | ast_node *ast = exec_node_data(ast_node, n, link); |
||
1522 | ir_rvalue *result = ast->hir(instructions, state)->as_rvalue(); |
||
1523 | |||
1524 | /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec: |
||
1525 | * |
||
1526 | * "It is an error to provide extra arguments beyond this |
||
1527 | * last used argument." |
||
1528 | */ |
||
1529 | if (components_used >= type_components) { |
||
1530 | _mesa_glsl_error(& loc, state, "too many parameters to `%s' " |
||
1531 | "constructor", |
||
1532 | constructor_type->name); |
||
1533 | return ir_rvalue::error_value(ctx); |
||
1534 | } |
||
1535 | |||
1536 | if (!result->type->is_numeric() && !result->type->is_boolean()) { |
||
1537 | _mesa_glsl_error(& loc, state, "cannot construct `%s' from a " |
||
1538 | "non-numeric data type", |
||
1539 | constructor_type->name); |
||
1540 | return ir_rvalue::error_value(ctx); |
||
1541 | } |
||
1542 | |||
1543 | /* Count the number of matrix and nonmatrix parameters. This |
||
1544 | * is used below to enforce some of the constructor rules. |
||
1545 | */ |
||
1546 | if (result->type->is_matrix()) |
||
1547 | matrix_parameters++; |
||
1548 | else |
||
1549 | nonmatrix_parameters++; |
||
1550 | |||
1551 | actual_parameters.push_tail(result); |
||
1552 | components_used += result->type->components(); |
||
1553 | } |
||
1554 | |||
1555 | /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec: |
||
1556 | * |
||
1557 | * "It is an error to construct matrices from other matrices. This |
||
1558 | * is reserved for future use." |
||
1559 | */ |
||
1560 | if (matrix_parameters > 0 |
||
1561 | && constructor_type->is_matrix() |
||
1562 | && !state->check_version(120, 100, &loc, |
||
1563 | "cannot construct `%s' from a matrix", |
||
1564 | constructor_type->name)) { |
||
1565 | return ir_rvalue::error_value(ctx); |
||
1566 | } |
||
1567 | |||
1568 | /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec: |
||
1569 | * |
||
1570 | * "If a matrix argument is given to a matrix constructor, it is |
||
1571 | * an error to have any other arguments." |
||
1572 | */ |
||
1573 | if ((matrix_parameters > 0) |
||
1574 | && ((matrix_parameters + nonmatrix_parameters) > 1) |
||
1575 | && constructor_type->is_matrix()) { |
||
1576 | _mesa_glsl_error(& loc, state, "for matrix `%s' constructor, " |
||
1577 | "matrix must be only parameter", |
||
1578 | constructor_type->name); |
||
1579 | return ir_rvalue::error_value(ctx); |
||
1580 | } |
||
1581 | |||
1582 | /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec: |
||
1583 | * |
||
1584 | * "In these cases, there must be enough components provided in the |
||
1585 | * arguments to provide an initializer for every component in the |
||
1586 | * constructed value." |
||
1587 | */ |
||
1588 | if (components_used < type_components && components_used != 1 |
||
1589 | && matrix_parameters == 0) { |
||
1590 | _mesa_glsl_error(& loc, state, "too few components to construct " |
||
1591 | "`%s'", |
||
1592 | constructor_type->name); |
||
1593 | return ir_rvalue::error_value(ctx); |
||
1594 | } |
||
1595 | |||
1596 | /* Later, we cast each parameter to the same base type as the |
||
1597 | * constructor. Since there are no non-floating point matrices, we |
||
1598 | * need to break them up into a series of column vectors. |
||
1599 | */ |
||
1600 | if (constructor_type->base_type != GLSL_TYPE_FLOAT) { |
||
1601 | foreach_list_safe(n, &actual_parameters) { |
||
1602 | ir_rvalue *matrix = (ir_rvalue *) n; |
||
1603 | |||
1604 | if (!matrix->type->is_matrix()) |
||
1605 | continue; |
||
1606 | |||
1607 | /* Create a temporary containing the matrix. */ |
||
1608 | ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp", |
||
1609 | ir_var_temporary); |
||
1610 | instructions->push_tail(var); |
||
1611 | instructions->push_tail(new(ctx) ir_assignment(new(ctx) |
||
1612 | ir_dereference_variable(var), matrix, NULL)); |
||
1613 | var->constant_value = matrix->constant_expression_value(); |
||
1614 | |||
1615 | /* Replace the matrix with dereferences of its columns. */ |
||
1616 | for (int i = 0; i < matrix->type->matrix_columns; i++) { |
||
1617 | matrix->insert_before(new (ctx) ir_dereference_array(var, |
||
1618 | new(ctx) ir_constant(i))); |
||
1619 | } |
||
1620 | matrix->remove(); |
||
1621 | } |
||
1622 | } |
||
1623 | |||
1624 | bool all_parameters_are_constant = true; |
||
1625 | |||
1626 | /* Type cast each parameter and, if possible, fold constants.*/ |
||
1627 | foreach_list_safe(n, &actual_parameters) { |
||
1628 | ir_rvalue *ir = (ir_rvalue *) n; |
||
1629 | |||
1630 | const glsl_type *desired_type = |
||
1631 | glsl_type::get_instance(constructor_type->base_type, |
||
1632 | ir->type->vector_elements, |
||
1633 | ir->type->matrix_columns); |
||
1634 | ir_rvalue *result = convert_component(ir, desired_type); |
||
1635 | |||
1636 | /* Attempt to convert the parameter to a constant valued expression. |
||
1637 | * After doing so, track whether or not all the parameters to the |
||
1638 | * constructor are trivially constant valued expressions. |
||
1639 | */ |
||
1640 | ir_rvalue *const constant = result->constant_expression_value(); |
||
1641 | |||
1642 | if (constant != NULL) |
||
1643 | result = constant; |
||
1644 | else |
||
1645 | all_parameters_are_constant = false; |
||
1646 | |||
1647 | if (result != ir) { |
||
1648 | ir->replace_with(result); |
||
1649 | } |
||
1650 | } |
||
1651 | |||
1652 | /* If all of the parameters are trivially constant, create a |
||
1653 | * constant representing the complete collection of parameters. |
||
1654 | */ |
||
1655 | if (all_parameters_are_constant) { |
||
1656 | return new(ctx) ir_constant(constructor_type, &actual_parameters); |
||
1657 | } else if (constructor_type->is_scalar()) { |
||
1658 | return dereference_component((ir_rvalue *) actual_parameters.head, |
||
1659 | 0); |
||
1660 | } else if (constructor_type->is_vector()) { |
||
1661 | return emit_inline_vector_constructor(constructor_type, |
||
1662 | instructions, |
||
1663 | &actual_parameters, |
||
1664 | ctx); |
||
1665 | } else { |
||
1666 | assert(constructor_type->is_matrix()); |
||
1667 | return emit_inline_matrix_constructor(constructor_type, |
||
1668 | instructions, |
||
1669 | &actual_parameters, |
||
1670 | ctx); |
||
1671 | } |
||
1672 | } else { |
||
1673 | const ast_expression *id = subexpressions[0]; |
||
1674 | const char *func_name = id->primary_expression.identifier; |
||
1675 | YYLTYPE loc = id->get_location(); |
||
1676 | exec_list actual_parameters; |
||
1677 | |||
1678 | process_parameters(instructions, &actual_parameters, &this->expressions, |
||
1679 | state); |
||
1680 | |||
1681 | ir_function_signature *sig = |
||
1682 | match_function_by_name(func_name, &actual_parameters, state); |
||
1683 | |||
1684 | ir_call *call = NULL; |
||
1685 | ir_rvalue *value = NULL; |
||
1686 | if (sig == NULL) { |
||
1687 | no_matching_function_error(func_name, &loc, &actual_parameters, state); |
||
1688 | value = ir_rvalue::error_value(ctx); |
||
1689 | } else if (!verify_parameter_modes(state, sig, actual_parameters, this->expressions)) { |
||
1690 | /* an error has already been emitted */ |
||
1691 | value = ir_rvalue::error_value(ctx); |
||
1692 | } else { |
||
1693 | value = generate_call(instructions, sig, &actual_parameters, |
||
1694 | &call, state); |
||
1695 | } |
||
1696 | |||
1697 | return value; |
||
1698 | } |
||
1699 | |||
1700 | return ir_rvalue::error_value(ctx); |
||
1701 | } |
||
1702 | |||
1703 | ir_rvalue * |
||
1704 | ast_aggregate_initializer::hir(exec_list *instructions, |
||
1705 | struct _mesa_glsl_parse_state *state) |
||
1706 | { |
||
1707 | void *ctx = state; |
||
1708 | YYLTYPE loc = this->get_location(); |
||
1709 | const char *name; |
||
1710 | |||
1711 | if (!this->constructor_type) { |
||
1712 | _mesa_glsl_error(&loc, state, "type of C-style initializer unknown"); |
||
1713 | return ir_rvalue::error_value(ctx); |
||
1714 | } |
||
1715 | const glsl_type *const constructor_type = |
||
1716 | this->constructor_type->glsl_type(&name, state); |
||
1717 | |||
1718 | if (!state->ARB_shading_language_420pack_enable) { |
||
1719 | _mesa_glsl_error(&loc, state, "C-style initialization requires the " |
||
1720 | "GL_ARB_shading_language_420pack extension"); |
||
1721 | return ir_rvalue::error_value(ctx); |
||
1722 | } |
||
1723 | |||
1724 | if (this->constructor_type->is_array) { |
||
1725 | return process_array_constructor(instructions, constructor_type, &loc, |
||
1726 | &this->expressions, state); |
||
1727 | } |
||
1728 | |||
1729 | if (this->constructor_type->structure) { |
||
1730 | return process_record_constructor(instructions, constructor_type, &loc, |
||
1731 | &this->expressions, state); |
||
1732 | } |
||
1733 | |||
1734 | return process_vec_mat_constructor(instructions, constructor_type, &loc, |
||
1735 | &this->expressions, state); |
||
1736 | }>>>>>>>><>>>>>>>>><>><>>><>><>><>><>>><>=>=>>=>=>>> |