diff --git a/src/gallium/drivers/r300/compiler/r3xx_fragprog.c b/src/gallium/drivers/r300/compiler/r3xx_fragprog.c index 556a16a2e0d..67680915226 100644 --- a/src/gallium/drivers/r300/compiler/r3xx_fragprog.c +++ b/src/gallium/drivers/r300/compiler/r3xx_fragprog.c @@ -30,6 +30,8 @@ #include "radeon_program_tex.h" #include "radeon_rename_regs.h" #include "radeon_remove_constants.h" +#include "radeon_variable.h" +#include "radeon_list.h" #include "r300_fragprog.h" #include "r300_fragprog_swizzle.h" #include "r500_fragprog.h" @@ -65,6 +67,48 @@ static void rc_rewrite_depth_out(struct radeon_compiler *cc, void *user) } } +/** + * This function will try to convert rgb instructions into alpha instructions + * and vice versa. While this is already attempted during the pair scheduling, + * it is much simpler to do it before pair conversion, so do it here at least for + * the simple cases. + * + * Currently only math opcodes writing to rgb (and with no friends) are + * converted to alpha. + * + * This function assumes all the instructions are still of type + * RC_INSTRUCTION_NORMAL, the conversion is much simpler. + * + * Beware that this needs to be also called before doing presubtract, because + * rc_get_variables can't get properly readers for normal instructions if presubtract + * is present (it works fine for pair instructions). + */ +static void rc_convert_rgb_alpha(struct radeon_compiler *c, void *user) +{ + struct rc_list * variables; + struct rc_list * var_ptr; + + variables = rc_get_variables(c); + + for (var_ptr = variables; var_ptr; var_ptr = var_ptr->Next) { + struct rc_variable * var = var_ptr->Item; + + if (var->Inst->U.I.DstReg.File != RC_FILE_TEMPORARY) { + continue; + } + + /* Only rewrite scalar opcodes that are used separatelly for now. */ + if (var->Friend) + continue; + + const struct rc_opcode_info * opcode = rc_get_opcode_info(var->Inst->U.I.Opcode); + if (opcode->IsStandardScalar && var->Dst.WriteMask != RC_MASK_W) { + unsigned index = rc_find_free_temporary(c); + rc_variable_change_dst(var, index, RC_MASK_W); + } + } +} + void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c) { int is_r500 = c->Base.is_r500; @@ -104,6 +148,7 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c) {"native rewrite", 1, is_r500, rc_local_transform, native_rewrite_r500}, {"native rewrite", 1, !is_r500, rc_local_transform, native_rewrite_r300}, {"deadcode", 1, opt, rc_dataflow_deadcode, NULL}, + {"convert rgb<->alpha", 1, opt, rc_convert_rgb_alpha, NULL}, {"register rename", 1, !is_r500 || opt, rc_rename_regs, NULL}, {"dataflow optimize", 1, opt, rc_optimize, NULL}, {"inline literals", 1, is_r500 && opt, rc_inline_literals, NULL},