diff options
7 files changed, 154 insertions, 15 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c index 590201a9ba..614c2e3d24 100644 --- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c @@ -88,11 +88,12 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c) if (c->is_r500) { struct radeon_program_transformation transformations[] = { { &r500_transform_TEX, c }, + { &r500_transform_IF, 0 }, { &radeonTransformALU, 0 }, { &radeonTransformDeriv, 0 }, { &radeonTransformTrigScale, 0 } }; - radeonLocalTransform(&c->Base, 4, transformations); + radeonLocalTransform(&c->Base, 5, transformations); c->Base.SwizzleCaps = &r500_swizzle_caps; } else { diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c index 971465e359..39f2445bd4 100644 --- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c @@ -169,6 +169,34 @@ int r500_transform_TEX( return 1; } +/** + * Rewrite IF instructions to use the ALU result special register. + */ +int r500_transform_IF( + struct radeon_compiler * c, + struct rc_instruction * inst, + void* data) +{ + if (inst->I.Opcode != RC_OPCODE_IF) + return 0; + + struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst->Prev); + inst_mov->I.Opcode = RC_OPCODE_MOV; + inst_mov->I.DstReg.WriteMask = 0; + inst_mov->I.WriteALUResult = RC_ALURESULT_W; + inst_mov->I.ALUResultCompare = RC_COMPARE_FUNC_NOTEQUAL; + inst_mov->I.SrcReg[0] = inst->I.SrcReg[0]; + inst_mov->I.SrcReg[0].Swizzle = combine_swizzles4(inst_mov->I.SrcReg[0].Swizzle, + RC_SWIZZLE_UNUSED, RC_SWIZZLE_UNUSED, RC_SWIZZLE_UNUSED, RC_SWIZZLE_X); + + inst->I.SrcReg[0].File = RC_FILE_SPECIAL; + inst->I.SrcReg[0].Index = RC_SPECIAL_ALU_RESULT; + inst->I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW; + inst->I.SrcReg[0].Negate = 0; + + return 1; +} + static int r500_swizzle_is_native(rc_opcode opcode, struct rc_src_register reg) { unsigned int relevant; diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h index 92ac75d5fd..0918cdf518 100644 --- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h +++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h @@ -47,4 +47,9 @@ extern int r500_transform_TEX( struct rc_instruction * inst, void* data); +extern int r500_transform_IF( + struct radeon_compiler * c, + struct rc_instruction * inst, + void* data); + #endif diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c index 95af6fd411..2ae3c56689 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c @@ -34,10 +34,12 @@ struct updatemask_state { unsigned char Output[RC_REGISTER_MAX_INDEX]; unsigned char Temporary[RC_REGISTER_MAX_INDEX]; unsigned char Address; + unsigned char Special[RC_NUM_SPECIAL_REGISTERS]; }; struct instruction_state { - unsigned char WriteMask; + unsigned char WriteMask:4; + unsigned char WriteALUResult:1; unsigned char SrcReg[3]; }; @@ -70,6 +72,9 @@ static void or_updatemasks( dst->Temporary[i] = a->Temporary[i] | b->Temporary[i]; } + for(unsigned int i = 0; i < RC_NUM_SPECIAL_REGISTERS; ++i) + dst->Special[i] = a->Special[i] | b->Special[i]; + dst->Address = a->Address | b->Address; } @@ -108,6 +113,13 @@ static unsigned char * get_used_ptr(struct deadcode_state *s, rc_register_file f return &s->R.Temporary[index]; } else if (file == RC_FILE_ADDRESS) { return &s->R.Address; + } else if (file == RC_FILE_SPECIAL) { + if (index >= RC_NUM_SPECIAL_REGISTERS) { + rc_error(s->C, "%s: special file index %i out of bounds\n", __FUNCTION__, index); + return 0; + } + + return &s->R.Special[index]; } return 0; @@ -136,6 +148,19 @@ static void update_instruction(struct deadcode_state * s, struct rc_instruction insts->WriteMask |= usedmask; + if (inst->I.WriteALUResult) { + unsigned char * pused = get_used_ptr(s, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT); + if (pused && *pused) { + if (inst->I.WriteALUResult == RC_ALURESULT_X) + usedmask |= RC_MASK_X; + else if (inst->I.WriteALUResult == RC_ALURESULT_W) + usedmask |= RC_MASK_W; + + *pused = 0; + insts->WriteALUResult = 1; + } + } + unsigned int srcmasks[3]; rc_compute_sources_for_writemask(opcode, usedmask, srcmasks); @@ -225,21 +250,38 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, rc_dataflow_mark_outputs_f for(struct rc_instruction * inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next, ++ip) { - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode); + const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode);\ + int dead = 1; + + if (!opcode->HasDstReg) { + dead = 0; + } else { + inst->I.DstReg.WriteMask = s.Instructions[ip].WriteMask; + if (s.Instructions[ip].WriteMask) + dead = 0; + + if (s.Instructions[ip].WriteALUResult) + dead = 0; + else + inst->I.WriteALUResult = RC_ALURESULT_NONE; + } - if (opcode->HasDstReg) { - if (s.Instructions[ip].WriteMask) { - inst->I.DstReg.WriteMask = s.Instructions[ip].WriteMask; - } else { - struct rc_instruction * todelete = inst; - inst = inst->Prev; - rc_remove_instruction(todelete); - continue; - } + if (dead) { + struct rc_instruction * todelete = inst; + inst = inst->Prev; + rc_remove_instruction(todelete); + continue; } unsigned int srcmasks[3]; - rc_compute_sources_for_writemask(opcode, s.Instructions[ip].WriteMask, srcmasks); + unsigned int usemask = s.Instructions[ip].WriteMask; + + if (inst->I.WriteALUResult == RC_ALURESULT_X) + usemask |= RC_MASK_X; + else if (inst->I.WriteALUResult == RC_ALURESULT_W) + usemask |= RC_MASK_W; + + rc_compute_sources_for_writemask(opcode, usemask, srcmasks); for(unsigned int src = 0; src < 3; ++src) { for(unsigned int chan = 0; chan < 4; ++chan) { diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.h b/src/mesa/drivers/dri/r300/compiler/radeon_program.h index efa2b0dfe3..071b0a0ca9 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.h @@ -87,6 +87,14 @@ struct rc_sub_instruction { rc_saturate_mode SaturateMode:2; /** + * Writing to the special register RC_SPECIAL_ALU_RESULT + */ + /*@{*/ + rc_write_aluresult WriteALUResult:2; + rc_compare_func ALUResultCompare:3; + /*@}*/ + + /** * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions. */ /*@{*/ diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_constants.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_constants.h index 69994f9880..7c0d6720b1 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_constants.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_constants.h @@ -74,9 +74,22 @@ typedef enum { /** * Indicates a constant from the \ref rc_constant_list . */ - RC_FILE_CONSTANT + RC_FILE_CONSTANT, + + /** + * Indicates a special register, see RC_SPECIAL_xxx. + */ + RC_FILE_SPECIAL } rc_register_file; +enum { + /** R500 fragment program ALU result "register" */ + RC_SPECIAL_ALU_RESULT = 0, + + /** Must be last */ + RC_NUM_SPECIAL_REGISTERS +}; + #define RC_REGISTER_INDEX_BITS 10 #define RC_REGISTER_MAX_INDEX (1 << RC_REGISTER_INDEX_BITS) @@ -125,4 +138,10 @@ typedef enum { #define RC_MASK_XYZW (RC_MASK_X|RC_MASK_Y|RC_MASK_Z|RC_MASK_W) /*@}*/ +typedef enum { + RC_ALURESULT_NONE = 0, + RC_ALURESULT_X, + RC_ALURESULT_W +} rc_write_aluresult; + #endif /* RADEON_PROGRAM_CONSTANTS_H */ diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c index 0485286451..6645d7cacb 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c @@ -38,10 +38,36 @@ static const char * textarget_to_string(rc_texture_target target) } } +static void rc_print_comparefunc(FILE * f, const char * lhs, rc_compare_func func, const char * rhs) +{ + if (func == RC_COMPARE_FUNC_NEVER) { + fprintf(f, "false"); + } else if (func == RC_COMPARE_FUNC_ALWAYS) { + fprintf(f, "true"); + } else { + const char * op; + switch(func) { + case RC_COMPARE_FUNC_LESS: op = "<"; break; + case RC_COMPARE_FUNC_EQUAL: op = "=="; break; + case RC_COMPARE_FUNC_LEQUAL: op = "<="; break; + case RC_COMPARE_FUNC_GREATER: op = ">"; break; + case RC_COMPARE_FUNC_NOTEQUAL: op = "!="; break; + case RC_COMPARE_FUNC_GEQUAL: op = ">="; break; + default: op = "???"; break; + } + fprintf(f, "%s %s %s", lhs, op, rhs); + } +} + static void rc_print_register(FILE * f, rc_register_file file, int index, unsigned int reladdr) { if (file == RC_FILE_NONE) { fprintf(f, "none"); + } else if (file == RC_FILE_SPECIAL) { + switch(index) { + case RC_SPECIAL_ALU_RESULT: fprintf(f, "aluresult"); break; + default: fprintf(f, "special[%i]", index); break; + } } else { const char * filename; switch(file) { @@ -151,7 +177,17 @@ static void rc_print_instruction(FILE * f, struct rc_instruction * inst) inst->I.TexSrcUnit); } - fprintf(f, ";\n"); + fprintf(f, ";"); + + if (inst->I.WriteALUResult) { + fprintf(f, " [aluresult = ("); + rc_print_comparefunc(f, + (inst->I.WriteALUResult == RC_ALURESULT_X) ? "x" : "w", + inst->I.ALUResultCompare, "0"); + fprintf(f, ")]"); + } + + fprintf(f, "\n"); } /** |