gallium: Disambiguate TGSI_OPCODE_IF.
authorJosé Fonseca <jfonseca@vmware.com>
Wed, 17 Apr 2013 09:47:03 +0000 (10:47 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Wed, 17 Apr 2013 09:54:08 +0000 (10:54 +0100)
TGSI_OPCODE_IF condition had two possible interpretations:

- src.x != 0.0f

  - Mesa statetracker when PIPE_SHADER_CAP_INTEGERS was false either for
    vertex and fragment shaders
  - gallivm/llvmpipe
  - postprocess
  - vl state tracker
  - vega state tracker
  - most old drivers
  - old internal state trackers
  - many graw examples

- src.x != 0U

  - Mesa statetracker when PIPE_SHADER_CAP_INTEGERS was true for both
    vertex and fragment shaders
  - tgsi_exec/softpipe
  - r600
  - radeonsi
  - nv50

And drivers that use draw module also were a mess (because Mesa would
emit float IFs, but draw module supports native integers so it would
interpret IF arg as integers...)

This sort of works if the source argument is limited to float +0.0f or
+1.0f, integer 0, but would fail if source is float -0.0f, or integer in
the float NaN range.  It could also fail if source is integer 1, and
hardware flushes denormalized numbers to zero.

But with this change there are now two opcodes, IF and UIF, with clear
meaning.

Drivers that do not support native integers do not need to worry about
UIF.  However, for backwards compatibility with old state trackers and
examples, it is advisable that native integer capable drivers also
support the float IF opcode.

I tried to implement this for r600 and radeonsi based on the surrounding
code.  I couldn't do this for nouveau, so I just shunted IF/UIF
together, which matches the current behavior.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Reviewed-by: Marek Olšák <maraeo@gmail.com>
v2:
- Incorporate Roland's feedback.
- Fix r600_shader.c merge conflict.
- Fix typo in radeon, spotted by Michel Dänzer.
- Incorporte  Christoph Bumiller's patch to handle TGSI_OPCODE_IF(float)
  properly in nv50/ir.

17 files changed:
src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi_aos.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi_info.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
src/gallium/auxiliary/tgsi/tgsi_dump.c
src/gallium/auxiliary/tgsi/tgsi_exec.c
src/gallium/auxiliary/tgsi/tgsi_info.c
src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
src/gallium/docs/source/tgsi.rst
src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
src/gallium/drivers/nv50/codegen/nv50_ir_lowering_nv50.cpp
src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp
src/gallium/drivers/r600/r600_shader.c
src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
src/gallium/include/pipe/p_shader_tokens.h
src/mesa/state_tracker/st_glsl_to_tgsi.cpp
src/mesa/state_tracker/st_mesa_to_tgsi.c

index c71c1f111bd073c6aa40863657cc429bbae14413..e1c362be4a851862fa242b332b55dadd03236f64 100644 (file)
@@ -868,6 +868,7 @@ lp_set_default_actions(struct lp_build_tgsi_context * bld_base)
    bld_base->op_actions[TGSI_OPCODE_COS].fetch_args = scalar_unary_fetch_args;
    bld_base->op_actions[TGSI_OPCODE_EX2].fetch_args = scalar_unary_fetch_args;
    bld_base->op_actions[TGSI_OPCODE_IF].fetch_args = scalar_unary_fetch_args;
+   bld_base->op_actions[TGSI_OPCODE_UIF].fetch_args = scalar_unary_fetch_args;
    bld_base->op_actions[TGSI_OPCODE_KIL].fetch_args = kil_fetch_args;
    bld_base->op_actions[TGSI_OPCODE_KILP].fetch_args = kilp_fetch_args;
    bld_base->op_actions[TGSI_OPCODE_RCP].fetch_args = scalar_unary_fetch_args;
index 98bce0eb26910951f5a27ae3bac18455617558c8..223184d554afdf3d27a61a26fb62a610ffea1743 100644 (file)
@@ -837,6 +837,7 @@ lp_emit_instruction_aos(
       return FALSE;
 
    case TGSI_OPCODE_IF:
+   case TGSI_OPCODE_UIF:
       return FALSE;
 
    case TGSI_OPCODE_BGNLOOP:
index 3c79abf7d5216ca69e0c9047ec8d53b97ecca6dd..b00aa094d38a445fb22fa5a5233b250fdc8cb138 100644 (file)
@@ -389,6 +389,7 @@ analyse_instruction(struct analysis_context *ctx,
 
    switch (inst->Instruction.Opcode) {
    case TGSI_OPCODE_IF:
+   case TGSI_OPCODE_UIF:
    case TGSI_OPCODE_ELSE:
    case TGSI_OPCODE_ENDIF:
    case TGSI_OPCODE_BGNLOOP:
index 239530de72940444667190626843d0702cec3a7a..73965360e7b75285e1eb45ac0459bafa4bf70296 100644 (file)
@@ -1732,6 +1732,7 @@ near_end_of_shader(struct lp_build_tgsi_soa_context *bld,
          opcode == TGSI_OPCODE_CAL ||
          opcode == TGSI_OPCODE_CALLNZ ||
          opcode == TGSI_OPCODE_IF ||
+          opcode == TGSI_OPCODE_UIF ||
          opcode == TGSI_OPCODE_BGNLOOP ||
          opcode == TGSI_OPCODE_SWITCH)
         return FALSE;
@@ -2394,6 +2395,21 @@ if_emit(
    lp_exec_mask_cond_push(&bld->exec_mask, tmp);
 }
 
+static void
+uif_emit(
+   const struct lp_build_tgsi_action * action,
+   struct lp_build_tgsi_context * bld_base,
+   struct lp_build_emit_data * emit_data)
+{
+   LLVMValueRef tmp;
+   struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+   struct lp_build_context *uint_bld = &bld_base->uint_bld;
+
+   tmp = lp_build_cmp(uint_bld, PIPE_FUNC_NOTEQUAL,
+                      emit_data->args[0], uint_bld->zero);
+   lp_exec_mask_cond_push(&bld->exec_mask, tmp);
+}
+
 static void
 bgnloop_emit(
    const struct lp_build_tgsi_action * action,
@@ -2742,6 +2758,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
    bld.bld_base.op_actions[TGSI_OPCODE_ENDLOOP].emit = endloop_emit;
    bld.bld_base.op_actions[TGSI_OPCODE_ENDSUB].emit = endsub_emit;
    bld.bld_base.op_actions[TGSI_OPCODE_IF].emit = if_emit;
+   bld.bld_base.op_actions[TGSI_OPCODE_UIF].emit = uif_emit;
    bld.bld_base.op_actions[TGSI_OPCODE_KIL].emit = kil_emit;
    bld.bld_base.op_actions[TGSI_OPCODE_KILP].emit = kilp_emit;
    bld.bld_base.op_actions[TGSI_OPCODE_NRM].emit = nrm_emit;
index 365665fa6f789764bb3dea9ec6963148d227de2d..77b75b1e0bf452872755c40fcb696ee9d24b8641 100644 (file)
@@ -589,6 +589,7 @@ iter_instruction(
 
    switch (inst->Instruction.Opcode) {
    case TGSI_OPCODE_IF:
+   case TGSI_OPCODE_UIF:
    case TGSI_OPCODE_ELSE:
    case TGSI_OPCODE_BGNLOOP:
    case TGSI_OPCODE_ENDLOOP:
@@ -600,6 +601,7 @@ iter_instruction(
 
    /* update indentation */
    if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
+       inst->Instruction.Opcode == TGSI_OPCODE_UIF ||
        inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
        inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
       ctx->indentation += indent_spaces;
index 8579d8a57eb143790e6639529def6e5fd765e82e..05f749ed6c174d781eb8bc530c52dba9e38906ca 100644 (file)
@@ -3982,6 +3982,28 @@ exec_instruction(
       mach->CondStack[mach->CondStackTop++] = mach->CondMask;
       FETCH( &r[0], 0, TGSI_CHAN_X );
       /* update CondMask */
+      if( ! r[0].f[0] ) {
+         mach->CondMask &= ~0x1;
+      }
+      if( ! r[0].f[1] ) {
+         mach->CondMask &= ~0x2;
+      }
+      if( ! r[0].f[2] ) {
+         mach->CondMask &= ~0x4;
+      }
+      if( ! r[0].f[3] ) {
+         mach->CondMask &= ~0x8;
+      }
+      UPDATE_EXEC_MASK(mach);
+      /* Todo: If CondMask==0, jump to ELSE */
+      break;
+
+   case TGSI_OPCODE_UIF:
+      /* push CondMask */
+      assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
+      mach->CondStack[mach->CondStackTop++] = mach->CondMask;
+      IFETCH( &r[0], 0, TGSI_CHAN_X );
+      /* update CondMask */
       if( ! r[0].u[0] ) {
          mach->CondMask &= ~0x1;
       }
index 716b16b7f9fad3e85f72a7f01efffd6e4a7136dc..aee2d3081b2434e33860140eea5f6e9c80b69bad 100644 (file)
@@ -112,7 +112,7 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
    { 1, 2, 1, 0, 0, 0, OTHR, "TXL", TGSI_OPCODE_TXL },
    { 0, 0, 0, 0, 0, 0, NONE, "BRK", TGSI_OPCODE_BRK },
    { 0, 1, 0, 1, 0, 1, NONE, "IF", TGSI_OPCODE_IF },
-   { 1, 1, 0, 0, 0, 1, NONE, "", 75 },      /* removed */
+   { 0, 1, 0, 1, 0, 1, NONE, "UIF", TGSI_OPCODE_UIF },
    { 0, 1, 0, 0, 0, 1, NONE, "", 76 },      /* removed */
    { 0, 0, 0, 1, 1, 1, NONE, "ELSE", TGSI_OPCODE_ELSE },
    { 0, 0, 0, 0, 1, 0, NONE, "ENDIF", TGSI_OPCODE_ENDIF },
@@ -297,6 +297,7 @@ tgsi_opcode_infer_src_type( uint opcode )
    case TGSI_OPCODE_TXF:
    case TGSI_OPCODE_SAMPLE_I:
    case TGSI_OPCODE_SAMPLE_I_MS:
+   case TGSI_OPCODE_UIF:
       return TGSI_TYPE_UNSIGNED;
    case TGSI_OPCODE_MOD:
    case TGSI_OPCODE_I2F:
index b8519c64a2bf04fdb377acbb0ea355fa310cc87a..a6bcbb0f3226531b4cca16bd0ede15aa24156517 100644 (file)
@@ -128,6 +128,7 @@ OP12(DP2)
 OP12_TEX(TXL)
 OP00(BRK)
 OP01_LBL(IF)
+OP01_LBL(UIF)
 OP00_LBL(ELSE)
 OP00(ENDIF)
 OP01(PUSHA)
index 0002626c7152a07aa11c39cc7686d23c1fb3f77f..b7180f85df43f927589ae839bee8ba3ba94e6a20 100644 (file)
@@ -864,19 +864,32 @@ This instruction replicates its result.
   TBD
 
 
-.. opcode:: IF - If
+.. opcode:: IF - Float If
 
-  TBD
+  Start an IF ... ELSE .. ENDIF block.  Condition evaluates to true if
+
+    src0.x != 0.0
+
+  where src0.x is interpreted as a floating point register.
+
+
+.. opcode:: UIF - Bitwise If
+
+  Start an UIF ... ELSE .. ENDIF block. Condition evaluates to true if
+
+    src0.x != 0
+
+  where src0.x is interpreted as an integer register.
 
 
 .. opcode:: ELSE - Else
 
-  TBD
+  Starts an else block, after an IF or UIF statement.
 
 
 .. opcode:: ENDIF - End If
 
-  TBD
+  Ends an IF or UIF block.
 
 
 .. opcode:: PUSHA - Push Address Register On Stack
index 68976914240f97466ed4f4978b7828e79c6dd994..d8abccd15afef2ca403f4ae648aa65c30469812c 100644 (file)
@@ -242,6 +242,7 @@ unsigned int Instruction::srcMask(unsigned int s) const
    case TGSI_OPCODE_SCS:
       return 0x1;
    case TGSI_OPCODE_IF:
+   case TGSI_OPCODE_UIF:
       return 0x1;
    case TGSI_OPCODE_LIT:
       return 0xb;
@@ -385,6 +386,7 @@ static nv50_ir::TexTarget translateTexture(uint tex)
 nv50_ir::DataType Instruction::inferSrcType() const
 {
    switch (getOpcode()) {
+   case TGSI_OPCODE_UIF:
    case TGSI_OPCODE_AND:
    case TGSI_OPCODE_OR:
    case TGSI_OPCODE_XOR:
@@ -2430,6 +2432,7 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
       mkOp1(op, TYPE_U32, NULL, src0)->fixed = 1;
       break;
    case TGSI_OPCODE_IF:
+   case TGSI_OPCODE_UIF:
    {
       BasicBlock *ifBB = new BasicBlock(func);
 
@@ -2437,7 +2440,7 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
       condBBs.push(bb);
       joinBBs.push(bb);
 
-      mkFlow(OP_BRA, NULL, CC_NOT_P, fetchSrc(0, 0));
+      mkFlow(OP_BRA, NULL, CC_NOT_P, fetchSrc(0, 0))->setType(srcTy);
 
       setPosition(ifBB, true);
    }
index 20f76f81ded7d559ca4b0ecd306d18817b8fa580..03086e379c026e69728bd9ea244abb0e23bcc10b 100644 (file)
@@ -1011,7 +1011,7 @@ NV50LoweringPreSSA::checkPredicate(Instruction *insn)
       return;
    cdst = bld.getSSA(1, FILE_FLAGS);
 
-   bld.mkCmp(OP_SET, CC_NEU, TYPE_U32, cdst, bld.loadImm(NULL, 0), pred);
+   bld.mkCmp(OP_SET, CC_NEU, insn->dType, cdst, bld.loadImm(NULL, 0), pred);
 
    insn->setPredicate(insn->cc, cdst);
 }
index 4d1d37281bc5be54ea8796ad346a943012c9c3db..7676185f03f15f7b665429215b8cce4298db1b84 100644 (file)
@@ -1490,7 +1490,7 @@ NVC0LoweringPass::checkPredicate(Instruction *insn)
    // CAUTION: don't use pdst->getInsn, the definition might not be unique,
    //  delay turning PSET(FSET(x,y),0) into PSET(x,y) to a later pass
 
-   bld.mkCmp(OP_SET, CC_NEU, TYPE_U32, pdst, bld.mkImm(0), pred);
+   bld.mkCmp(OP_SET, CC_NEU, insn->dType, pdst, bld.mkImm(0), pred);
 
    insn->setPredicate(insn->cc, pdst);
 }
index 7185c8e78f0429f060ad79006d3910908202c823..5ac8c095183f2fede50706054a8357750ba9917f 100644 (file)
@@ -5728,7 +5728,7 @@ static void break_loop_on_flag(struct r600_shader_ctx *ctx, unsigned fc_sp)
 }
 #endif
 
-static int tgsi_if(struct r600_shader_ctx *ctx)
+static int emit_if(struct r600_shader_ctx *ctx, int opcode)
 {
        int alu_type = CF_OP_ALU_PUSH_BEFORE;
 
@@ -5742,7 +5742,7 @@ static int tgsi_if(struct r600_shader_ctx *ctx)
                alu_type = CF_OP_ALU;
        }
 
-       emit_logic_pred(ctx, ALU_OP2_PRED_SETNE_INT, alu_type);
+       emit_logic_pred(ctx, opcode, alu_type);
 
        r600_bytecode_add_cfinst(ctx->bc, CF_OP_JUMP);
 
@@ -5752,6 +5752,16 @@ static int tgsi_if(struct r600_shader_ctx *ctx)
        return 0;
 }
 
+static int tgsi_if(struct r600_shader_ctx *ctx)
+{
+       return emit_if(ctx, ALU_OP2_PRED_SETNE);
+}
+
+static int tgsi_uif(struct r600_shader_ctx *ctx)
+{
+       return emit_if(ctx, ALU_OP2_PRED_SETNE_INT);
+}
+
 static int tgsi_else(struct r600_shader_ctx *ctx)
 {
        r600_bytecode_add_cfinst(ctx->bc, CF_OP_ELSE);
@@ -6003,8 +6013,7 @@ static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
        {TGSI_OPCODE_TXL,       0, FETCH_OP_SAMPLE_L, tgsi_tex},
        {TGSI_OPCODE_BRK,       0, CF_OP_LOOP_BREAK, tgsi_loop_brk_cont},
        {TGSI_OPCODE_IF,        0, ALU_OP0_NOP, tgsi_if},
-       /* gap */
-       {75,                    0, ALU_OP0_NOP, tgsi_unsupported},
+       {TGSI_OPCODE_UIF,       0, ALU_OP0_NOP, tgsi_uif},
        {76,                    0, ALU_OP0_NOP, tgsi_unsupported},
        {TGSI_OPCODE_ELSE,      0, ALU_OP0_NOP, tgsi_else},
        {TGSI_OPCODE_ENDIF,     0, ALU_OP0_NOP, tgsi_endif},
@@ -6197,8 +6206,7 @@ static struct r600_shader_tgsi_instruction eg_shader_tgsi_instruction[] = {
        {TGSI_OPCODE_TXL,       0, FETCH_OP_SAMPLE_L, tgsi_tex},
        {TGSI_OPCODE_BRK,       0, CF_OP_LOOP_BREAK, tgsi_loop_brk_cont},
        {TGSI_OPCODE_IF,        0, ALU_OP0_NOP, tgsi_if},
-       /* gap */
-       {75,                    0, ALU_OP0_NOP, tgsi_unsupported},
+       {TGSI_OPCODE_UIF,       0, ALU_OP0_NOP, tgsi_uif},
        {76,                    0, ALU_OP0_NOP, tgsi_unsupported},
        {TGSI_OPCODE_ELSE,      0, ALU_OP0_NOP, tgsi_else},
        {TGSI_OPCODE_ENDIF,     0, ALU_OP0_NOP, tgsi_endif},
@@ -6391,8 +6399,7 @@ static struct r600_shader_tgsi_instruction cm_shader_tgsi_instruction[] = {
        {TGSI_OPCODE_TXL,       0, FETCH_OP_SAMPLE_L, tgsi_tex},
        {TGSI_OPCODE_BRK,       0, CF_OP_LOOP_BREAK, tgsi_loop_brk_cont},
        {TGSI_OPCODE_IF,        0, ALU_OP0_NOP, tgsi_if},
-       /* gap */
-       {75,                    0, ALU_OP0_NOP, tgsi_unsupported},
+       {TGSI_OPCODE_UIF,       0, ALU_OP0_NOP, tgsi_uif},
        {76,                    0, ALU_OP0_NOP, tgsi_unsupported},
        {TGSI_OPCODE_ELSE,      0, ALU_OP0_NOP, tgsi_else},
        {TGSI_OPCODE_ENDIF,     0, ALU_OP0_NOP, tgsi_endif},
index 314c9634fa759fa35b00fd7e18121a5fe1f92000..0629b89a8e52cfc8cd792a976b564f5d4207b718 100644 (file)
@@ -515,20 +515,16 @@ static void endloop_emit(
        ctx->loop_depth--;
 }
 
-static void if_emit(
+static void if_cond_emit(
        const struct lp_build_tgsi_action * action,
        struct lp_build_tgsi_context * bld_base,
-       struct lp_build_emit_data * emit_data)
+       struct lp_build_emit_data * emit_data,
+       LLVMValueRef cond)
 {
        struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
        struct gallivm_state * gallivm = bld_base->base.gallivm;
-       LLVMValueRef cond;
        LLVMBasicBlockRef if_block, else_block, endif_block;
 
-       cond = LLVMBuildICmp(gallivm->builder, LLVMIntNE,
-               bitcast(bld_base, TGSI_TYPE_UNSIGNED, emit_data->args[0]),
-                       bld_base->int_bld.zero, "");
-
        endif_block = LLVMAppendBasicBlockInContext(gallivm->context,
                                                ctx->main_fn, "ENDIF");
        if_block = LLVMInsertBasicBlockInContext(gallivm->context,
@@ -545,6 +541,36 @@ static void if_emit(
        ctx->branch[ctx->branch_depth - 1].has_else = 0;
 }
 
+static void if_emit(
+       const struct lp_build_tgsi_action * action,
+       struct lp_build_tgsi_context * bld_base,
+       struct lp_build_emit_data * emit_data)
+{
+       struct gallivm_state * gallivm = bld_base->base.gallivm;
+       LLVMValueRef cond;
+
+       cond = LLVMBuildFCmp(gallivm->builder, LLVMRealUNE,
+                       emit_data->args[0],
+                       bld_base->base.zero, "");
+
+       if_cond_emit(action, bld_base, emit_data, cond);
+}
+
+static void uif_emit(
+       const struct lp_build_tgsi_action * action,
+       struct lp_build_tgsi_context * bld_base,
+       struct lp_build_emit_data * emit_data)
+{
+       struct gallivm_state * gallivm = bld_base->base.gallivm;
+       LLVMValueRef cond;
+
+       cond = LLVMBuildICmp(gallivm->builder, LLVMIntNE,
+               bitcast(bld_base, TGSI_TYPE_UNSIGNED, emit_data->args[0]),
+                       bld_base->int_bld.zero, "");
+
+       if_cond_emit(action, bld_base, emit_data, cond);
+}
+
 static void kil_emit(
        const struct lp_build_tgsi_action * action,
        struct lp_build_tgsi_context * bld_base,
@@ -1209,6 +1235,7 @@ void radeon_llvm_context_init(struct radeon_llvm_context * ctx)
        bld_base->op_actions[TGSI_OPCODE_IABS].intr_name = "llvm.AMDIL.abs.";
        bld_base->op_actions[TGSI_OPCODE_IDIV].emit = emit_idiv;
        bld_base->op_actions[TGSI_OPCODE_IF].emit = if_emit;
+       bld_base->op_actions[TGSI_OPCODE_UIF].emit = uif_emit;
        bld_base->op_actions[TGSI_OPCODE_IMAX].emit = build_tgsi_intrinsic_nomem;
        bld_base->op_actions[TGSI_OPCODE_IMAX].intr_name = "llvm.AMDGPU.imax";
        bld_base->op_actions[TGSI_OPCODE_IMIN].emit = build_tgsi_intrinsic_nomem;
index 6fcd151aecc487959a8b0bfecd88d1832d798f34..50de2d370a12f404c7fd66fa22dcb1ad6d9982fc 100644 (file)
@@ -335,7 +335,7 @@ struct tgsi_property_data {
 #define TGSI_OPCODE_TXL                 72
 #define TGSI_OPCODE_BRK                 73
 #define TGSI_OPCODE_IF                  74
-                                /* gap */
+#define TGSI_OPCODE_UIF                 75
 #define TGSI_OPCODE_ELSE                77
 #define TGSI_OPCODE_ENDIF               78
                                 /* gap */
index 589c91287128f9291cbdd774a0b7c19f901ba5fd..f2eb3e7d9124afafedfb3f2d407e0be2eecd363d 100644 (file)
@@ -2978,12 +2978,15 @@ glsl_to_tgsi_visitor::visit(ir_discard *ir)
 void
 glsl_to_tgsi_visitor::visit(ir_if *ir)
 {
+   unsigned if_opcode;
    glsl_to_tgsi_instruction *if_inst;
 
    ir->condition->accept(this);
    assert(this->result.file != PROGRAM_UNDEFINED);
 
-   if_inst = emit(ir->condition, TGSI_OPCODE_IF, undef_dst, this->result);
+   if_opcode = native_integers ? TGSI_OPCODE_UIF : TGSI_OPCODE_IF;
+
+   if_inst = emit(ir->condition, if_opcode, undef_dst, this->result);
 
    this->instructions.push_tail(if_inst);
 
@@ -3462,6 +3465,7 @@ glsl_to_tgsi_visitor::copy_propagate(void)
          break;
 
       case TGSI_OPCODE_IF:
+      case TGSI_OPCODE_UIF:
          ++level;
          break;
 
@@ -3664,6 +3668,7 @@ glsl_to_tgsi_visitor::eliminate_dead_code_advanced(void)
          break;
 
       case TGSI_OPCODE_IF:
+      case TGSI_OPCODE_UIF:
          ++level;
          /* fallthrough to default case to mark the condition as read */
       
@@ -4389,6 +4394,7 @@ compile_tgsi_instruction(struct st_translate *t,
    case TGSI_OPCODE_ELSE:
    case TGSI_OPCODE_ENDLOOP:
    case TGSI_OPCODE_IF:
+   case TGSI_OPCODE_UIF:
       assert(num_dst == 0);
       ureg_label_insn(ureg,
                       inst->op,
index 5471a9a86f2206cf722e640261071ee3f9416704..27d8beae1e9f13a0b2ad92be5fe15d3ddb190f89 100644 (file)
@@ -665,6 +665,7 @@ translate_opcode( unsigned op )
 
 static void
 compile_instruction(
+   struct gl_context *ctx,
    struct st_translate *t,
    const struct prog_instruction *inst,
    boolean clamp_dst_color_output)
@@ -697,7 +698,6 @@ compile_instruction(
    case OPCODE_CAL:
    case OPCODE_ELSE:
    case OPCODE_ENDLOOP:
-   case OPCODE_IF:
       debug_assert(num_dst == 0);
       ureg_label_insn( ureg,
                        translate_opcode( inst->Opcode ),
@@ -705,6 +705,14 @@ compile_instruction(
                        get_label( t, inst->BranchTarget ));
       return;
 
+   case OPCODE_IF:
+      debug_assert(num_dst == 0);
+      ureg_label_insn( ureg,
+                       ctx->Const.NativeIntegers ? TGSI_OPCODE_UIF : TGSI_OPCODE_IF,
+                       src, num_src,
+                       get_label( t, inst->BranchTarget ));
+      return;
+
    case OPCODE_TEX:
    case OPCODE_TXB:
    case OPCODE_TXD:
@@ -1229,7 +1237,7 @@ st_translate_mesa_program(
     */
    for (i = 0; i < program->NumInstructions; i++) {
       set_insn_start( t, ureg_get_instruction_number( ureg ));
-      compile_instruction( t, &program->Instructions[i], clamp_color );
+      compile_instruction( ctx, t, &program->Instructions[i], clamp_color );
    }
 
    /* Fix up all emitted labels: