Mesa (master): r300/compiler: Enable swizzle packing in the allocator for r300 and r400

Tom Stellard tstellar at kemper.freedesktop.org
Sat Apr 30 18:26:21 UTC 2011


Module: Mesa
Branch: master
Commit: d379e938f0ed10f193f2aa6c60e283d7af6360e4
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d379e938f0ed10f193f2aa6c60e283d7af6360e4

Author: Tom Stellard <tstellar at gmail.com>
Date:   Tue Apr 26 00:29:39 2011 -0700

r300/compiler: Enable swizzle packing in the allocator for r300 and r400

---

 .../dri/r300/compiler/r300_fragprog_swizzle.c      |   12 +++
 .../dri/r300/compiler/r300_fragprog_swizzle.h      |    1 +
 .../dri/r300/compiler/radeon_compiler_util.c       |   35 +++++++-
 .../dri/r300/compiler/radeon_compiler_util.h       |    8 ++
 .../dri/r300/compiler/radeon_pair_regalloc.c       |   88 ++++++++++++++-----
 .../drivers/dri/r300/compiler/radeon_variable.c    |   17 +----
 6 files changed, 120 insertions(+), 41 deletions(-)

diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c
index 5223aaa..603818f 100644
--- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c
@@ -87,6 +87,18 @@ static const struct swizzle_data* lookup_native_swizzle(unsigned int swizzle)
 	return 0;
 }
 
+/**
+ * Determines if the given swizzle is valid for r300/r400.  In most situations
+ * it is better to use r300_swizzle_is_native() which can be accesed via
+ * struct radeon_compiler *c; c->SwizzleCaps->IsNative().
+ */
+int r300_swizzle_is_native_basic(unsigned int swizzle)
+{
+	if(lookup_native_swizzle(swizzle))
+		return 1;
+	else
+		return 0;
+}
 
 /**
  * Check whether the given instruction supports the swizzle and negate
diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.h b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.h
index 118476a..f2635be 100644
--- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.h
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.h
@@ -34,5 +34,6 @@ extern struct rc_swizzle_caps r300_swizzle_caps;
 
 unsigned int r300FPTranslateRGBSwizzle(unsigned int src, unsigned int swizzle);
 unsigned int r300FPTranslateAlphaSwizzle(unsigned int src, unsigned int swizzle);
+int r300_swizzle_is_native_basic(unsigned int swizzle);
 
 #endif /* __R300_FRAGPROG_SWIZZLE_H_ */
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
index 3a6b0a7..b077e7b 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
@@ -141,7 +141,11 @@ static unsigned int srcs_need_rewrite(const struct rc_opcode_info * info)
 	}
 }
 
-static unsigned int adjust_channels(
+/**
+ * @return A swizzle the results from converting old_swizzle using
+ * conversion_swizzle
+ */
+unsigned int rc_adjust_channels(
 	unsigned int old_swizzle,
 	unsigned int conversion_swizzle)
 {
@@ -197,7 +201,8 @@ void rc_pair_rewrite_writemask(
 
 	for (i = 0; i < info->NumSrcRegs; i++) {
 		sub->Arg[i].Swizzle =
-			adjust_channels(sub->Arg[i].Swizzle, conversion_swizzle);
+			rc_adjust_channels(sub->Arg[i].Swizzle,
+						conversion_swizzle);
 	}
 }
 
@@ -207,7 +212,7 @@ static void normal_rewrite_writemask_cb(
 	struct rc_src_register * src)
 {
 	unsigned int * new_mask = (unsigned int *)userdata;
-	src->Swizzle = adjust_channels(src->Swizzle, *new_mask);
+	src->Swizzle = rc_adjust_channels(src->Swizzle, *new_mask);
 }
 
 /**
@@ -605,3 +610,27 @@ struct rc_instruction * rc_match_bgnloop(struct rc_instruction * bgnloop)
 	}
 	return NULL;
 }
+
+/**
+ * @return A conversion swizzle for converting from old_mask->new_mask
+ */
+unsigned int rc_make_conversion_swizzle(
+	unsigned int old_mask,
+	unsigned int new_mask)
+{
+	unsigned int conversion_swizzle = rc_init_swizzle(RC_SWIZZLE_UNUSED, 0);
+	unsigned int old_idx;
+	unsigned int new_idx = 0;
+	for (old_idx = 0; old_idx < 4; old_idx++) {
+		if (!GET_BIT(old_mask, old_idx))
+			continue;
+		for ( ; new_idx < 4; new_idx++) {
+			if (GET_BIT(new_mask, new_idx)) {
+				SET_SWZ(conversion_swizzle, old_idx, new_idx);
+				new_idx++;
+				break;
+			}
+		}
+	}
+	return conversion_swizzle;
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
index 1a0b962..2af289d 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
@@ -27,6 +27,10 @@ rc_swizzle rc_mask_to_swizzle(unsigned int mask);
 
 unsigned swizzle_mask(unsigned swizzle, unsigned mask);
 
+unsigned int rc_adjust_channels(
+	unsigned int old_swizzle,
+	unsigned int conversion_swizzle);
+
 void rc_pair_rewrite_writemask(
 	struct rc_pair_sub_instruction * sub,
 	unsigned int conversion_swizzle);
@@ -78,4 +82,8 @@ rc_opcode rc_get_flow_control_inst(struct rc_instruction * inst);
 struct rc_instruction * rc_match_endloop(struct rc_instruction * endloop);
 struct rc_instruction * rc_match_bgnloop(struct rc_instruction * bgnloop);
 
+unsigned int rc_make_conversion_swizzle(
+	unsigned int old_mask,
+	unsigned int new_mask);
+
 #endif /* RADEON_PROGRAM_UTIL_H */
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_regalloc.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_regalloc.c
index fd03c73..828c753 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_regalloc.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_regalloc.c
@@ -34,6 +34,7 @@
 #include "program/register_allocate.h"
 #include "ralloc.h"
 
+#include "r300_fragprog_swizzle.h"
 #include "radeon_compiler.h"
 #include "radeon_compiler_util.h"
 #include "radeon_dataflow.h"
@@ -232,6 +233,26 @@ static unsigned int is_derivative(rc_opcode op)
 	return (op == RC_OPCODE_DDX || op == RC_OPCODE_DDY);
 }
 
+static int find_class(
+	struct rc_class * classes,
+	unsigned int writemask,
+	unsigned int max_writemask_count)
+{
+	unsigned int i;
+	for (i = 0; i < RC_REG_CLASS_COUNT; i++) {
+		unsigned int j;
+		if (classes[i].WritemaskCount > max_writemask_count) {
+			continue;
+		}
+		for (j = 0; j < 3; j++) {
+			if (classes[i].Writemasks[j] == writemask) {
+				return i;
+			}
+		}
+	}
+	return -1;
+}
+
 static enum rc_reg_class variable_get_class(
 	struct rc_variable * variable,
 	struct rc_class * classes)
@@ -240,25 +261,48 @@ static enum rc_reg_class variable_get_class(
 	unsigned int can_change_writemask= 1;
 	unsigned int writemask = rc_variable_writemask_sum(variable);
 	struct rc_list * readers = rc_variable_readers_union(variable);
+	int class_index;
 
 	if (!variable->C->is_r500) {
-		unsigned int mask_count = 0;
+		struct rc_class c;
 		/* The assumption here is that if an instruction has type
 		 * RC_INSTRUCTION_NORMAL then it is a TEX instruction.
 		 * r300 and r400 can't swizzle the result of a TEX lookup. */
 		if (variable->Inst->Type == RC_INSTRUCTION_NORMAL) {
 			writemask = RC_MASK_XYZW;
 		}
-		for (i = 0; i < 4; i++) {
-			if (GET_BIT(writemask, i)) {
-				mask_count++;
-			}
+
+		/* Check if it is possible to do swizzle packing for r300/r400
+		 * without creating non-native swizzles. */
+		class_index = find_class(classes, writemask, 3);
+		if (class_index < 0) {
+			goto error;
 		}
-		/* XXX We should do swizzle packing for r300 and r400 here.
-		 * We need to figure out how not to create non-native
-		 * swizzles. */
-		if (mask_count > 1) {
-			can_change_writemask = 0;
+		c = classes[class_index];
+		for (i = 0; i < c.WritemaskCount; i++) {
+			int j;
+			unsigned int conversion_swizzle =
+						rc_make_conversion_swizzle(
+						writemask, c.Writemasks[i]);
+			for (j = 0; j < variable->ReaderCount; j++) {
+				unsigned int old_swizzle;
+				unsigned int new_swizzle;
+				struct rc_reader r = variable->Readers[j];
+				if (r.Inst->Type == RC_INSTRUCTION_PAIR ) {
+					old_swizzle = r.U.P.Arg->Swizzle;
+				} else {
+					old_swizzle = r.U.I.Src->Swizzle;
+				}
+				new_swizzle = rc_adjust_channels(
+					old_swizzle, conversion_swizzle);
+				if (!r300_swizzle_is_native_basic(new_swizzle)) {
+					can_change_writemask = 0;
+					break;
+				}
+			}
+			if (!can_change_writemask) {
+				break;
+			}
 		}
 	}
 
@@ -285,20 +329,18 @@ static enum rc_reg_class variable_get_class(
 			}
 		}
 	}
-	for (i = 0; i < RC_REG_CLASS_COUNT; i++) {
-		unsigned int j;
-		if (!can_change_writemask && classes[i].WritemaskCount > 1) {
-			continue;
-		}
-		for (j = 0; j < 3; j++) {
-			if (classes[i].Writemasks[j] == writemask) {
-				return classes[i].Class;
-			}
-		}
-	}
-	rc_error(variable->C, "Could not find class for index=%u mask=%u\n",
+
+	class_index = find_class(classes, writemask,
+						can_change_writemask ? 3 : 1);
+	if (class_index > -1) {
+		return classes[class_index].Class;
+	} else {
+error:
+		rc_error(variable->C,
+				"Could not find class for index=%u mask=%u\n",
 				variable->Dst.Index, writemask);
-	return 0;
+		return 0;
+	}
 }
 
 static unsigned int overlap_live_intervals_array(
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_variable.c b/src/mesa/drivers/dri/r300/compiler/radeon_variable.c
index 082717e..16fa5d2 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_variable.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_variable.c
@@ -44,24 +44,11 @@ void rc_variable_change_dst(
 	unsigned int new_index,
 	unsigned int new_writemask)
 {
-	unsigned int new_idx, old_idx;
-	unsigned int conversion_swizzle = rc_init_swizzle(RC_SWIZZLE_UNUSED, 0);
 	struct rc_variable * var_ptr;
 	struct rc_list * readers;
 	unsigned int old_mask = rc_variable_writemask_sum(var);
-
-	new_idx = 0;
-	for (old_idx = 0; old_idx < 4; old_idx++) {
-		if (!GET_BIT(old_mask, old_idx))
-			continue;
-		for ( ; new_idx < 4; new_idx++) {
-			if (GET_BIT(new_writemask, new_idx)) {
-				SET_SWZ(conversion_swizzle, old_idx, new_idx);
-				new_idx++;
-				break;
-			}
-		}
-	}
+	unsigned int conversion_swizzle =
+			rc_make_conversion_swizzle(old_mask, new_writemask);
 
 	for (var_ptr = var; var_ptr; var_ptr = var_ptr->Friend) {
 		if (var_ptr->Inst->Type == RC_INSTRUCTION_NORMAL) {




More information about the mesa-commit mailing list