[Mesa-dev] [PATCH] r600g: Fix missing SET_TEXTURE_OFFSETS

Glenn Kennard glenn.kennard at gmail.com
Sun Aug 17 13:26:19 PDT 2014


SB needs a bit of special handling to handle
instructions without obvious side effects, to
avoid it deleting them.

Fixes failing non-const ARB_gpu_shader5
textureOffsets piglits with sb enabled.

Signed-off-by: Glenn Kennard <glenn.kennard at gmail.com>
---
 src/gallium/drivers/r600/r600_isa.h            |   9 +-
 src/gallium/drivers/r600/sb/sb_bc_finalize.cpp | 119 ++++++++++++++-----------
 src/gallium/drivers/r600/sb/sb_bc_parser.cpp   |  13 ++-
 src/gallium/drivers/r600/sb/sb_pass.h          |   3 +
 4 files changed, 87 insertions(+), 57 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_isa.h b/src/gallium/drivers/r600/r600_isa.h
index c6bb869..ec3f702 100644
--- a/src/gallium/drivers/r600/r600_isa.h
+++ b/src/gallium/drivers/r600/r600_isa.h
@@ -123,6 +123,9 @@ enum fetch_op_flags
 
 	FF_VTX		= (1<<5),
 	FF_MEM		= (1<<6),
+
+	FF_SET_TEXTURE_OFFSETS = (1<<7),
+	FF_USE_TEXTURE_OFFSETS = (1<<8),
 };
 
 /* flags for CF instructions */
@@ -523,7 +526,7 @@ static const struct fetch_op_info fetch_op_table[] = {
 		{"GET_GRADIENTS_H_FINE",          {       -1,        -1,  0x000107,  0x000107 }, FF_GETGRAD },
 		{"GET_GRADIENTS_V_FINE",          {       -1,        -1,  0x000108,  0x000108 }, FF_GETGRAD },
 		{"GET_LERP",                      { 0x000009,  0x000009,        -1,        -1 }, 0 },
-		{"SET_TEXTURE_OFFSETS",           {       -1,        -1,  0x000009,  0x000009 }, 0 },
+		{"SET_TEXTURE_OFFSETS",           {       -1,        -1,  0x000009,  0x000009 }, FF_SET_TEXTURE_OFFSETS },
 		{"KEEP_GRADIENTS",                {       -1,  0x00000A,  0x00000A,  0x00000A }, 0 },
 		{"SET_GRADIENTS_H",               { 0x00000B,  0x00000B,  0x00000B,  0x00000B }, FF_SETGRAD },
 		{"SET_GRADIENTS_V",               { 0x00000C,  0x00000C,  0x00000C,  0x00000C }, FF_SETGRAD },
@@ -550,7 +553,7 @@ static const struct fetch_op_info fetch_op_table[] = {
 		{"GATHER4",                       {       -1,        -1,  0x000015,  0x000015 }, FF_TEX },
 		{"SAMPLE_G_LB",                   { 0x000016,  0x000016,  0x000016,  0x000016 }, FF_TEX | FF_USEGRAD},
 		{"SAMPLE_G_LZ",                   { 0x000017,  0x000017,        -1,        -1 }, FF_TEX | FF_USEGRAD},
-		{"GATHER4_O",                     {       -1,        -1,  0x000017,  0x000017 }, FF_TEX },
+		{"GATHER4_O",                     {       -1,        -1,  0x000017,  0x000017 }, FF_TEX | FF_USE_TEXTURE_OFFSETS},
 		{"SAMPLE_C",                      { 0x000018,  0x000018,  0x000018,  0x000018 }, FF_TEX },
 		{"SAMPLE_C_L",                    { 0x000019,  0x000019,  0x000019,  0x000019 }, FF_TEX },
 		{"SAMPLE_C_LB",                   { 0x00001A,  0x00001A,  0x00001A,  0x00001A }, FF_TEX },
@@ -560,7 +563,7 @@ static const struct fetch_op_info fetch_op_table[] = {
 		{"GATHER4_C",                     {       -1,        -1,  0x00001D,  0x00001D }, FF_TEX },
 		{"SAMPLE_C_G_LB",                 { 0x00001E,  0x00001E,  0x00001E,  0x00001E }, FF_TEX | FF_USEGRAD},
 		{"SAMPLE_C_G_LZ",                 { 0x00001F,  0x00001F,        -1,        -1 }, FF_TEX | FF_USEGRAD},
-		{"GATHER4_C_O",                   {       -1,        -1,  0x00001F,  0x00001F }, FF_TEX }
+		{"GATHER4_C_O",                   {       -1,        -1,  0x00001F,  0x00001F }, FF_TEX | FF_USE_TEXTURE_OFFSETS}
 };
 
 static const struct cf_op_info cf_op_table[] = {
diff --git a/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp b/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp
index 99a20eb..5c22f96 100644
--- a/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp
+++ b/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp
@@ -394,81 +394,96 @@ void bc_finalizer::finalize_alu_src(alu_group_node* g, alu_node* a) {
 	}
 }
 
-void bc_finalizer::emit_set_grad(fetch_node* f) {
+void bc_finalizer::copy_fetch_src(fetch_node &dst, fetch_node &src, unsigned arg_start)
+{
+	int reg = -1;
 
-	assert(f->src.size() == 12);
-	unsigned ops[2] = { FETCH_OP_SET_GRADIENTS_V, FETCH_OP_SET_GRADIENTS_H };
+	for (unsigned chan = 0; chan < 4; ++chan) {
 
-	unsigned arg_start = 0;
+		dst.bc.dst_sel[chan] = SEL_MASK;
 
-	for (unsigned op = 0; op < 2; ++op) {
-		fetch_node *n = sh.create_fetch();
-		n->bc.set_op(ops[op]);
+		unsigned sel = SEL_MASK;
 
-		// FIXME extract this loop into a separate method and reuse it
+		value *v = src.src[arg_start + chan];
 
-		int reg = -1;
+		if (!v || v->is_undef()) {
+			sel = SEL_MASK;
+		} else if (v->is_const()) {
+			literal l = v->literal_value;
+			if (l == literal(0))
+				sel = SEL_0;
+			else if (l == literal(1.0f))
+				sel = SEL_1;
+			else {
+				sblog << "invalid fetch constant operand  " << chan << " ";
+				dump::dump_op(&src);
+				sblog << "\n";
+				abort();
+			}
 
-		arg_start += 4;
+		} else if (v->is_any_gpr()) {
+			unsigned vreg = v->gpr.sel();
+			unsigned vchan = v->gpr.chan();
 
-		for (unsigned chan = 0; chan < 4; ++chan) {
+			if (reg == -1)
+				reg = vreg;
+			else if ((unsigned)reg != vreg) {
+				sblog << "invalid fetch source operand  " << chan << " ";
+				dump::dump_op(&src);
+				sblog << "\n";
+				abort();
+			}
 
-			n->bc.dst_sel[chan] = SEL_MASK;
+			sel = vchan;
 
-			unsigned sel = SEL_MASK;
+		} else {
+			sblog << "invalid fetch source operand  " << chan << " ";
+			dump::dump_op(&src);
+			sblog << "\n";
+			abort();
+		}
 
-			value *v = f->src[arg_start + chan];
+		dst.bc.src_sel[chan] = sel;
+	}
 
-			if (!v || v->is_undef()) {
-				sel = SEL_MASK;
-			} else if (v->is_const()) {
-				literal l = v->literal_value;
-				if (l == literal(0))
-					sel = SEL_0;
-				else if (l == literal(1.0f))
-					sel = SEL_1;
-				else {
-					sblog << "invalid fetch constant operand  " << chan << " ";
-					dump::dump_op(f);
-					sblog << "\n";
-					abort();
-				}
+	if (reg >= 0)
+		update_ngpr(reg);
 
-			} else if (v->is_any_gpr()) {
-				unsigned vreg = v->gpr.sel();
-				unsigned vchan = v->gpr.chan();
+	dst.bc.src_gpr = reg >= 0 ? reg : 0;
+}
 
-				if (reg == -1)
-					reg = vreg;
-				else if ((unsigned)reg != vreg) {
-					sblog << "invalid fetch source operand  " << chan << " ";
-					dump::dump_op(f);
-					sblog << "\n";
-					abort();
-				}
+void bc_finalizer::emit_set_grad(fetch_node* f) {
 
-				sel = vchan;
+	assert(f->src.size() == 12);
+	unsigned ops[2] = { FETCH_OP_SET_GRADIENTS_V, FETCH_OP_SET_GRADIENTS_H };
 
-			} else {
-				sblog << "invalid fetch source operand  " << chan << " ";
-				dump::dump_op(f);
-				sblog << "\n";
-				abort();
-			}
+	unsigned arg_start = 0;
 
-			n->bc.src_sel[chan] = sel;
-		}
+	for (unsigned op = 0; op < 2; ++op) {
+		fetch_node *n = sh.create_fetch();
+		n->bc.set_op(ops[op]);
 
-		if (reg >= 0)
-			update_ngpr(reg);
+		arg_start += 4;
 
-		n->bc.src_gpr = reg >= 0 ? reg : 0;
+		copy_fetch_src(*n, *f, arg_start);
 
 		f->insert_before(n);
 	}
 
 }
 
+void bc_finalizer::emit_set_texture_offsets(fetch_node &f) {
+	assert(f.src.size() == 8);
+
+	fetch_node *n = sh.create_fetch();
+
+	n->bc.set_op(FETCH_OP_SET_TEXTURE_OFFSETS);
+
+	copy_fetch_src(*n, f, 4);
+
+	f.insert_before(n);
+}
+
 void bc_finalizer::finalize_fetch(fetch_node* f) {
 
 	int reg = -1;
@@ -483,6 +498,8 @@ void bc_finalizer::finalize_fetch(fetch_node* f) {
 		src_count = 1;
 	} else if (flags & FF_USEGRAD) {
 		emit_set_grad(f);
+	} else if (flags & FF_USE_TEXTURE_OFFSETS) {
+		emit_set_texture_offsets(*f);
 	}
 
 	for (unsigned chan = 0; chan < src_count; ++chan) {
diff --git a/src/gallium/drivers/r600/sb/sb_bc_parser.cpp b/src/gallium/drivers/r600/sb/sb_bc_parser.cpp
index 7181e27..346ccc9 100644
--- a/src/gallium/drivers/r600/sb/sb_bc_parser.cpp
+++ b/src/gallium/drivers/r600/sb/sb_bc_parser.cpp
@@ -520,7 +520,7 @@ int bc_parser::decode_fetch_clause(cf_node* cf) {
 
 int bc_parser::prepare_fetch_clause(cf_node *cf) {
 
-	vvec grad_v, grad_h;
+	vvec grad_v, grad_h, texture_offsets;
 
 	for (node_iterator I = cf->begin(), E = cf->end(); I != E; ++I) {
 
@@ -538,7 +538,7 @@ int bc_parser::prepare_fetch_clause(cf_node *cf) {
 			sh->uses_gradients = true;
 		}
 
-		if (flags & FF_SETGRAD) {
+		if (flags & (FF_SETGRAD | FF_SET_TEXTURE_OFFSETS)) {
 
 			vvec *grad = NULL;
 
@@ -549,6 +549,9 @@ int bc_parser::prepare_fetch_clause(cf_node *cf) {
 				case FETCH_OP_SET_GRADIENTS_H:
 					grad = &grad_h;
 					break;
+				case FETCH_OP_SET_TEXTURE_OFFSETS:
+					grad = &texture_offsets;
+					break;
 				default:
 					assert(!"unexpected SET_GRAD instruction");
 					return -1;
@@ -568,11 +571,15 @@ int bc_parser::prepare_fetch_clause(cf_node *cf) {
 					(*grad)[s] = sh->get_const_value(1.0f);
 			}
 		} else {
-
+			// Fold source values for instructions with hidden target values in to the instructions
+			// using them. The set instructions are later re-emitted by bc_finalizer
 			if (flags & FF_USEGRAD) {
 				n->src.resize(12);
 				std::copy(grad_v.begin(), grad_v.end(), n->src.begin() + 4);
 				std::copy(grad_h.begin(), grad_h.end(), n->src.begin() + 8);
+			} else if (flags & FF_USE_TEXTURE_OFFSETS) {
+				n->src.resize(8);
+				std::copy(texture_offsets.begin(), texture_offsets.end(), n->src.begin() + 4);
 			} else {
 				n->src.resize(4);
 			}
diff --git a/src/gallium/drivers/r600/sb/sb_pass.h b/src/gallium/drivers/r600/sb/sb_pass.h
index c955656..812d14a 100644
--- a/src/gallium/drivers/r600/sb/sb_pass.h
+++ b/src/gallium/drivers/r600/sb/sb_pass.h
@@ -713,6 +713,9 @@ public:
 
 	void cf_peephole();
 
+private:
+	void copy_fetch_src(fetch_node &dst, fetch_node &src, unsigned arg_start);
+	void emit_set_texture_offsets(fetch_node &f);
 };
 
 
-- 
1.9.1



More information about the mesa-dev mailing list