diff options
author | Tom Stellard <tstellar@gmail.com> | 2010-07-24 10:19:06 -0700 |
---|---|---|
committer | Tom Stellard <tstellar@gmail.com> | 2010-07-24 16:53:19 -0700 |
commit | 0847fd67f4671bce59ca08bc7de95e8fd91027d0 (patch) | |
tree | 08cb95bb43d83bab040b07bf733bb113d3b7f964 | |
parent | ed6b48c0b423171f1db5f12dda6095b6fb409b9b (diff) |
r300/compiler: Fix glean tests texCombine and texCombine4 after latestpresub
presubtract changes.
6 files changed, 243 insertions, 62 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c index 5cb4af869f6..af072bb313e 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c @@ -75,51 +75,33 @@ static void reads_normal(struct rc_instruction * fullinst, rc_read_write_chan_fn } } -static void pair_rgb_get_src_refmasks(unsigned int * refmasks, - struct radeon_pair_instruction_rgb inst_rgb) +static void pair_get_src_refmasks(unsigned int * refmasks, + struct rc_pair_instruction * inst, + unsigned int swz, unsigned int src) { - unsigned int arg; + if (swz >= 4) + return; - for(arg = 0; arg < 3; ++arg) { - unsigned int chan; - for(chan = 0; chan < 3; ++chan) { - unsigned int src; - unsigned int swz = - GET_SWZ(inst_rgb.Arg[arg].Swizzle, chan); - if (swz >= 4) - continue; - - src = inst_rgb.Arg[arg].Source; - if(src == RC_PAIR_PRESUB_SRC) { - unsigned int i; - int srcp_regs = rc_presubtract_src_reg_count( - inst_rgb.Src[src].Index); - for(i = 0; i < srcp_regs; i++) { - refmasks[i] |= 1 << swz; - } - } - else { - refmasks[src] |= 1 << swz; + if (swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y || swz == RC_SWIZZLE_Z) { + if(src == RC_PAIR_PRESUB_SRC) { + unsigned int i; + int srcp_regs = + rc_presubtract_src_reg_count( + inst->RGB.Src[src].Index); + for(i = 0; i < srcp_regs; i++) { + refmasks[i] |= 1 << swz; } } + else { + refmasks[src] |= 1 << swz; + } } -} -static void pair_alpha_get_src_refmasks(unsigned int * refmasks, - struct radeon_pair_instruction_alpha inst_alpha) -{ - unsigned int arg; - - for(arg = 0; arg < 3; ++arg) { - unsigned int swz = inst_alpha.Arg[arg].Swizzle; - if(swz >= 4) - continue; - - unsigned int src = inst_alpha.Arg[arg].Source; - if(src == RC_PAIR_PRESUB_SRC) { + if (swz == RC_SWIZZLE_W) { + if (src == RC_PAIR_PRESUB_SRC) { unsigned int i; - int srcp_regs = rc_presubtract_src_reg_count( - inst_alpha.Src[src].Index); + int srcp_regs = rc_presubtract_src_reg_count( + inst->Alpha.Src[src].Index); for(i = 0; i < srcp_regs; i++) { refmasks[i] |= 1 << swz; } @@ -139,8 +121,21 @@ static void reads_pair(struct rc_instruction * fullinst, rc_read_write_mask_fn * opcode is RC_OPCODE_NOP. This is because alpha instructions can * read from rgb source and vice-versa, so we always need to compute * the readmasks for both sets of sources. */ - pair_rgb_get_src_refmasks(refmasks, inst->RGB); - pair_alpha_get_src_refmasks(refmasks, inst->Alpha); + unsigned int arg; + + for(arg = 0; arg < 3; ++arg) { + unsigned int chan; + for(chan = 0; chan < 3; ++chan) { + unsigned int swz_rgb = + GET_SWZ(inst->RGB.Arg[arg].Swizzle, chan); + unsigned int swz_alpha = + GET_SWZ(inst->Alpha.Arg[arg].Swizzle, chan); + pair_get_src_refmasks(refmasks, inst, swz_rgb, + inst->RGB.Arg[arg].Source); + pair_get_src_refmasks(refmasks, inst, swz_alpha, + inst->Alpha.Arg[arg].Source); + } + } for(unsigned int src = 0; src < 3; ++src) { if (inst->RGB.Src[src].Used && (refmasks[src] & RC_MASK_XYZ)) diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c index 8f0fd7aa8ba..560628669d3 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c @@ -480,6 +480,20 @@ static unsigned int src_reads_dst(struct rc_src_register src, return mask; } +/* Return 1 if the source registers has a constant swizzle (e.g. 0, 0.5, 1.0) + * in any of its channels. Return 0 otherwise. */ +static int src_has_const_swz(struct rc_src_register src) { + int chan; + for(chan = 0; chan < 4; chan++) { + unsigned int swz = GET_SWZ(src.Swizzle, chan); + if (swz == RC_SWIZZLE_ZERO || swz == RC_SWIZZLE_HALF + || swz == RC_SWIZZLE_ONE) { + return 1; + } + } + return 0; +} + static void peephole_scan_write(void * data, struct rc_instruction * inst, rc_register_file file, unsigned int index, unsigned int mask) { @@ -506,23 +520,30 @@ static int peephole_add_presub_inv( struct rc_instruction * inst_add) { unsigned int i, swz, mask; - unsigned int modified = 0; + unsigned int can_remove = 0; struct rc_instruction * inst; struct peephole_state s; + if (inst_add->U.I.SaturateMode) + return 0; + swz = inst_add->U.I.SrcReg[0].Swizzle; mask = inst_add->U.I.DstReg.WriteMask; - /* Check if src0 is the 1. */ + + /* Check if src0 is 1. */ + /* XXX It would be nice to use is_src_uniform_constant here, but that + * function only works if the register's file is RC_FILE_NONE */ for(i = 0; i < 4; i++ ) { - if(GET_BIT(mask, i) && GET_SWZ(swz, i) != RC_SWIZZLE_ONE) + if(GET_SWZ(swz, i) != RC_SWIZZLE_ONE) return 0; } - /* src1 needs to be negative and not an absolute value. src1's register - * file needs to be constant or temporary. */ - if(!(inst_add->U.I.SrcReg[1].Negate & mask) + + /* Check src1. */ + if (inst_add->U.I.SrcReg[1].Negate != inst_add->U.I.DstReg.WriteMask || inst_add->U.I.SrcReg[1].Abs || (inst_add->U.I.SrcReg[1].File != RC_FILE_TEMPORARY - && inst_add->U.I.SrcReg[1].File != RC_FILE_CONSTANT)) { + && inst_add->U.I.SrcReg[1].File != RC_FILE_CONSTANT) + || src_has_const_swz(inst_add->U.I.SrcReg[1])) { return 0; } @@ -541,6 +562,10 @@ static int peephole_add_presub_inv( inst_add->U.I.DstReg)) { continue; } + if (inst->U.I.PreSub.Opcode != RC_PRESUB_NONE) { + can_remove = 0; + break; + } /* We must be careful not to modify inst_add, since it * is possible it will remain part of the program. */ inst->U.I.PreSub.SrcReg[0] = inst_add->U.I.SrcReg[1]; @@ -551,8 +576,10 @@ static int peephole_add_presub_inv( inst->U.I.SrcReg[i].File = RC_FILE_PRESUB; inst->U.I.SrcReg[i].Index = RC_PRESUB_INV; - modified++; + can_remove = 1; } + if(!can_remove) + break; rc_for_all_writes_mask(inst, peephole_scan_write, &s); /* If all components of inst_add's destination register have * been written to by subsequent instructions, the original @@ -562,7 +589,7 @@ static int peephole_add_presub_inv( break; } } - if(modified) { + if(can_remove) { rc_remove_instruction(inst_add); return 1; } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c index 6e6fc00de3c..a8712772286 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c @@ -279,16 +279,17 @@ static int destructive_merge_instructions( struct rc_pair_instruction * rgb, struct rc_pair_instruction * alpha) { + const struct rc_opcode_info * opcode; assert(rgb->Alpha.Opcode == RC_OPCODE_NOP); assert(alpha->RGB.Opcode == RC_OPCODE_NOP); - /* Copy alpha args into rgb */ - const struct rc_opcode_info * opcode = rc_get_opcode_info(alpha->Alpha.Opcode); /* Presubtract registers need to be merged first so that registers * needed by the presubtract operation can be placed in src0 and/or * src1. */ /* Merge the rgb presubtract registers. */ + const struct rc_opcode_info * rgb_info = + rc_get_opcode_info(rgb->RGB.Opcode); if (alpha->RGB.Src[RC_PAIR_PRESUB_SRC].Used) { unsigned int srcp_src; unsigned int srcp_regs; @@ -299,7 +300,6 @@ static int destructive_merge_instructions( for(srcp_src = 0; srcp_src < srcp_regs; srcp_src++) { unsigned int arg; int free_source; - const struct rc_opcode_info * info; struct radeon_pair_instruction_source srcp = alpha->RGB.Src[srcp_src]; struct radeon_pair_instruction_source temp; @@ -317,10 +317,20 @@ static int destructive_merge_instructions( return 0; /* Shuffle the sources, so we can put the * presubtract source in the correct place. */ - info = rc_get_opcode_info(rgb->RGB.Opcode); - for (arg = 0; arg < info->NumSrcRegs; arg++) { + for (arg = 0; arg < rgb_info->NumSrcRegs; arg++) { + /*If this arg does not read from an rgb source, + * do nothing. */ + if (rc_source_type_that_arg_reads( + rgb->RGB.Arg[arg].Source, + rgb->RGB.Arg[arg].Swizzle, 3) + != RC_PAIR_SOURCE_RGB) { + continue; + } if (rgb->RGB.Arg[arg].Source == srcp_src) rgb->RGB.Arg[arg].Source = free_source; + /* We need to do this just in case register + * is one of the sources already, but in the + * wrong spot. */ else if(rgb->RGB.Arg[arg].Source == free_source) rgb->RGB.Arg[arg].Source = srcp_src; } @@ -342,7 +352,6 @@ static int destructive_merge_instructions( for(srcp_src = 0; srcp_src < srcp_regs; srcp_src++) { unsigned int arg; int free_source; - const struct rc_opcode_info * info; struct radeon_pair_instruction_source srcp = alpha->Alpha.Src[srcp_src]; struct radeon_pair_instruction_source temp; @@ -360,12 +369,19 @@ static int destructive_merge_instructions( return 0; /* Shuffle the sources, so we can put the * presubtract source in the correct place. */ - info = rc_get_opcode_info(rgb->Alpha.Opcode); - for(arg = 0; arg < info->NumSrcRegs; arg++) { - if(rgb->Alpha.Arg[arg].Source == srcp_src) - rgb->Alpha.Arg[arg].Source = free_source; - else if(rgb->Alpha.Arg[arg].Source == free_source) - rgb->Alpha.Arg[arg].Source = srcp_src; + for(arg = 0; arg < rgb_info->NumSrcRegs; arg++) { + /*If this arg does not read from an alpha + * source, do nothing. */ + if (rc_source_type_that_arg_reads( + rgb->RGB.Arg[arg].Source, + rgb->RGB.Arg[arg].Swizzle, 1) + != RC_PAIR_SOURCE_ALPHA) { + continue; + } + if (rgb->RGB.Arg[arg].Source == srcp_src) + rgb->RGB.Arg[arg].Source = free_source; + else if (rgb->RGB.Arg[arg].Source == free_source) + rgb->RGB.Arg[arg].Source = srcp_src; } temp = rgb->Alpha.Src[srcp_src]; rgb->Alpha.Src[srcp_src] = rgb->Alpha.Src[free_source]; @@ -373,6 +389,9 @@ static int destructive_merge_instructions( } } + /* Copy alpha args into rgb */ + opcode = rc_get_opcode_info(alpha->Alpha.Opcode); + for(unsigned int arg = 0; arg < opcode->NumSrcRegs; ++arg) { unsigned int srcrgb = 0; unsigned int srcalpha = 0; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c index 844ffee6a02..ab7748e02b4 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c @@ -193,12 +193,14 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c, inst->PreSub.SrcReg[i].File; pair->RGB.Src[i].Index = inst->PreSub.SrcReg[i].Index; + pair->RGB.Src[i].Used = 1; } if(alpha) { pair->Alpha.Src[i].File = inst->PreSub.SrcReg[i].File; pair->Alpha.Src[i].Index = inst->PreSub.SrcReg[i].Index; + pair->Alpha.Src[i].Used = 1; } } } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c index 98327f389b9..16166dbccf1 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c @@ -24,7 +24,7 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - +#include <stdio.h> #include "radeon_program_pair.h" @@ -104,3 +104,118 @@ int rc_pair_alloc_source(struct rc_pair_instruction *pair, return candidate; } + +static void pair_foreach_source_callback( + struct rc_pair_instruction * pair, + void * data, + rc_pair_foreach_src_fn cb, + unsigned int swz, + unsigned int src) +{ + /* swz > 3 means that the swizzle is either not used, or a constant + * swizzle (e.g. 0, 1, 0.5). */ + if(swz > 3) + return; + + if(swz == RC_SWIZZLE_W) { + if (src == RC_PAIR_PRESUB_SRC) { + unsigned int i; + unsigned int src_count = rc_presubtract_src_reg_count( + pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Index); + for(i = 0; i < src_count; i++) { + cb(data, &pair->Alpha.Src[i]); + } + } else { + cb(data, &pair->Alpha.Src[src]); + } + } else { + if (src == RC_PAIR_PRESUB_SRC) { + unsigned int i; + unsigned int src_count = rc_presubtract_src_reg_count( + pair->RGB.Src[RC_PAIR_PRESUB_SRC].Index); + for(i = 0; i < src_count; i++) { + cb(data, &pair->RGB.Src[i]); + } + } + else { + cb(data, &pair->RGB.Src[src]); + } + } +} + +void rc_pair_foreach_source_that_alpha_reads( + struct rc_pair_instruction * pair, + void * data, + rc_pair_foreach_src_fn cb) +{ + unsigned int i; + const struct rc_opcode_info * info = + rc_get_opcode_info(pair->Alpha.Opcode); + for(i = 0; i < info->NumSrcRegs; i++) { + pair_foreach_source_callback(pair, data, cb, + GET_SWZ(pair->Alpha.Arg[i].Swizzle, 0), + pair->Alpha.Arg[i].Source); + } +} + +void rc_pair_foreach_source_that_rgb_reads( + struct rc_pair_instruction * pair, + void * data, + rc_pair_foreach_src_fn cb) +{ + unsigned int i; + const struct rc_opcode_info * info = + rc_get_opcode_info(pair->RGB.Opcode); + for(i = 0; i < info->NumSrcRegs; i++) { + unsigned int chan; + unsigned int swz = RC_SWIZZLE_UNUSED; + /* Find a swizzle that is either X,Y,Z,or W. We assume here + * that if one channel swizzles X,Y, or Z, then none of the + * other channels swizzle W, and vice-versa. */ + for(chan = 0; chan < 4; chan++) { + swz = GET_SWZ(pair->RGB.Arg[i].Swizzle, chan); + if(swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y + || swz == RC_SWIZZLE_Z || swz == RC_SWIZZLE_W) + continue; + } + pair_foreach_source_callback(pair, data, cb, + swz, + pair->RGB.Arg[i].Source); + } +} + +/*return 0 for rgb, 1 for alpha -1 for error. */ + +rc_pair_source_type rc_source_type_that_arg_reads( + unsigned int source, + unsigned int swizzle, + unsigned int channels) +{ + unsigned int chan; + unsigned int swz = RC_SWIZZLE_UNUSED; + int isRGB = 0; + int isAlpha = 0; + fprintf(stderr,"source=%u channels=%u swz=%u\n",source,channels,swizzle); + /* Find a swizzle that is either X,Y,Z,or W. We assume here + * that if one channel swizzles X,Y, or Z, then none of the + * other channels swizzle W, and vice-versa. */ + for(chan = 0; chan < channels; chan++) { + swz = GET_SWZ(swizzle, chan); + if (swz == RC_SWIZZLE_W) { + isAlpha = 1; + } else if (swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y + || RC_SWIZZLE_Z) { + isRGB = 1; + } + fprintf(stderr,"%u:isAlpha=%u isRGB=%u\n",chan, isAlpha, isRGB); + } + assert(!isRGB || !isAlpha); + + if(!isRGB && !isAlpha) + return RC_PAIR_SOURCE_NONE; + + if (isRGB) + return RC_PAIR_SOURCE_RGB; + /*isAlpha*/ + return RC_PAIR_SOURCE_ALPHA; +} diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h index b77491375e6..a7cd8104507 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h @@ -107,6 +107,14 @@ struct rc_pair_instruction { unsigned int Nop:1; }; +typedef void (*rc_pair_foreach_src_fn) + (void *, struct radeon_pair_instruction_source *); + +typedef enum { + RC_PAIR_SOURCE_NONE = 0, + RC_PAIR_SOURCE_RGB, + RC_PAIR_SOURCE_ALPHA +} rc_pair_source_type; /** * General helper functions for dealing with the paired instruction format. @@ -115,6 +123,21 @@ struct rc_pair_instruction { int rc_pair_alloc_source(struct rc_pair_instruction *pair, unsigned int rgb, unsigned int alpha, rc_register_file file, unsigned int index); + +void rc_pair_foreach_source_that_alpha_reads( + struct rc_pair_instruction * pair, + void * data, + rc_pair_foreach_src_fn cb); + +void rc_pair_foreach_source_that_rgb_reads( + struct rc_pair_instruction * pair, + void * data, + rc_pair_foreach_src_fn cb); + +rc_pair_source_type rc_source_type_that_arg_reads( + unsigned int source, + unsigned int swizzle, + unsigned int channels); /*@}*/ |