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 <za...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev