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_to_mesa.cpp
27 * Translates the IR to ARB_fragment_program text if possible,
31 /* Quiet compiler warnings due to monoburg not marking functions defined
32 * in the header as inline.
36 #include "mesa_codegen.h"
39 #include "ir_visitor.h"
40 #include "ir_print_visitor.h"
41 #include "ir_expression_flattening.h"
42 #include "glsl_types.h"
45 #include "shader/prog_instruction.h"
46 #include "shader/prog_print.h"
49 ir_to_mesa_src_reg ir_to_mesa_undef
= {
50 PROGRAM_UNDEFINED
, 0, SWIZZLE_NOOP
, NEGATE_NONE
, false,
53 ir_to_mesa_dst_reg ir_to_mesa_undef_dst
= {
54 PROGRAM_UNDEFINED
, 0, SWIZZLE_NOOP
57 ir_to_mesa_instruction
*
58 ir_to_mesa_emit_op3(ir_to_mesa_visitor
*v
, ir_instruction
*ir
,
60 ir_to_mesa_dst_reg dst
,
61 ir_to_mesa_src_reg src0
,
62 ir_to_mesa_src_reg src1
,
63 ir_to_mesa_src_reg src2
)
65 ir_to_mesa_instruction
*inst
= new ir_to_mesa_instruction();
69 inst
->src_reg
[0] = src0
;
70 inst
->src_reg
[1] = src1
;
71 inst
->src_reg
[2] = src2
;
74 v
->instructions
.push_tail(inst
);
80 ir_to_mesa_instruction
*
81 ir_to_mesa_emit_op2_full(ir_to_mesa_visitor
*v
, ir_instruction
*ir
,
83 ir_to_mesa_dst_reg dst
,
84 ir_to_mesa_src_reg src0
,
85 ir_to_mesa_src_reg src1
)
87 return ir_to_mesa_emit_op3(v
, ir
,
88 op
, dst
, src0
, src1
, ir_to_mesa_undef
);
91 ir_to_mesa_instruction
*
92 ir_to_mesa_emit_op2(struct mbtree
*tree
, enum prog_opcode op
)
94 return ir_to_mesa_emit_op2_full(tree
->v
, tree
->ir
, op
,
97 tree
->right
->src_reg
);
100 ir_to_mesa_instruction
*
101 ir_to_mesa_emit_op1_full(ir_to_mesa_visitor
*v
, ir_instruction
*ir
,
103 ir_to_mesa_dst_reg dst
,
104 ir_to_mesa_src_reg src0
)
106 return ir_to_mesa_emit_op3(v
, ir
, op
,
107 dst
, src0
, ir_to_mesa_undef
, ir_to_mesa_undef
);
110 ir_to_mesa_instruction
*
111 ir_to_mesa_emit_op1(struct mbtree
*tree
, enum prog_opcode op
)
113 return ir_to_mesa_emit_op1_full(tree
->v
, tree
->ir
, op
,
115 tree
->left
->src_reg
);
119 * Emits Mesa scalar opcodes to produce unique answers across channels.
121 * Some Mesa opcodes are scalar-only, like ARB_fp/vp. The src X
122 * channel determines the result across all channels. So to do a vec4
123 * of this operation, we want to emit a scalar per source channel used
124 * to produce dest channels.
127 ir_to_mesa_emit_scalar_op1(struct mbtree
*tree
, enum prog_opcode op
,
128 ir_to_mesa_dst_reg dst
,
129 ir_to_mesa_src_reg src0
)
132 int done_mask
= ~dst
.writemask
;
134 /* Mesa RCP is a scalar operation splatting results to all channels,
135 * like ARB_fp/vp. So emit as many RCPs as necessary to cover our
138 for (i
= 0; i
< 4; i
++) {
139 int this_mask
= (1 << i
);
140 ir_to_mesa_instruction
*inst
;
141 ir_to_mesa_src_reg src
= src0
;
143 if (done_mask
& this_mask
)
146 int src_swiz
= GET_SWZ(src
.swizzle
, i
);
147 for (j
= i
+ 1; j
< 4; j
++) {
148 if (!(done_mask
& (1 << j
)) && GET_SWZ(src
.swizzle
, j
) == src_swiz
) {
149 this_mask
|= (1 << j
);
152 src
.swizzle
= MAKE_SWIZZLE4(src_swiz
, src_swiz
,
155 inst
= ir_to_mesa_emit_op1_full(tree
->v
, tree
->ir
, op
,
158 inst
->dst_reg
.writemask
= this_mask
;
159 done_mask
|= this_mask
;
164 ir_to_mesa_set_tree_reg(struct mbtree
*tree
, int file
, int index
)
166 tree
->dst_reg
.file
= file
;
167 tree
->dst_reg
.index
= index
;
169 tree
->src_reg
.file
= file
;
170 tree
->src_reg
.index
= index
;
174 ir_to_mesa_visitor::create_tree(int op
,
176 struct mbtree
*left
, struct mbtree
*right
)
178 struct mbtree
*tree
= (struct mbtree
*)calloc(sizeof(struct mbtree
), 1);
186 tree
->src_reg
.swizzle
= SWIZZLE_XYZW
;
187 tree
->src_reg
.negate
= 0;
188 tree
->dst_reg
.writemask
= WRITEMASK_XYZW
;
189 ir_to_mesa_set_tree_reg(tree
, PROGRAM_UNDEFINED
, 0);
196 ir_to_mesa_visitor::create_tree_for_float(ir_instruction
*ir
, float val
)
198 struct mbtree
*tree
= (struct mbtree
*)calloc(sizeof(struct mbtree
), 1);
200 tree
= this->create_tree(MB_TERM_reference_vec4
, ir
, NULL
, NULL
);
202 /* FINISHME: This will end up being _mesa_add_unnamed_constant,
203 * which handles sharing values and sharing channels of vec4
204 * constants for small values.
206 /* FINISHME: Do something with the constant values for now.
209 ir_to_mesa_set_tree_reg(tree
, PROGRAM_CONSTANT
, this->next_constant
++);
210 tree
->src_reg
.swizzle
= SWIZZLE_NOOP
;
217 * In the initial pass of codegen, we assign temporary numbers to
218 * intermediate results. (not SSA -- variable assignments will reuse
219 * storage). Actual register allocation for the Mesa VM occurs in a
220 * pass over the Mesa IR later.
223 ir_to_mesa_visitor::get_temp(struct mbtree
*tree
, int size
)
228 ir_to_mesa_set_tree_reg(tree
, PROGRAM_TEMPORARY
, this->next_temp
++);
230 for (i
= 0; i
< size
; i
++)
233 swizzle
[i
] = size
- 1;
234 tree
->src_reg
.swizzle
= MAKE_SWIZZLE4(swizzle
[0], swizzle
[1],
235 swizzle
[2], swizzle
[3]);
236 tree
->dst_reg
.writemask
= (1 << size
) - 1;
240 type_size(const struct glsl_type
*type
)
245 switch (type
->base_type
) {
248 case GLSL_TYPE_FLOAT
:
250 assert(!type
->is_matrix());
251 /* Regardless of size of vector, it gets a vec4. This is bad
252 * packing for things like floats, but otherwise arrays become a
253 * mess. Hopefully a later pass over the code can pack scalars
254 * down if appropriate.
257 case GLSL_TYPE_ARRAY
:
258 return type_size(type
->fields
.array
) * type
->length
;
259 case GLSL_TYPE_STRUCT
:
261 for (i
= 0; i
< type
->length
; i
++) {
262 size
+= type_size(type
->fields
.structure
[i
].type
);
271 ir_to_mesa_visitor::get_temp_for_var(ir_variable
*var
, struct mbtree
*tree
)
275 foreach_iter(exec_list_iterator
, iter
, this->variable_storage
) {
276 entry
= (temp_entry
*)iter
.get();
278 if (entry
->var
== var
) {
279 ir_to_mesa_set_tree_reg(tree
, entry
->file
, entry
->index
);
284 entry
= new temp_entry(var
, PROGRAM_TEMPORARY
, this->next_temp
);
285 this->variable_storage
.push_tail(entry
);
287 next_temp
+= type_size(var
->type
);
289 ir_to_mesa_set_tree_reg(tree
, entry
->file
, entry
->index
);
293 reduce(struct mbtree
*t
, int goal
)
295 struct mbtree
*kids
[10];
296 int rule
= mono_burg_rule((MBState
*)t
->state
, goal
);
297 const uint16_t *nts
= mono_burg_nts
[rule
];
300 mono_burg_kids (t
, rule
, kids
);
302 for (i
= 0; nts
[i
]; i
++) {
303 reduce(kids
[i
], nts
[i
]);
307 if (mono_burg_func
[rule
]) {
308 mono_burg_func
[rule
](t
, NULL
);
310 printf("no code for rules %s\n", mono_burg_rule_string
[rule
]);
314 if (mono_burg_func
[rule
]) {
315 printf("unused code for rule %s\n", mono_burg_rule_string
[rule
]);
322 ir_to_mesa_visitor::visit(ir_variable
*ir
)
328 ir_to_mesa_visitor::visit(ir_loop
*ir
)
332 assert(!ir
->increment
);
333 assert(!ir
->counter
);
335 ir_to_mesa_emit_op1_full(this, NULL
,
336 OPCODE_BGNLOOP
, ir_to_mesa_undef_dst
,
339 visit_exec_list(&ir
->body_instructions
, this);
341 ir_to_mesa_emit_op1_full(this, NULL
,
342 OPCODE_ENDLOOP
, ir_to_mesa_undef_dst
,
347 ir_to_mesa_visitor::visit(ir_loop_jump
*ir
)
350 case ir_loop_jump::jump_break
:
351 ir_to_mesa_emit_op1_full(this, NULL
,
352 OPCODE_BRK
, ir_to_mesa_undef_dst
,
355 case ir_loop_jump::jump_continue
:
356 ir_to_mesa_emit_op1_full(this, NULL
,
357 OPCODE_CONT
, ir_to_mesa_undef_dst
,
365 ir_to_mesa_visitor::visit(ir_function_signature
*ir
)
372 ir_to_mesa_visitor::visit(ir_function
*ir
)
374 /* Ignore function bodies other than main() -- we shouldn't see calls to
375 * them since they should all be inlined before we get to ir_to_mesa.
377 if (strcmp(ir
->name
, "main") == 0) {
378 const ir_function_signature
*sig
;
381 sig
= ir
->matching_signature(&empty
);
385 foreach_iter(exec_list_iterator
, iter
, sig
->body
) {
386 ir_instruction
*ir
= (ir_instruction
*)iter
.get();
394 ir_to_mesa_visitor::visit(ir_expression
*ir
)
396 unsigned int operand
;
397 struct mbtree
*op
[2];
398 const glsl_type
*vec4_type
= glsl_type::get_instance(GLSL_TYPE_FLOAT
, 4, 1);
399 const glsl_type
*vec3_type
= glsl_type::get_instance(GLSL_TYPE_FLOAT
, 3, 1);
400 const glsl_type
*vec2_type
= glsl_type::get_instance(GLSL_TYPE_FLOAT
, 2, 1);
402 for (operand
= 0; operand
< ir
->get_num_operands(); operand
++) {
404 ir
->operands
[operand
]->accept(this);
407 printf("Failed to get tree for expression operand:\n");
408 ir
->operands
[operand
]->accept(&v
);
411 op
[operand
] = this->result
;
416 switch (ir
->operation
) {
417 case ir_unop_logic_not
:
418 this->result
= this->create_tree_for_float(ir
, 0.0);
419 this->result
= this->create_tree(MB_TERM_seq_vec4_vec4
, ir
,
420 op
[0], this->result
);
423 op
[0]->src_reg
.negate
= ~op
[0]->src_reg
.negate
;
424 this->result
= op
[0];
427 this->result
= this->create_tree(MB_TERM_exp_vec4
, ir
, op
[0], NULL
);
430 this->result
= this->create_tree(MB_TERM_exp2_vec4
, ir
, op
[0], NULL
);
433 this->result
= this->create_tree(MB_TERM_log_vec4
, ir
, op
[0], NULL
);
436 this->result
= this->create_tree(MB_TERM_log2_vec4
, ir
, op
[0], NULL
);
439 this->result
= this->create_tree(MB_TERM_sin_vec4
, ir
, op
[0], NULL
);
442 this->result
= this->create_tree(MB_TERM_cos_vec4
, ir
, op
[0], NULL
);
445 this->result
= this->create_tree(MB_TERM_add_vec4_vec4
, ir
, op
[0], op
[1]);
448 this->result
= this->create_tree(MB_TERM_sub_vec4_vec4
, ir
, op
[0], op
[1]);
451 this->result
= this->create_tree(MB_TERM_mul_vec4_vec4
, ir
, op
[0], op
[1]);
454 this->result
= this->create_tree(MB_TERM_div_vec4_vec4
, ir
, op
[0], op
[1]);
458 this->result
= this->create_tree(MB_TERM_slt_vec4_vec4
, ir
, op
[0], op
[1]);
460 case ir_binop_greater
:
461 this->result
= this->create_tree(MB_TERM_sgt_vec4_vec4
, ir
, op
[0], op
[1]);
463 case ir_binop_lequal
:
464 this->result
= this->create_tree(MB_TERM_sle_vec4_vec4
, ir
, op
[0], op
[1]);
466 case ir_binop_gequal
:
467 this->result
= this->create_tree(MB_TERM_sge_vec4_vec4
, ir
, op
[0], op
[1]);
470 this->result
= this->create_tree(MB_TERM_seq_vec4_vec4
, ir
, op
[0], op
[1]);
472 case ir_binop_logic_xor
:
473 case ir_binop_nequal
:
474 this->result
= this->create_tree(MB_TERM_sne_vec4_vec4
, ir
, op
[0], op
[1]);
477 case ir_binop_logic_or
:
478 /* This could be a saturated add. */
479 this->result
= this->create_tree(MB_TERM_add_vec4_vec4
, ir
, op
[0], op
[1]);
480 this->result
= this->create_tree(MB_TERM_sne_vec4_vec4
, ir
,
481 this->create_tree_for_float(ir
, 0.0),
485 case ir_binop_logic_and
:
486 /* the bool args are stored as float 0.0 or 1.0, so "mul" gives us "and". */
487 this->result
= this->create_tree(MB_TERM_mul_vec4_vec4
, ir
, op
[0], op
[1]);
491 if (ir
->operands
[0]->type
== vec4_type
) {
492 assert(ir
->operands
[1]->type
== vec4_type
);
493 this->result
= this->create_tree(MB_TERM_dp4_vec4_vec4
,
495 } else if (ir
->operands
[0]->type
== vec3_type
) {
496 assert(ir
->operands
[1]->type
== vec3_type
);
497 this->result
= this->create_tree(MB_TERM_dp3_vec4_vec4
,
499 } else if (ir
->operands
[0]->type
== vec2_type
) {
500 assert(ir
->operands
[1]->type
== vec2_type
);
501 this->result
= this->create_tree(MB_TERM_dp2_vec4_vec4
,
506 this->result
= this->create_tree(MB_TERM_sqrt_vec4
, ir
, op
[0], op
[1]);
509 this->result
= this->create_tree(MB_TERM_rsq_vec4
, ir
, op
[0], op
[1]);
512 /* Mesa IR lacks types, ints are stored as truncated floats. */
513 this->result
= op
[0];
516 this->result
= this->create_tree(MB_TERM_trunc_vec4
, ir
, op
[0], NULL
);
519 this->result
= this->create_tree_for_float(ir
, 0.0);
520 this->result
= this->create_tree(MB_TERM_sne_vec4_vec4
, ir
,
521 op
[0], this->result
);
524 this->result
= this->create_tree(MB_TERM_trunc_vec4
, ir
, op
[0], NULL
);
527 this->result
= this->create_tree(MB_TERM_ceil_vec4
, ir
, op
[0], NULL
);
530 this->result
= this->create_tree(MB_TERM_floor_vec4
, ir
, op
[0], NULL
);
533 this->result
= this->create_tree(MB_TERM_min_vec4_vec4
, ir
, op
[0], op
[1]);
536 this->result
= this->create_tree(MB_TERM_max_vec4_vec4
, ir
, op
[0], op
[1]);
543 printf("Failed to get tree for expression:\n");
548 /* Allocate a temporary for the result. */
549 this->get_temp(this->result
, ir
->type
->vector_elements
);
554 ir_to_mesa_visitor::visit(ir_swizzle
*ir
)
560 /* Note that this is only swizzles in expressions, not those on the left
561 * hand side of an assignment, which do write masking. See ir_assignment
565 ir
->val
->accept(this);
566 assert(this->result
);
568 tree
= this->create_tree(MB_TERM_swizzle_vec4
, ir
, this->result
, NULL
);
569 this->get_temp(tree
, 4);
571 for (i
= 0; i
< 4; i
++) {
572 if (i
< ir
->type
->vector_elements
) {
575 swizzle
[i
] = ir
->mask
.x
;
578 swizzle
[i
] = ir
->mask
.y
;
581 swizzle
[i
] = ir
->mask
.z
;
584 swizzle
[i
] = ir
->mask
.w
;
588 /* If the type is smaller than a vec4, replicate the last
591 swizzle
[i
] = ir
->type
->vector_elements
- 1;
595 tree
->src_reg
.swizzle
= MAKE_SWIZZLE4(swizzle
[0],
603 /* This list should match up with builtin_variables.h */
604 static const struct {
608 } builtin_var_to_mesa_reg
[] = {
610 {"gl_Position", PROGRAM_OUTPUT
, VERT_RESULT_HPOS
},
611 {"gl_PointSize", PROGRAM_OUTPUT
, VERT_RESULT_PSIZ
},
614 {"gl_FragCoord", PROGRAM_INPUT
, FRAG_ATTRIB_WPOS
},
615 {"gl_FrontFacing", PROGRAM_INPUT
, FRAG_ATTRIB_FACE
},
616 {"gl_FragColor", PROGRAM_INPUT
, FRAG_ATTRIB_COL0
},
617 {"gl_FragDepth", PROGRAM_UNDEFINED
, FRAG_ATTRIB_WPOS
}, /* FINISHME: WPOS.z */
619 /* 110_deprecated_fs */
620 {"gl_Color", PROGRAM_INPUT
, FRAG_ATTRIB_COL0
},
621 {"gl_SecondaryColor", PROGRAM_INPUT
, FRAG_ATTRIB_COL1
},
622 {"gl_FogFragCoord", PROGRAM_INPUT
, FRAG_ATTRIB_FOGC
},
624 /* 110_deprecated_vs */
625 {"gl_Vertex", PROGRAM_INPUT
, VERT_ATTRIB_POS
},
626 {"gl_Normal", PROGRAM_INPUT
, VERT_ATTRIB_NORMAL
},
627 {"gl_Color", PROGRAM_INPUT
, VERT_ATTRIB_COLOR0
},
628 {"gl_SecondaryColor", PROGRAM_INPUT
, VERT_ATTRIB_COLOR1
},
629 {"gl_MultiTexCoord0", PROGRAM_INPUT
, VERT_ATTRIB_TEX0
},
630 {"gl_MultiTexCoord1", PROGRAM_INPUT
, VERT_ATTRIB_TEX1
},
631 {"gl_MultiTexCoord2", PROGRAM_INPUT
, VERT_ATTRIB_TEX2
},
632 {"gl_MultiTexCoord3", PROGRAM_INPUT
, VERT_ATTRIB_TEX3
},
633 {"gl_MultiTexCoord4", PROGRAM_INPUT
, VERT_ATTRIB_TEX4
},
634 {"gl_MultiTexCoord5", PROGRAM_INPUT
, VERT_ATTRIB_TEX5
},
635 {"gl_MultiTexCoord6", PROGRAM_INPUT
, VERT_ATTRIB_TEX6
},
636 {"gl_MultiTexCoord7", PROGRAM_INPUT
, VERT_ATTRIB_TEX7
},
637 {"gl_TexCoord", PROGRAM_OUTPUT
, VERT_RESULT_TEX0
}, /* array */
638 {"gl_FogCoord", PROGRAM_INPUT
, VERT_RESULT_FOGC
},
639 /*{"gl_ClipVertex", PROGRAM_OUTPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */
640 {"gl_FrontColor", PROGRAM_OUTPUT
, VERT_RESULT_COL0
},
641 {"gl_BackColor", PROGRAM_OUTPUT
, VERT_RESULT_BFC0
},
642 {"gl_FrontSecondaryColor", PROGRAM_OUTPUT
, VERT_RESULT_COL1
},
643 {"gl_BackSecondaryColor", PROGRAM_OUTPUT
, VERT_RESULT_BFC1
},
644 {"gl_FogFragCoord", PROGRAM_OUTPUT
, VERT_RESULT_FOGC
},
647 /*{"gl_VertexID", PROGRAM_INPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */
649 {"gl_FragData", PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
}, /* array */
653 ir_to_mesa_visitor::visit(ir_dereference_variable
*ir
)
656 int size_swizzles
[4] = {
657 MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_X
, SWIZZLE_X
, SWIZZLE_X
),
658 MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Y
, SWIZZLE_Y
),
659 MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Z
, SWIZZLE_Z
),
660 MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Z
, SWIZZLE_W
),
663 /* By the time we make it to this stage, matrices should be broken down
666 assert(!ir
->var
->type
->is_matrix());
668 tree
= this->create_tree(MB_TERM_reference_vec4
, ir
, NULL
, NULL
);
670 if (strncmp(ir
->var
->name
, "gl_", 3) == 0) {
673 for (i
= 0; i
< ARRAY_SIZE(builtin_var_to_mesa_reg
); i
++) {
674 if (strcmp(ir
->var
->name
, builtin_var_to_mesa_reg
[i
].name
) == 0)
677 assert(i
!= ARRAY_SIZE(builtin_var_to_mesa_reg
));
678 ir_to_mesa_set_tree_reg(tree
, builtin_var_to_mesa_reg
[i
].file
,
679 builtin_var_to_mesa_reg
[i
].index
);
681 this->get_temp_for_var(ir
->var
, tree
);
684 /* If the type is smaller than a vec4, replicate the last channel out. */
685 tree
->src_reg
.swizzle
= size_swizzles
[ir
->type
->vector_elements
- 1];
691 ir_to_mesa_visitor::visit(ir_dereference_array
*ir
)
694 int size_swizzles
[4] = {
695 MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Z
, SWIZZLE_W
),
696 MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Z
, SWIZZLE_Z
),
697 MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Y
, SWIZZLE_Y
),
698 MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_X
, SWIZZLE_X
, SWIZZLE_X
),
702 index
= ir
->array_index
->constant_expression_value();
704 /* By the time we make it to this stage, matrices should be broken down
707 assert(!ir
->type
->is_matrix());
709 ir
->array
->accept(this);
712 if (tree
->src_reg
.file
== PROGRAM_INPUT
||
713 tree
->src_reg
.file
== PROGRAM_OUTPUT
) {
714 assert(index
); /* FINISHME: Handle variable indexing of builtins. */
716 tree
->src_reg
.index
+= index
->value
.i
[0];
717 tree
->dst_reg
.index
+= index
->value
.i
[0];
720 tree
->src_reg
.index
+= index
->value
.i
[0];
721 tree
->dst_reg
.index
+= index
->value
.i
[0];
723 /* Variable index array dereference. It eats the "vec4" of the
724 * base of the array and an index that offsets the Mesa register
727 ir
->array_index
->accept(this);
729 tree
->src_reg
.reladdr
= true;
730 tree
= this->create_tree(MB_TERM_array_reference_vec4_vec4
,
731 ir
, tree
, this->result
);
732 this->get_temp(tree
, ir
->type
->vector_elements
);
736 /* If the type is smaller than a vec4, replicate the last channel out. */
737 tree
->src_reg
.swizzle
= size_swizzles
[ir
->type
->vector_elements
- 1];
743 ir_to_mesa_visitor::visit(ir_dereference_record
*ir
)
745 ir_variable
*var
= ir
->variable_referenced();
746 const char *field
= ir
->field
;
750 const glsl_type
*struct_type
= var
->type
;
753 tree
= this->create_tree(MB_TERM_reference_vec4
, ir
, NULL
, NULL
);
754 this->get_temp_for_var(var
, tree
);
756 for (i
= 0; i
< struct_type
->length
; i
++) {
757 if (strcmp(struct_type
->fields
.structure
[i
].name
, field
) == 0)
759 offset
+= type_size(struct_type
->fields
.structure
[i
].type
);
761 tree
->src_reg
.index
+= offset
;
762 tree
->dst_reg
.index
+= offset
;
766 * We want to be careful in assignment setup to hit the actual storage
767 * instead of potentially using a temporary like we might with the
768 * ir_dereference handler.
770 * Thanks to ir_swizzle_swizzle, and ir_vec_index_to_swizzle, we
771 * should only see potentially one variable array index of a vector,
772 * and one swizzle, before getting to actual vec4 storage. So handle
773 * those, then go use ir_dereference to handle the rest.
775 static struct mbtree
*
776 get_assignment_lhs(ir_instruction
*ir
, ir_to_mesa_visitor
*v
)
778 struct mbtree
*tree
= NULL
;
779 ir_dereference
*deref
;
785 if ((deref
= ir
->as_dereference())) {
786 ir_dereference_array
*deref_array
= ir
->as_dereference_array();
787 assert(!deref_array
|| deref_array
->array
->type
->is_array());
791 } else if ((swiz
= ir
->as_swizzle())) {
792 tree
->dst_reg
.writemask
= 0;
793 if (swiz
->mask
.num_components
>= 1)
794 tree
->dst_reg
.writemask
|= (1 << swiz
->mask
.x
);
795 if (swiz
->mask
.num_components
>= 2)
796 tree
->dst_reg
.writemask
|= (1 << swiz
->mask
.y
);
797 if (swiz
->mask
.num_components
>= 3)
798 tree
->dst_reg
.writemask
|= (1 << swiz
->mask
.z
);
799 if (swiz
->mask
.num_components
>= 4)
800 tree
->dst_reg
.writemask
|= (1 << swiz
->mask
.w
);
809 ir_to_mesa_visitor::visit(ir_assignment
*ir
)
811 struct mbtree
*l
, *r
, *t
;
813 assert(!ir
->lhs
->type
->is_matrix());
814 assert(!ir
->lhs
->type
->is_array());
815 assert(ir
->lhs
->type
->base_type
!= GLSL_TYPE_STRUCT
);
817 l
= get_assignment_lhs(ir
->lhs
, this);
819 ir
->rhs
->accept(this);
825 ir_constant
*condition_constant
;
827 condition_constant
= ir
->condition
->constant_expression_value();
829 assert(condition_constant
&& condition_constant
->value
.b
[0]);
832 t
= this->create_tree(MB_TERM_assign
, ir
, l
, r
);
833 mono_burg_label(t
, NULL
);
834 reduce(t
, MB_NTERM_stmt
);
839 ir_to_mesa_visitor::visit(ir_constant
*ir
)
843 assert(!ir
->type
->is_matrix());
845 tree
= this->create_tree(MB_TERM_reference_vec4
, ir
, NULL
, NULL
);
847 assert(ir
->type
->base_type
== GLSL_TYPE_FLOAT
||
848 ir
->type
->base_type
== GLSL_TYPE_UINT
||
849 ir
->type
->base_type
== GLSL_TYPE_INT
||
850 ir
->type
->base_type
== GLSL_TYPE_BOOL
);
852 /* FINISHME: This will end up being _mesa_add_unnamed_constant,
853 * which handles sharing values and sharing channels of vec4
854 * constants for small values.
856 /* FINISHME: Do something with the constant values for now.
858 ir_to_mesa_set_tree_reg(tree
, PROGRAM_CONSTANT
, this->next_constant
++);
859 tree
->src_reg
.swizzle
= SWIZZLE_NOOP
;
866 ir_to_mesa_visitor::visit(ir_call
*ir
)
868 printf("Can't support call to %s\n", ir
->callee_name());
874 ir_to_mesa_visitor::visit(ir_texture
*ir
)
878 ir
->coordinate
->accept(this);
882 ir_to_mesa_visitor::visit(ir_return
*ir
)
886 ir
->get_value()->accept(this);
891 ir_to_mesa_visitor::visit(ir_if
*ir
)
893 ir_to_mesa_instruction
*if_inst
, *else_inst
= NULL
;
895 ir
->condition
->accept(this);
896 assert(this->result
);
898 if_inst
= ir_to_mesa_emit_op1_full(this, ir
->condition
,
899 OPCODE_IF
, ir_to_mesa_undef_dst
,
900 this->result
->src_reg
);
902 this->instructions
.push_tail(if_inst
);
904 visit_exec_list(&ir
->then_instructions
, this);
906 if (!ir
->else_instructions
.is_empty()) {
907 else_inst
= ir_to_mesa_emit_op1_full(this, ir
->condition
,
908 OPCODE_ELSE
, ir_to_mesa_undef_dst
,
910 visit_exec_list(&ir
->then_instructions
, this);
913 if_inst
= ir_to_mesa_emit_op1_full(this, ir
->condition
,
914 OPCODE_ENDIF
, ir_to_mesa_undef_dst
,
918 ir_to_mesa_visitor::ir_to_mesa_visitor()
925 static struct prog_src_register
926 mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg
)
928 struct prog_src_register mesa_reg
;
930 mesa_reg
.File
= reg
.file
;
931 assert(reg
.index
< (1 << INST_INDEX_BITS
) - 1);
932 mesa_reg
.Index
= reg
.index
;
933 mesa_reg
.Swizzle
= reg
.swizzle
;
934 mesa_reg
.RelAddr
= reg
.reladdr
;
940 set_branchtargets(struct prog_instruction
*mesa_instructions
,
941 int num_instructions
)
943 int if_count
= 0, loop_count
;
944 int *if_stack
, *loop_stack
;
945 int if_stack_pos
= 0, loop_stack_pos
= 0;
948 for (i
= 0; i
< num_instructions
; i
++) {
949 switch (mesa_instructions
[i
].Opcode
) {
958 mesa_instructions
[i
].BranchTarget
= -1;
965 if_stack
= (int *)calloc(if_count
, sizeof(*if_stack
));
966 loop_stack
= (int *)calloc(loop_count
, sizeof(*loop_stack
));
968 for (i
= 0; i
< num_instructions
; i
++) {
969 switch (mesa_instructions
[i
].Opcode
) {
971 if_stack
[if_stack_pos
] = i
;
975 mesa_instructions
[if_stack
[if_stack_pos
- 1]].BranchTarget
= i
;
976 if_stack
[if_stack_pos
- 1] = i
;
979 mesa_instructions
[if_stack
[if_stack_pos
- 1]].BranchTarget
= i
;
983 loop_stack
[loop_stack_pos
] = i
;
988 /* Rewrite any breaks/conts at this nesting level (haven't
989 * already had a BranchTarget assigned) to point to the end
992 for (j
= loop_stack
[loop_stack_pos
]; j
< i
; j
++) {
993 if (mesa_instructions
[j
].Opcode
== OPCODE_BRK
||
994 mesa_instructions
[j
].Opcode
== OPCODE_CONT
) {
995 if (mesa_instructions
[j
].BranchTarget
== -1) {
996 mesa_instructions
[j
].BranchTarget
= i
;
1000 /* The loop ends point at each other. */
1001 mesa_instructions
[i
].BranchTarget
= loop_stack
[loop_stack_pos
];
1002 mesa_instructions
[loop_stack
[loop_stack_pos
]].BranchTarget
= i
;
1012 print_program(struct prog_instruction
*mesa_instructions
,
1013 ir_instruction
**mesa_instruction_annotation
,
1014 int num_instructions
)
1016 ir_instruction
*last_ir
= NULL
;
1019 for (i
= 0; i
< num_instructions
; i
++) {
1020 struct prog_instruction
*mesa_inst
= mesa_instructions
+ i
;
1021 ir_instruction
*ir
= mesa_instruction_annotation
[i
];
1023 if (last_ir
!= ir
&& ir
) {
1024 ir_print_visitor print
;
1030 _mesa_print_instruction(mesa_inst
);
1035 do_ir_to_mesa(exec_list
*instructions
)
1037 ir_to_mesa_visitor v
;
1038 struct prog_instruction
*mesa_instructions
, *mesa_inst
;
1039 ir_instruction
**mesa_instruction_annotation
;
1042 visit_exec_list(instructions
, &v
);
1044 int num_instructions
= 0;
1045 foreach_iter(exec_list_iterator
, iter
, v
.instructions
) {
1050 (struct prog_instruction
*)calloc(num_instructions
,
1051 sizeof(*mesa_instructions
));
1052 mesa_instruction_annotation
=
1053 (ir_instruction
**)calloc(num_instructions
,
1054 sizeof(*mesa_instruction_annotation
));
1056 mesa_inst
= mesa_instructions
;
1058 foreach_iter(exec_list_iterator
, iter
, v
.instructions
) {
1059 ir_to_mesa_instruction
*inst
= (ir_to_mesa_instruction
*)iter
.get();
1061 mesa_inst
->Opcode
= inst
->op
;
1062 mesa_inst
->DstReg
.File
= inst
->dst_reg
.file
;
1063 mesa_inst
->DstReg
.Index
= inst
->dst_reg
.index
;
1064 mesa_inst
->DstReg
.CondMask
= COND_TR
;
1065 mesa_inst
->DstReg
.WriteMask
= inst
->dst_reg
.writemask
;
1066 mesa_inst
->SrcReg
[0] = mesa_src_reg_from_ir_src_reg(inst
->src_reg
[0]);
1067 mesa_inst
->SrcReg
[1] = mesa_src_reg_from_ir_src_reg(inst
->src_reg
[1]);
1068 mesa_inst
->SrcReg
[2] = mesa_src_reg_from_ir_src_reg(inst
->src_reg
[2]);
1069 mesa_instruction_annotation
[i
] = inst
->ir
;
1075 set_branchtargets(mesa_instructions
, num_instructions
);
1076 print_program(mesa_instructions
, mesa_instruction_annotation
, num_instructions
);
1078 free(mesa_instruction_annotation
);