summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Stellard <tstellar@gmail.com>2010-07-24 10:19:06 -0700
committerTom Stellard <tstellar@gmail.com>2010-07-24 16:53:19 -0700
commit0847fd67f4671bce59ca08bc7de95e8fd91027d0 (patch)
tree08cb95bb43d83bab040b07bf733bb113d3b7f964
parented6b48c0b423171f1db5f12dda6095b6fb409b9b (diff)
r300/compiler: Fix glean tests texCombine and texCombine4 after latestpresub
presubtract changes.
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c75
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_optimize.c45
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c43
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c117
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h23
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);
/*@}*/