diff options
author | Eric Anholt <eric@anholt.net> | 2010-06-02 17:43:43 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-06-24 15:05:21 -0700 |
commit | 0161515c395c44233529c8d51f823b60050bc7ba (patch) | |
tree | 519436e6362c0b705258d6a408ae762a5a4e9002 | |
parent | 224f712950494730c76b48864f2ca19acde1c8cf (diff) |
ir_to_mesa: Remove the BURG code.
The promise of the BURG was to recognize multi-instruction sequences
and emit reduced sequences for them. It would have worked well for
recognizing MUL+ADD -> MAD and possibly even MIN(MAX(val, 0), 1) ->
MOV_SAT with some grammar changes. However, that potential benefit in
making those optimizations easy is outweighed by the fragility of
monoburg, the amount of (incorrect, as I wrote it) code for using it,
and the burden it was going to cause for handling operations on
aggregate types.
-rw-r--r-- | Makefile.am | 10 | ||||
-rw-r--r-- | ir_to_mesa.cpp | 509 | ||||
-rw-r--r-- | ir_to_mesa.h | 81 | ||||
-rw-r--r-- | mesa_codegen.brg | 281 |
4 files changed, 258 insertions, 623 deletions
diff --git a/Makefile.am b/Makefile.am index bf062595a9..c34f7d8abf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,16 +63,11 @@ glsl_SOURCES = \ ir_validate.cpp \ ir_vec_index_to_swizzle.cpp \ linker.cpp \ - mesa_codegen.cpp \ - msea_codegen.h \ mesa/shader/prog_instruction.c \ mesa/shader/prog_instruction.h \ mesa/shader/prog_print.c \ mesa/shader/prog_print.h -DISTFILES = \ - mesa_codegen.brg - BUILT_SOURCES = glsl_parser.h glsl_parser.cpp glsl_lexer.cpp CLEANFILES = $(BUILT_SOURCES) @@ -82,8 +77,3 @@ glsl_parser.h: glsl_parser.cpp .lpp.cpp: $(LEXCOMPILE) --outfile="$@" $< - -mesa_codegen.h: mesa_codegen.cpp - -mesa_codegen.cpp: mesa_codegen.brg - monoburg --no-glib -s $@ -d mesa_codegen.h $< diff --git a/ir_to_mesa.cpp b/ir_to_mesa.cpp index f121fc88b3..3376e89705 100644 --- a/ir_to_mesa.cpp +++ b/ir_to_mesa.cpp @@ -33,10 +33,11 @@ */ #define g_new #define g_error -#include "mesa_codegen.h" +#include <stdio.h> #include "ir.h" #include "ir_visitor.h" +#include "ir_to_mesa.h" #include "ir_print_visitor.h" #include "ir_expression_flattening.h" #include "glsl_types.h" @@ -54,13 +55,29 @@ ir_to_mesa_dst_reg ir_to_mesa_undef_dst = { PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP }; +ir_to_mesa_dst_reg ir_to_mesa_address_reg = { + PROGRAM_ADDRESS, 0, WRITEMASK_X +}; + +static int swizzle_for_size(int size) +{ + int size_swizzles[4] = { + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X), + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y), + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z), + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W), + }; + + return size_swizzles[size - 1]; +} + ir_to_mesa_instruction * -ir_to_mesa_emit_op3(ir_to_mesa_visitor *v, ir_instruction *ir, - enum prog_opcode op, - ir_to_mesa_dst_reg dst, - ir_to_mesa_src_reg src0, - ir_to_mesa_src_reg src1, - ir_to_mesa_src_reg src2) +ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir, + enum prog_opcode op, + ir_to_mesa_dst_reg dst, + ir_to_mesa_src_reg src0, + ir_to_mesa_src_reg src1, + ir_to_mesa_src_reg src2) { ir_to_mesa_instruction *inst = new ir_to_mesa_instruction(); @@ -71,48 +88,42 @@ ir_to_mesa_emit_op3(ir_to_mesa_visitor *v, ir_instruction *ir, inst->src_reg[2] = src2; inst->ir = ir; - v->instructions.push_tail(inst); + this->instructions.push_tail(inst); return inst; } ir_to_mesa_instruction * -ir_to_mesa_emit_op2_full(ir_to_mesa_visitor *v, ir_instruction *ir, - enum prog_opcode op, - ir_to_mesa_dst_reg dst, - ir_to_mesa_src_reg src0, - ir_to_mesa_src_reg src1) +ir_to_mesa_visitor::ir_to_mesa_emit_op2(ir_instruction *ir, + enum prog_opcode op, + ir_to_mesa_dst_reg dst, + ir_to_mesa_src_reg src0, + ir_to_mesa_src_reg src1) { - return ir_to_mesa_emit_op3(v, ir, - op, dst, src0, src1, ir_to_mesa_undef); + return ir_to_mesa_emit_op3(ir, op, dst, src0, src1, ir_to_mesa_undef); } ir_to_mesa_instruction * -ir_to_mesa_emit_op2(struct mbtree *tree, enum prog_opcode op) +ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir, + enum prog_opcode op, + ir_to_mesa_dst_reg dst, + ir_to_mesa_src_reg src0) { - return ir_to_mesa_emit_op2_full(tree->v, tree->ir, op, - tree->dst_reg, - tree->left->src_reg, - tree->right->src_reg); + return ir_to_mesa_emit_op3(ir, op, dst, + src0, ir_to_mesa_undef, ir_to_mesa_undef); } -ir_to_mesa_instruction * -ir_to_mesa_emit_op1_full(ir_to_mesa_visitor *v, ir_instruction *ir, - enum prog_opcode op, - ir_to_mesa_dst_reg dst, - ir_to_mesa_src_reg src0) +inline ir_to_mesa_dst_reg +ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg) { - return ir_to_mesa_emit_op3(v, ir, op, - dst, src0, ir_to_mesa_undef, ir_to_mesa_undef); -} + ir_to_mesa_dst_reg dst_reg; -ir_to_mesa_instruction * -ir_to_mesa_emit_op1(struct mbtree *tree, enum prog_opcode op) -{ - return ir_to_mesa_emit_op1_full(tree->v, tree->ir, op, - tree->dst_reg, - tree->left->src_reg); + dst_reg.file = reg.file; + dst_reg.index = reg.index; + dst_reg.writemask = WRITEMASK_XYZW; + + return dst_reg; } /** @@ -124,9 +135,10 @@ ir_to_mesa_emit_op1(struct mbtree *tree, enum prog_opcode op) * to produce dest channels. */ void -ir_to_mesa_emit_scalar_op1(struct mbtree *tree, enum prog_opcode op, - ir_to_mesa_dst_reg dst, - ir_to_mesa_src_reg src0) +ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir, + enum prog_opcode op, + ir_to_mesa_dst_reg dst, + ir_to_mesa_src_reg src0) { int i, j; int done_mask = ~dst.writemask; @@ -152,52 +164,18 @@ ir_to_mesa_emit_scalar_op1(struct mbtree *tree, enum prog_opcode op, src.swizzle = MAKE_SWIZZLE4(src_swiz, src_swiz, src_swiz, src_swiz); - inst = ir_to_mesa_emit_op1_full(tree->v, tree->ir, op, - dst, - src); + inst = ir_to_mesa_emit_op1(ir, op, + dst, + src); inst->dst_reg.writemask = this_mask; done_mask |= this_mask; } } -static void -ir_to_mesa_set_tree_reg(struct mbtree *tree, int file, int index) -{ - tree->dst_reg.file = file; - tree->dst_reg.index = index; - - tree->src_reg.file = file; - tree->src_reg.index = index; -} - -struct mbtree * -ir_to_mesa_visitor::create_tree(int op, - ir_instruction *ir, - struct mbtree *left, struct mbtree *right) -{ - struct mbtree *tree = (struct mbtree *)calloc(sizeof(struct mbtree), 1); - - assert(ir); - - tree->op = op; - tree->left = left; - tree->right = right; - tree->v = this; - tree->src_reg.swizzle = SWIZZLE_XYZW; - tree->src_reg.negate = 0; - tree->dst_reg.writemask = WRITEMASK_XYZW; - ir_to_mesa_set_tree_reg(tree, PROGRAM_UNDEFINED, 0); - tree->ir = ir; - - return tree; -} - -struct mbtree * -ir_to_mesa_visitor::create_tree_for_float(ir_instruction *ir, float val) +struct ir_to_mesa_src_reg +ir_to_mesa_visitor::src_reg_for_float(float val) { - struct mbtree *tree = (struct mbtree *)calloc(sizeof(struct mbtree), 1); - - tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL); + ir_to_mesa_src_reg src_reg; /* FINISHME: This will end up being _mesa_add_unnamed_constant, * which handles sharing values and sharing channels of vec4 @@ -206,11 +184,11 @@ ir_to_mesa_visitor::create_tree_for_float(ir_instruction *ir, float val) /* FINISHME: Do something with the constant values for now. */ (void)val; - ir_to_mesa_set_tree_reg(tree, PROGRAM_CONSTANT, this->next_constant++); - tree->src_reg.swizzle = SWIZZLE_NOOP; + src_reg.file = PROGRAM_CONSTANT; + src_reg.index = this->next_constant++; + src_reg.swizzle = SWIZZLE_NOOP; - this->result = tree; - return tree; + return src_reg; } /** @@ -219,21 +197,24 @@ ir_to_mesa_visitor::create_tree_for_float(ir_instruction *ir, float val) * storage). Actual register allocation for the Mesa VM occurs in a * pass over the Mesa IR later. */ -void -ir_to_mesa_visitor::get_temp(struct mbtree *tree, int size) +ir_to_mesa_src_reg +ir_to_mesa_visitor::get_temp(int size) { + ir_to_mesa_src_reg src_reg; int swizzle[4]; int i; - ir_to_mesa_set_tree_reg(tree, PROGRAM_TEMPORARY, this->next_temp++); + src_reg.file = PROGRAM_TEMPORARY; + src_reg.index = this->next_temp++; for (i = 0; i < size; i++) swizzle[i] = i; for (; i < 4; i++) swizzle[i] = size - 1; - tree->src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], - swizzle[2], swizzle[3]); - tree->dst_reg.writemask = (1 << size) - 1; + src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], + swizzle[2], swizzle[3]); + + return src_reg; } static int @@ -267,18 +248,18 @@ type_size(const struct glsl_type *type) } } -void -ir_to_mesa_visitor::get_temp_for_var(ir_variable *var, struct mbtree *tree) +ir_to_mesa_src_reg +ir_to_mesa_visitor::get_temp_for_var(ir_variable *var) { + ir_to_mesa_src_reg src_reg; + temp_entry *entry; foreach_iter(exec_list_iterator, iter, this->variable_storage) { entry = (temp_entry *)iter.get(); - if (entry->var == var) { - ir_to_mesa_set_tree_reg(tree, entry->file, entry->index); - return; - } + if (entry->var == var) + goto done; } entry = new temp_entry(var, PROGRAM_TEMPORARY, this->next_temp); @@ -286,36 +267,12 @@ ir_to_mesa_visitor::get_temp_for_var(ir_variable *var, struct mbtree *tree) next_temp += type_size(var->type); - ir_to_mesa_set_tree_reg(tree, entry->file, entry->index); -} +done: + src_reg.file = entry->file; + src_reg.index = entry->index; + src_reg.swizzle = swizzle_for_size(var->type->vector_elements); -static void -reduce(struct mbtree *t, int goal) -{ - struct mbtree *kids[10]; - int rule = mono_burg_rule((MBState *)t->state, goal); - const uint16_t *nts = mono_burg_nts[rule]; - int i; - - mono_burg_kids (t, rule, kids); - - for (i = 0; nts[i]; i++) { - reduce(kids[i], nts[i]); - } - - if (t->left) { - if (mono_burg_func[rule]) { - mono_burg_func[rule](t, NULL); - } else { - printf("no code for rules %s\n", mono_burg_rule_string[rule]); - exit(1); - } - } else { - if (mono_burg_func[rule]) { - printf("unused code for rule %s\n", mono_burg_rule_string[rule]); - exit(1); - } - } + return src_reg; } void @@ -332,15 +289,13 @@ ir_to_mesa_visitor::visit(ir_loop *ir) assert(!ir->increment); assert(!ir->counter); - ir_to_mesa_emit_op1_full(this, NULL, - OPCODE_BGNLOOP, ir_to_mesa_undef_dst, - ir_to_mesa_undef); + ir_to_mesa_emit_op1(NULL, OPCODE_BGNLOOP, + ir_to_mesa_undef_dst, ir_to_mesa_undef); visit_exec_list(&ir->body_instructions, this); - ir_to_mesa_emit_op1_full(this, NULL, - OPCODE_ENDLOOP, ir_to_mesa_undef_dst, - ir_to_mesa_undef); + ir_to_mesa_emit_op1(NULL, OPCODE_ENDLOOP, + ir_to_mesa_undef_dst, ir_to_mesa_undef); } void @@ -348,14 +303,12 @@ ir_to_mesa_visitor::visit(ir_loop_jump *ir) { switch (ir->mode) { case ir_loop_jump::jump_break: - ir_to_mesa_emit_op1_full(this, NULL, - OPCODE_BRK, ir_to_mesa_undef_dst, - ir_to_mesa_undef); + ir_to_mesa_emit_op1(NULL, OPCODE_BRK, + ir_to_mesa_undef_dst, ir_to_mesa_undef); break; case ir_loop_jump::jump_continue: - ir_to_mesa_emit_op1_full(this, NULL, - OPCODE_CONT, ir_to_mesa_undef_dst, - ir_to_mesa_undef); + ir_to_mesa_emit_op1(NULL, OPCODE_CONT, + ir_to_mesa_undef_dst, ir_to_mesa_undef); break; } } @@ -394,15 +347,17 @@ void ir_to_mesa_visitor::visit(ir_expression *ir) { unsigned int operand; - struct mbtree *op[2]; + struct ir_to_mesa_src_reg op[2], temp; + struct ir_to_mesa_src_reg result_src; + struct ir_to_mesa_dst_reg result_dst; const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1); const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1); const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1); for (operand = 0; operand < ir->get_num_operands(); operand++) { - this->result = NULL; + this->result.file = PROGRAM_UNDEFINED; ir->operands[operand]->accept(this); - if (!this->result) { + if (this->result.file == PROGRAM_UNDEFINED) { ir_print_visitor v; printf("Failed to get tree for expression operand:\n"); ir->operands[operand]->accept(&v); @@ -411,149 +366,163 @@ ir_to_mesa_visitor::visit(ir_expression *ir) op[operand] = this->result; } - this->result = NULL; + this->result.file = PROGRAM_UNDEFINED; + + /* Storage for our result. Ideally for an assignment we'd be using + * the actual storage for the result here, instead. + */ + result_src = get_temp(4); + /* convenience for the emit functions below. */ + result_dst = ir_to_mesa_dst_reg_from_src(result_src); switch (ir->operation) { case ir_unop_logic_not: - this->result = this->create_tree_for_float(ir, 0.0); - this->result = this->create_tree(MB_TERM_seq_vec4_vec4, ir, - op[0], this->result); + temp = src_reg_for_float(0.0); + ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], temp); break; case ir_unop_neg: - op[0]->src_reg.negate = ~op[0]->src_reg.negate; - this->result = op[0]; + op[0].negate = ~op[0].negate; + result_src = op[0]; break; case ir_unop_exp: - this->result = this->create_tree(MB_TERM_exp_vec4, ir, op[0], NULL); + ir_to_mesa_emit_scalar_op1(ir, OPCODE_EXP, result_dst, op[0]); break; case ir_unop_exp2: - this->result = this->create_tree(MB_TERM_exp2_vec4, ir, op[0], NULL); + ir_to_mesa_emit_scalar_op1(ir, OPCODE_EX2, result_dst, op[0]); break; case ir_unop_log: - this->result = this->create_tree(MB_TERM_log_vec4, ir, op[0], NULL); + ir_to_mesa_emit_scalar_op1(ir, OPCODE_LOG, result_dst, op[0]); break; case ir_unop_log2: - this->result = this->create_tree(MB_TERM_log2_vec4, ir, op[0], NULL); + ir_to_mesa_emit_scalar_op1(ir, OPCODE_LG2, result_dst, op[0]); break; case ir_unop_sin: - this->result = this->create_tree(MB_TERM_sin_vec4, ir, op[0], NULL); + ir_to_mesa_emit_scalar_op1(ir, OPCODE_SIN, result_dst, op[0]); break; case ir_unop_cos: - this->result = this->create_tree(MB_TERM_cos_vec4, ir, op[0], NULL); + ir_to_mesa_emit_scalar_op1(ir, OPCODE_COS, result_dst, op[0]); break; case ir_binop_add: - this->result = this->create_tree(MB_TERM_add_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_ADD, result_dst, op[0], op[1]); break; case ir_binop_sub: - this->result = this->create_tree(MB_TERM_sub_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_SUB, result_dst, op[0], op[1]); break; case ir_binop_mul: - this->result = this->create_tree(MB_TERM_mul_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]); break; case ir_binop_div: - this->result = this->create_tree(MB_TERM_div_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_RCP, result_dst, op[0], result_src); break; case ir_binop_less: - this->result = this->create_tree(MB_TERM_slt_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_SLT, result_dst, op[0], temp); break; case ir_binop_greater: - this->result = this->create_tree(MB_TERM_sgt_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_SGT, result_dst, op[0], temp); break; case ir_binop_lequal: - this->result = this->create_tree(MB_TERM_sle_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_SLE, result_dst, op[0], temp); break; case ir_binop_gequal: - this->result = this->create_tree(MB_TERM_sge_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], temp); break; case ir_binop_equal: - this->result = this->create_tree(MB_TERM_seq_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], temp); break; case ir_binop_logic_xor: case ir_binop_nequal: - this->result = this->create_tree(MB_TERM_sne_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], temp); break; case ir_binop_logic_or: - /* This could be a saturated add. */ - this->result = this->create_tree(MB_TERM_add_vec4_vec4, ir, op[0], op[1]); - this->result = this->create_tree(MB_TERM_sne_vec4_vec4, ir, - this->create_tree_for_float(ir, 0.0), - this->result); + /* This could be a saturated add and skip the SNE. */ + ir_to_mesa_emit_op2(ir, OPCODE_ADD, + result_dst, + op[0], op[1]); + + ir_to_mesa_emit_op2(ir, OPCODE_SNE, + result_dst, + result_src, src_reg_for_float(0.0)); break; case ir_binop_logic_and: /* the bool args are stored as float 0.0 or 1.0, so "mul" gives us "and". */ - this->result = this->create_tree(MB_TERM_mul_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_MUL, + result_dst, + op[0], op[1]); break; case ir_binop_dot: if (ir->operands[0]->type == vec4_type) { assert(ir->operands[1]->type == vec4_type); - this->result = this->create_tree(MB_TERM_dp4_vec4_vec4, - ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_DP4, + result_dst, + op[0], op[1]); } else if (ir->operands[0]->type == vec3_type) { assert(ir->operands[1]->type == vec3_type); - this->result = this->create_tree(MB_TERM_dp3_vec4_vec4, - ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_DP3, + result_dst, + op[0], op[1]); } else if (ir->operands[0]->type == vec2_type) { assert(ir->operands[1]->type == vec2_type); - this->result = this->create_tree(MB_TERM_dp2_vec4_vec4, - ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_DP2, + result_dst, + op[0], op[1]); } break; case ir_unop_sqrt: - this->result = this->create_tree(MB_TERM_sqrt_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]); + ir_to_mesa_emit_op1(ir, OPCODE_RCP, result_dst, result_src); break; case ir_unop_rsq: - this->result = this->create_tree(MB_TERM_rsq_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]); break; case ir_unop_i2f: /* Mesa IR lacks types, ints are stored as truncated floats. */ - this->result = op[0]; + result_src = op[0]; break; case ir_unop_f2i: - this->result = this->create_tree(MB_TERM_trunc_vec4, ir, op[0], NULL); + ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]); break; case ir_unop_f2b: - this->result = this->create_tree_for_float(ir, 0.0); - this->result = this->create_tree(MB_TERM_sne_vec4_vec4, ir, - op[0], this->result); + ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, + result_src, src_reg_for_float(0.0)); break; case ir_unop_trunc: - this->result = this->create_tree(MB_TERM_trunc_vec4, ir, op[0], NULL); + ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]); break; case ir_unop_ceil: - this->result = this->create_tree(MB_TERM_ceil_vec4, ir, op[0], NULL); + op[0].negate = ~op[0].negate; + ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]); + result_src.negate = ~result_src.negate; break; case ir_unop_floor: - this->result = this->create_tree(MB_TERM_floor_vec4, ir, op[0], NULL); + ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]); break; case ir_binop_min: - this->result = this->create_tree(MB_TERM_min_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_MIN, result_dst, op[0], op[1]); break; case ir_binop_max: - this->result = this->create_tree(MB_TERM_max_vec4_vec4, ir, op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_MAX, result_dst, op[0], op[1]); break; default: - break; - } - if (!this->result) { ir_print_visitor v; printf("Failed to get tree for expression:\n"); ir->accept(&v); exit(1); + break; } - /* Allocate a temporary for the result. */ - this->get_temp(this->result, ir->type->vector_elements); + this->result = result_src; } void ir_to_mesa_visitor::visit(ir_swizzle *ir) { - struct mbtree *tree; + ir_to_mesa_src_reg src_reg; int i; int swizzle[4]; @@ -563,10 +532,9 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir) */ ir->val->accept(this); - assert(this->result); + assert(this->result.file != PROGRAM_UNDEFINED); - tree = this->create_tree(MB_TERM_swizzle_vec4, ir, this->result, NULL); - this->get_temp(tree, 4); + src_reg = this->get_temp(4); for (i = 0; i < 4; i++) { if (i < ir->type->vector_elements) { @@ -592,12 +560,12 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir) } } - tree->src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], - swizzle[1], - swizzle[2], - swizzle[3]); + src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], + swizzle[1], + swizzle[2], + swizzle[3]); - this->result = tree; + this->result = src_reg; } /* This list should match up with builtin_variables.h */ @@ -653,28 +621,18 @@ static const struct { void ir_to_mesa_visitor::visit(ir_dereference_variable *ir) { - struct mbtree *tree; - int size_swizzles[4] = { - MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X), - MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y), - MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z), - MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W), - }; + ir_to_mesa_src_reg src_reg; /* By the time we make it to this stage, matrices should be broken down * to vectors. */ assert(!ir->var->type->is_matrix()); - tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL); - if (strncmp(ir->var->name, "gl_", 3) == 0) { unsigned int i; bool var_in = (ir->var->mode == ir_var_in || ir->var->mode == ir_var_inout); - tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL); - for (i = 0; i < ARRAY_SIZE(builtin_var_to_mesa_reg); i++) { bool in = builtin_var_to_mesa_reg[i].file == PROGRAM_INPUT; @@ -688,29 +646,25 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) ir->var->name); abort(); } - ir_to_mesa_set_tree_reg(tree, builtin_var_to_mesa_reg[i].file, - builtin_var_to_mesa_reg[i].index); + src_reg.file = builtin_var_to_mesa_reg[i].file; + src_reg.index = builtin_var_to_mesa_reg[i].index; } else { - this->get_temp_for_var(ir->var, tree); + src_reg = get_temp_for_var(ir->var); } /* If the type is smaller than a vec4, replicate the last channel out. */ - tree->src_reg.swizzle = size_swizzles[ir->type->vector_elements - 1]; + src_reg.swizzle = swizzle_for_size(ir->type->vector_elements); + src_reg.reladdr = false; + src_reg.negate = 0; - this->result = tree; + this->result = src_reg; } void ir_to_mesa_visitor::visit(ir_dereference_array *ir) { - struct mbtree *tree; - int size_swizzles[4] = { - MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W), - MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z), - MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y), - MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X), - }; ir_constant *index; + ir_to_mesa_src_reg src_reg; index = ir->array_index->constant_expression_value(); @@ -720,59 +674,59 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir) assert(!ir->type->is_matrix()); ir->array->accept(this); - tree = this->result; + src_reg = this->result; - if (tree->src_reg.file == PROGRAM_INPUT || - tree->src_reg.file == PROGRAM_OUTPUT) { + if (src_reg.file == PROGRAM_INPUT || + src_reg.file == PROGRAM_OUTPUT) { assert(index); /* FINISHME: Handle variable indexing of builtins. */ - tree->src_reg.index += index->value.i[0]; - tree->dst_reg.index += index->value.i[0]; + src_reg.index += index->value.i[0]; } else { if (index) { - tree->src_reg.index += index->value.i[0]; - tree->dst_reg.index += index->value.i[0]; + src_reg.index += index->value.i[0]; } else { + ir_to_mesa_src_reg array_base = this->result; /* Variable index array dereference. It eats the "vec4" of the * base of the array and an index that offsets the Mesa register * index. */ ir->array_index->accept(this); - tree->src_reg.reladdr = true; - tree = this->create_tree(MB_TERM_array_reference_vec4_vec4, - ir, tree, this->result); - this->get_temp(tree, ir->type->vector_elements); + /* FINISHME: This doesn't work when we're trying to do the LHS + * of an assignment. + */ + src_reg.reladdr = true; + ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg, + this->result); + + this->result = get_temp(ir->type->vector_elements); + ir_to_mesa_emit_op1(ir, OPCODE_MOV, + ir_to_mesa_dst_reg_from_src(this->result), + src_reg); } } /* If the type is smaller than a vec4, replicate the last channel out. */ - tree->src_reg.swizzle = size_swizzles[ir->type->vector_elements - 1]; + src_reg.swizzle = swizzle_for_size(ir->type->vector_elements); - this->result = tree; + this->result = src_reg; } void ir_to_mesa_visitor::visit(ir_dereference_record *ir) { - ir_variable *var = ir->variable_referenced(); - const char *field = ir->field; - struct mbtree *tree; unsigned int i; - - const glsl_type *struct_type = var->type; + const glsl_type *struct_type = ir->record->type; int offset = 0; - tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL); - this->get_temp_for_var(var, tree); + ir->record->accept(this); for (i = 0; i < struct_type->length; i++) { - if (strcmp(struct_type->fields.structure[i].name, field) == 0) + if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0) break; offset += type_size(struct_type->fields.structure[i].type); } - tree->src_reg.index += offset; - tree->dst_reg.index += offset; + this->result.index += offset; } /** @@ -785,43 +739,44 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) * and one swizzle, before getting to actual vec4 storage. So handle * those, then go use ir_dereference to handle the rest. */ -static struct mbtree * +static struct ir_to_mesa_dst_reg get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v) { - struct mbtree *tree = NULL; + struct ir_to_mesa_dst_reg dst_reg; ir_dereference *deref; ir_swizzle *swiz; + /* Use the rvalue deref handler for the most part. We'll ignore + * swizzles in it and write swizzles using writemask, though. + */ ir->accept(v); - tree = v->result; + dst_reg = ir_to_mesa_dst_reg_from_src(v->result); if ((deref = ir->as_dereference())) { ir_dereference_array *deref_array = ir->as_dereference_array(); assert(!deref_array || deref_array->array->type->is_array()); ir->accept(v); - tree = v->result; } else if ((swiz = ir->as_swizzle())) { - tree->dst_reg.writemask = 0; + dst_reg.writemask = 0; if (swiz->mask.num_components >= 1) - tree->dst_reg.writemask |= (1 << swiz->mask.x); + dst_reg.writemask |= (1 << swiz->mask.x); if (swiz->mask.num_components >= 2) - tree->dst_reg.writemask |= (1 << swiz->mask.y); + dst_reg.writemask |= (1 << swiz->mask.y); if (swiz->mask.num_components >= 3) - tree->dst_reg.writemask |= (1 << swiz->mask.z); + dst_reg.writemask |= (1 << swiz->mask.z); if (swiz->mask.num_components >= 4) - tree->dst_reg.writemask |= (1 << swiz->mask.w); + dst_reg.writemask |= (1 << swiz->mask.w); } - assert(tree); - - return tree; + return dst_reg; } void ir_to_mesa_visitor::visit(ir_assignment *ir) { - struct mbtree *l, *r, *t; + struct ir_to_mesa_dst_reg l; + struct ir_to_mesa_src_reg r; assert(!ir->lhs->type->is_matrix()); assert(!ir->lhs->type->is_array()); @@ -831,8 +786,8 @@ ir_to_mesa_visitor::visit(ir_assignment *ir) ir->rhs->accept(this); r = this->result; - assert(l); - assert(r); + assert(l.file != PROGRAM_UNDEFINED); + assert(r.file != PROGRAM_UNDEFINED); if (ir->condition) { ir_constant *condition_constant; @@ -842,21 +797,17 @@ ir_to_mesa_visitor::visit(ir_assignment *ir) assert(condition_constant && condition_constant->value.b[0]); } - t = this->create_tree(MB_TERM_assign, ir, l, r); - mono_burg_label(t, NULL); - reduce(t, MB_NTERM_stmt); + ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r); } void ir_to_mesa_visitor::visit(ir_constant *ir) { - struct mbtree *tree; + ir_to_mesa_src_reg src_reg; assert(!ir->type->is_matrix()); - tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL); - assert(ir->type->base_type == GLSL_TYPE_FLOAT || ir->type->base_type == GLSL_TYPE_UINT || ir->type->base_type == GLSL_TYPE_INT || @@ -868,10 +819,13 @@ ir_to_mesa_visitor::visit(ir_constant *ir) */ /* FINISHME: Do something with the constant values for now. */ - ir_to_mesa_set_tree_reg(tree, PROGRAM_CONSTANT, this->next_constant++); - tree->src_reg.swizzle = SWIZZLE_NOOP; + src_reg.file = PROGRAM_CONSTANT; + src_reg.index = this->next_constant++; + src_reg.swizzle = SWIZZLE_NOOP; + src_reg.reladdr = false; + src_reg.negate = 0; - this->result = tree; + this->result = src_reg; } @@ -906,31 +860,30 @@ ir_to_mesa_visitor::visit(ir_if *ir) ir_to_mesa_instruction *if_inst, *else_inst = NULL; ir->condition->accept(this); - assert(this->result); + assert(this->result.file != PROGRAM_UNDEFINED); - if_inst = ir_to_mesa_emit_op1_full(this, ir->condition, - OPCODE_IF, ir_to_mesa_undef_dst, - this->result->src_reg); + if_inst = ir_to_mesa_emit_op1(ir->condition, + OPCODE_IF, ir_to_mesa_undef_dst, + this->result); this->instructions.push_tail(if_inst); visit_exec_list(&ir->then_instructions, this); if (!ir->else_instructions.is_empty()) { - else_inst = ir_to_mesa_emit_op1_full(this, ir->condition, - OPCODE_ELSE, ir_to_mesa_undef_dst, - ir_to_mesa_undef); + else_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_ELSE, + ir_to_mesa_undef_dst, + ir_to_mesa_undef); visit_exec_list(&ir->then_instructions, this); } - if_inst = ir_to_mesa_emit_op1_full(this, ir->condition, - OPCODE_ENDIF, ir_to_mesa_undef_dst, - ir_to_mesa_undef); + if_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_ENDIF, + ir_to_mesa_undef_dst, ir_to_mesa_undef); } ir_to_mesa_visitor::ir_to_mesa_visitor() { - result = NULL; + result.file = PROGRAM_UNDEFINED; next_temp = 1; next_constant = 0; } diff --git a/ir_to_mesa.h b/ir_to_mesa.h index 0535bc08a2..b05b9ebc7a 100644 --- a/ir_to_mesa.h +++ b/ir_to_mesa.h @@ -102,15 +102,11 @@ public: int next_temp; int next_constant; - void get_temp(struct mbtree *tree, int size); + ir_to_mesa_src_reg get_temp(int size); - void get_temp_for_var(ir_variable *var, struct mbtree *tree); + ir_to_mesa_src_reg get_temp_for_var(ir_variable *var); - struct mbtree *create_tree(int op, - ir_instruction *ir, - struct mbtree *left, - struct mbtree *right); - struct mbtree *create_tree_for_float(ir_instruction *ir, float val); + struct ir_to_mesa_src_reg src_reg_for_float(float val); /** * \name Visit methods @@ -138,61 +134,38 @@ public: virtual void visit(ir_if *); /*@}*/ - struct mbtree *result; + struct ir_to_mesa_src_reg result; /** List of temp_entry */ exec_list variable_storage; /** List of ir_to_mesa_instruction */ exec_list instructions; + + ir_to_mesa_instruction *ir_to_mesa_emit_op1(ir_instruction *ir, + enum prog_opcode op, + ir_to_mesa_dst_reg dst, + ir_to_mesa_src_reg src0); + + ir_to_mesa_instruction *ir_to_mesa_emit_op2(ir_instruction *ir, + enum prog_opcode op, + ir_to_mesa_dst_reg dst, + ir_to_mesa_src_reg src0, + ir_to_mesa_src_reg src1); + + ir_to_mesa_instruction *ir_to_mesa_emit_op3(ir_instruction *ir, + enum prog_opcode op, + ir_to_mesa_dst_reg dst, + ir_to_mesa_src_reg src0, + ir_to_mesa_src_reg src1, + ir_to_mesa_src_reg src2); + + void ir_to_mesa_emit_scalar_op1(ir_instruction *ir, + enum prog_opcode op, + ir_to_mesa_dst_reg dst, + ir_to_mesa_src_reg src0); }; extern ir_to_mesa_src_reg ir_to_mesa_undef; extern ir_to_mesa_dst_reg ir_to_mesa_undef_dst; -ir_to_mesa_instruction * -ir_to_mesa_emit_op1(struct mbtree *tree, enum prog_opcode op); - -ir_to_mesa_instruction * -ir_to_mesa_emit_op1_full(ir_to_mesa_visitor *v, ir_instruction *ir, - enum prog_opcode op, - ir_to_mesa_dst_reg dst, - ir_to_mesa_src_reg src0); - -ir_to_mesa_instruction * -ir_to_mesa_emit_op2(struct mbtree *tree, enum prog_opcode op); - -ir_to_mesa_instruction * -ir_to_mesa_emit_op2_full(ir_to_mesa_visitor *v, ir_instruction *ir, - enum prog_opcode op, - ir_to_mesa_dst_reg dst, - ir_to_mesa_src_reg src0, - ir_to_mesa_src_reg src1); - -ir_to_mesa_instruction * -ir_to_mesa_emit_simple_op2(struct mbtree *tree, enum prog_opcode op); - -ir_to_mesa_instruction * -ir_to_mesa_emit_op3(ir_to_mesa_visitor *v, ir_instruction *ir, - enum prog_opcode op, - ir_to_mesa_dst_reg dst, - ir_to_mesa_src_reg src0, - ir_to_mesa_src_reg src1, - ir_to_mesa_src_reg src2); - -void -ir_to_mesa_emit_scalar_op1(struct mbtree *tree, enum prog_opcode op, - ir_to_mesa_dst_reg dst, - ir_to_mesa_src_reg src0); - -inline ir_to_mesa_dst_reg -ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg) -{ - ir_to_mesa_dst_reg dst_reg; - - dst_reg.file = reg.file; - dst_reg.index = reg.index; - dst_reg.writemask = WRITEMASK_XYZW; - - return dst_reg; -} diff --git a/mesa_codegen.brg b/mesa_codegen.brg deleted file mode 100644 index d53ccf3907..0000000000 --- a/mesa_codegen.brg +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * - */ - -/* DO NOT EDIT mesa_codegen.h. It is a generated file produced - * from mesa_codegen.brg and will be overwritten. - */ - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <stdio.h> - -/* Everything before the first %% is pasted at the start of the - * mesa_codegen.h header file. - */ - -#include "ir_to_mesa.h" - -#define MBTREE_TYPE struct mbtree - -%% -# The list of terminals is the set of things that ir_to_mesa.cpp will -# generate in its trees. -%term assign -%term reference_vec4 -%term array_reference_vec4_vec4 -%term exp_vec4 -%term exp2_vec4 -%term log_vec4 -%term log2_vec4 -%term trunc_vec4 -%term ceil_vec4 -%term floor_vec4 -%term sin_vec4 -%term cos_vec4 -%term add_vec4_vec4 -%term sub_vec4_vec4 -%term mul_vec4_vec4 -%term div_vec4_vec4 -%term slt_vec4_vec4 -%term sgt_vec4_vec4 -%term sle_vec4_vec4 -%term sge_vec4_vec4 -%term seq_vec4_vec4 -%term sne_vec4_vec4 -%term dp4_vec4_vec4 -%term dp3_vec4_vec4 -%term dp2_vec4_vec4 -%term sqrt_vec4 -%term rsq_vec4 -%term swizzle_vec4 -%term min_vec4_vec4 -%term max_vec4_vec4 - -# Each tree will produce stmt. Currently, the only production for -# stmt is from an assign rule -- every statement tree from -# ir_to_mesa.cpp assigns a result to a register. - -%start stmt - -# Now comes all the rules for code generation. Each rule is of the -# general form -# -# produced: term(term, term) cost -# { -# code_run_when_we_choose_this_rule(); -# } -# -# where choosing this rule means we turn term(term, term) into -# produced at the cost of "cost". We measure "cost" in approximate -# instruction count. The BURG should then more or less minimize the -# number of instructions. - -# A reference of a variable is just a vec4 register location, -# so it can be used as an argument for pretty much anything. -vec4: reference_vec4 0 - -# A reference of a variable is just a vec4 register location, -# so it can be used as an argument for pretty much anything. -vec4: array_reference_vec4_vec4(vec4, vec4) 1 -{ - ir_to_mesa_dst_reg address_reg = {PROGRAM_ADDRESS, 0, WRITEMASK_X}; - - ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_ARL, - address_reg, - tree->right->src_reg); - ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_MOV, - tree->dst_reg, - tree->left->src_reg); -} - -# Here's the rule everyone will hit: Moving the result of an -# expression into a variable-dereference register location. -# -# Note that this is likely a gratuitous move. We could make variants -# of each of the following rules, e.g: -# -# vec4: add_vec4_vec4(vec4, vec4) 1 -# { -# emit(ADD, tree, tree->left, tree->right); -# } -# -# becoming -# -# vec4: assign(vec4_vec4, add_vec4_vec4(vec4, vec4) 1 -# { -# emit(ADD, tree->left, tree->right->left, tree->right->right); -# } -# -# But it seems like a lot of extra typing and duped code, when we -# probably want copy propagation and dead code after codegen anyway, -# which would clean these up. -stmt: assign(vec4, vec4) 1 -{ - ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_MOV, - tree->left->dst_reg, - tree->right->src_reg); -} - -# Perform a swizzle by composing our swizzle with the swizzle -# required to get at the src reg. -vec4: swizzle_vec4(vec4) 1 -{ - ir_to_mesa_src_reg reg = tree->left->src_reg; - int swiz[4]; - int i; - - for (i = 0; i < 4; i++) { - swiz[i] = GET_SWZ(tree->src_reg.swizzle, i); - if (swiz[i] >= SWIZZLE_X && swiz[i] <= SWIZZLE_Y) { - swiz[i] = GET_SWZ(tree->left->src_reg.swizzle, swiz[i]); - } - } - reg.swizzle = MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]); - - ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_MOV, - tree->dst_reg, - reg); -} - -vec4: trunc_vec4(vec4) 1 { ir_to_mesa_emit_op1(tree, OPCODE_TRUNC); } - -vec4: ceil_vec4(vec4) 1 { - tree->left->src_reg.negate = ~tree->left->src_reg.negate; - ir_to_mesa_emit_op1(tree, OPCODE_FLR); - tree->src_reg.negate = ~tree->left->src_reg.negate; -} - -vec4: floor_vec4(vec4) 1 { ir_to_mesa_emit_op1(tree, OPCODE_FLR); } - -vec4: sin_vec4(vec4) 1 -{ - ir_to_mesa_emit_scalar_op1(tree, OPCODE_SIN, - tree->dst_reg, - tree->left->src_reg); -} - -vec4: cos_vec4(vec4) 1 -{ - ir_to_mesa_emit_scalar_op1(tree, OPCODE_COS, - tree->dst_reg, - tree->left->src_reg); -} - -vec4: add_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_ADD); } -vec4: sub_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_SUB); } -vec4: mul_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_MUL); } - -vec4: dp4_vec4_vec4(vec4, vec4) 1 -{ - ir_to_mesa_emit_op2(tree, OPCODE_DP4); - tree->src_reg.swizzle = SWIZZLE_XXXX; -} - -vec4: dp3_vec4_vec4(vec4, vec4) 1 -{ - ir_to_mesa_emit_op2(tree, OPCODE_DP3); - tree->src_reg.swizzle = SWIZZLE_XXXX; -} - - -vec4: dp2_vec4_vec4(vec4, vec4) 1 -{ - ir_to_mesa_emit_op2(tree, OPCODE_DP2); - tree->src_reg.swizzle = SWIZZLE_XXXX; -} - -vec4: div_vec4_vec4(vec4, vec4) 1 -{ - ir_to_mesa_emit_scalar_op1(tree, OPCODE_RCP, - tree->dst_reg, - tree->right->src_reg); - - ir_to_mesa_emit_op2_full(tree->v, tree->ir, OPCODE_MUL, - tree->dst_reg, - tree->src_reg, - tree->left->src_reg); -} - -vec4: slt_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_SLT); } -vec4: sgt_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_SGT); } -vec4: sle_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_SLE); } -vec4: sge_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_SGE); } -vec4: sne_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_SNE); } -vec4: seq_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_SEQ); } - -vec4: sqrt_vec4(vec4) 1 -{ - ir_to_mesa_emit_scalar_op1(tree, OPCODE_RSQ, - tree->dst_reg, - tree->left->src_reg); - - ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_RCP, - tree->dst_reg, - tree->src_reg); -} - -vec4: rsq_vec4(vec4) 1 -{ - ir_to_mesa_emit_scalar_op1(tree, OPCODE_RSQ, - tree->dst_reg, - tree->left->src_reg); -} - -vec4: exp_vec4(vec4) 1 -{ - ir_to_mesa_emit_scalar_op1(tree, OPCODE_EXP, - tree->dst_reg, - tree->left->src_reg); -} - -vec4: exp2_vec4(vec4) 1 -{ - ir_to_mesa_emit_scalar_op1(tree, OPCODE_EX2, - tree->dst_reg, - tree->left->src_reg); -} - -vec4: log_vec4(vec4) 1 -{ - ir_to_mesa_emit_scalar_op1(tree, OPCODE_LOG, - tree->dst_reg, - tree->left->src_reg); -} - -vec4: log2_vec4(vec4) 1 -{ - ir_to_mesa_emit_scalar_op1(tree, OPCODE_LG2, - tree->dst_reg, - tree->left->src_reg); -} - -vec4: min_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_MIN); } -vec4: max_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_MAX); } - -%% |