[Mesa-dev] [PATCH] tgsi: Add a conditional move inststruction
Zack Rusin
zackr at vmware.com
Wed Apr 3 18:45:16 PDT 2013
It's part of SM4 (http://goo.gl/4IpeK). It's also fairly
painful to emulate without branching. Most hardware
supports it natively and even llvm has a 'select' opcode
which can handle it without too much hassle.
Signed-off-by: Zack Rusin <zackr at vmware.com>
---
src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c | 19 ++++++++++++++++++-
src/gallium/auxiliary/tgsi/tgsi_exec.c | 17 +++++++++++++++++
src/gallium/auxiliary/tgsi/tgsi_info.c | 1 +
src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h | 2 +-
src/gallium/docs/source/tgsi.rst | 11 +++++++++++
src/gallium/drivers/r600/r600_shader.c | 3 +++
src/gallium/include/pipe/p_shader_tokens.h | 4 +++-
src/gallium/tests/graw/fragment-shader/frag-movc.sh | 11 +++++++++++
8 files changed, 65 insertions(+), 3 deletions(-)
create mode 100644 src/gallium/tests/graw/fragment-shader/frag-movc.sh
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
index dfe581d..3a06542 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
@@ -563,7 +563,6 @@ mad_emit(
}
/* TGSI_OPCODE_MOV */
-
static void
mov_emit(
const struct lp_build_tgsi_action * action,
@@ -573,6 +572,23 @@ mov_emit(
emit_data->output[emit_data->chan] = emit_data->args[0];
}
+/* TGSI_OPCODE_MOVC */
+static void
+movc_emit(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ emit_data->output[emit_data->chan] =
+ LLVMBuildSelect(builder,
+ LLVMBuildFCmp(builder, LLVMRealUNE,
+ emit_data->args[0],
+ bld_base->base.zero, ""),
+ emit_data->args[1], emit_data->args[2], "");
+}
+
+
/* TGSI_OPCODE_MUL */
static void
mul_emit(
@@ -882,6 +898,7 @@ lp_set_default_actions(struct lp_build_tgsi_context * bld_base)
bld_base->op_actions[TGSI_OPCODE_LRP].emit = lrp_emit;
bld_base->op_actions[TGSI_OPCODE_MAD].emit = mad_emit;
bld_base->op_actions[TGSI_OPCODE_MOV].emit = mov_emit;
+ bld_base->op_actions[TGSI_OPCODE_MOVC].emit = movc_emit;
bld_base->op_actions[TGSI_OPCODE_MUL].emit = mul_emit;
bld_base->op_actions[TGSI_OPCODE_DIV].emit = fdiv_emit;
bld_base->op_actions[TGSI_OPCODE_RCP].emit = rcp_emit;
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 8579d8a..b1ab021 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -303,6 +303,19 @@ micro_mov(union tgsi_exec_channel *dst,
dst->u[3] = src->u[3];
}
+
+static void
+micro_movc(union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1,
+ const union tgsi_exec_channel *src2)
+{
+ dst->u[0] = src0->u[0] ? src1->u[0] : src2->u[0];
+ dst->u[1] = src0->u[1] ? src1->u[1] : src2->u[1];
+ dst->u[2] = src0->u[2] ? src1->u[2] : src2->u[2];
+ dst->u[3] = src0->u[3] ? src1->u[3] : src2->u[3];
+}
+
static void
micro_rcp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
@@ -4385,6 +4398,10 @@ exec_instruction(
/* src[2] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, 2);
break;
+
+ case TGSI_OPCODE_MOVC:
+ exec_vector_trinary(mach, inst, micro_movc, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT);
+ break;
default:
assert( 0 );
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c
index 8ae5523..f7b2dc0 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.c
@@ -219,6 +219,7 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
{ 1, 3, 1, 0, 0, 0, OTHR, "TEX2", TGSI_OPCODE_TEX2 },
{ 1, 3, 1, 0, 0, 0, OTHR, "TXB2", TGSI_OPCODE_TXB2 },
{ 1, 3, 1, 0, 0, 0, OTHR, "TXL2", TGSI_OPCODE_TXL2 },
+ { 1, 3, 0, 0, 0, 0, COMP, "MOVC", TGSI_OPCODE_MOVC },
};
const struct tgsi_opcode_info *
diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
index fa30352..7caf15e 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
@@ -197,7 +197,7 @@ OP13_SAMPLE(GATHER4)
OP12(SVIEWINFO)
OP13(SAMPLE_POS)
OP12(SAMPLE_INFO)
-
+OP13(MOVC)
#undef OP00
#undef OP01
diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst
index 28308cb..6c5a02b 100644
--- a/src/gallium/docs/source/tgsi.rst
+++ b/src/gallium/docs/source/tgsi.rst
@@ -72,6 +72,17 @@ used.
dst.w = src.w
+.. opcode:: MOVC - Conditional move
+
+.. math::
+
+ dst.x = src0.x ? src1.x : src2.x
+
+ dst.y = src0.y ? src1.y : src2.y
+
+ dst.z = src0.z ? src1.z : src2.z
+
+ dst.w = src0.w ? src1.w : src2.w
.. opcode:: LIT - Light Coefficients
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index d24d8e7..5aff3d0 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -6080,6 +6080,7 @@ static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
{TGSI_OPCODE_TEX2, 0, FETCH_OP_SAMPLE, tgsi_tex},
{TGSI_OPCODE_TXB2, 0, FETCH_OP_SAMPLE_LB, tgsi_tex},
{TGSI_OPCODE_TXL2, 0, FETCH_OP_SAMPLE_L, tgsi_tex},
+ {TGSI_OPCODE_MOVC, 0, ALU_OP0_NOP, tgsi_unsupported},
{TGSI_OPCODE_LAST, 0, ALU_OP0_NOP, tgsi_unsupported},
};
@@ -6273,6 +6274,7 @@ static struct r600_shader_tgsi_instruction eg_shader_tgsi_instruction[] = {
{TGSI_OPCODE_TEX2, 0, FETCH_OP_SAMPLE, tgsi_tex},
{TGSI_OPCODE_TXB2, 0, FETCH_OP_SAMPLE_LB, tgsi_tex},
{TGSI_OPCODE_TXL2, 0, FETCH_OP_SAMPLE_L, tgsi_tex},
+ {TGSI_OPCODE_MOVC, 0, ALU_OP0_NOP, tgsi_unsupported},
{TGSI_OPCODE_LAST, 0, ALU_OP0_NOP, tgsi_unsupported},
};
@@ -6466,5 +6468,6 @@ static struct r600_shader_tgsi_instruction cm_shader_tgsi_instruction[] = {
{TGSI_OPCODE_TEX2, 0, FETCH_OP_SAMPLE, tgsi_tex},
{TGSI_OPCODE_TXB2, 0, FETCH_OP_SAMPLE_LB, tgsi_tex},
{TGSI_OPCODE_TXL2, 0, FETCH_OP_SAMPLE_L, tgsi_tex},
+ {TGSI_OPCODE_MOVC, 0, ALU_OP0_NOP, tgsi_unsupported},
{TGSI_OPCODE_LAST, 0, ALU_OP0_NOP, tgsi_unsupported},
};
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 478ce25..d2405d7 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -442,7 +442,9 @@ struct tgsi_property_data {
#define TGSI_OPCODE_TXB2 178
#define TGSI_OPCODE_TXL2 179
-#define TGSI_OPCODE_LAST 180
+#define TGSI_OPCODE_MOVC 180
+
+#define TGSI_OPCODE_LAST 181
#define TGSI_SAT_NONE 0 /* do not saturate */
#define TGSI_SAT_ZERO_ONE 1 /* clamp to [0,1] */
diff --git a/src/gallium/tests/graw/fragment-shader/frag-movc.sh b/src/gallium/tests/graw/fragment-shader/frag-movc.sh
new file mode 100644
index 0000000..f6bc7b0
--- /dev/null
+++ b/src/gallium/tests/graw/fragment-shader/frag-movc.sh
@@ -0,0 +1,11 @@
+FRAG
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+DCL TEMP[0]
+IMM[0] FLT32 { 10.0000, 1.0000, 0.0000, 0.0000}
+IMM[1] UINT32 {1, 0, 0, 0}
+0: MUL TEMP[0].x, IN[0].xxxx, IMM[0].xxxx
+1: F2U TEMP[0].x, TEMP[0].xxxx
+2: AND TEMP[0].x, TEMP[0].xxxx, IMM[1].xxxx
+3: MOVC OUT[0], TEMP[0].xxxx, IMM[0].yzzz, IMM[0].yyyz
+4: END
--
1.7.10.4
More information about the mesa-dev
mailing list