st/nine: Implement predicated instructions
authorAxel Davy <davyaxel0@gmail.com>
Mon, 10 Sep 2018 19:39:28 +0000 (21:39 +0200)
committerAxel Davy <davyaxel0@gmail.com>
Tue, 25 Sep 2018 20:05:24 +0000 (22:05 +0200)
Most of the work was already there, just not implemented.

Fixes: https://github.com/iXit/Mesa-3D/issues/318
Signed-off-by: Axel Davy <davyaxel0@gmail.com>
src/gallium/state_trackers/nine/nine_shader.c

index 913508fb889ca637e7e0a83f1eda236165228503..9e90da59597ac6154b90f885980e6a95ee687b5b 100644 (file)
@@ -481,6 +481,9 @@ struct shader_translator
         struct ureg_dst p;
         struct ureg_dst address;
         struct ureg_dst a0;
+        struct ureg_dst predicate;
+        struct ureg_dst predicate_tmp;
+        struct ureg_dst predicate_dst;
         struct ureg_dst tS[8]; /* texture stage registers */
         struct ureg_dst tdst; /* scratch dst if we need extra modifiers */
         struct ureg_dst t[5]; /* scratch TEMPs */
@@ -496,6 +499,7 @@ struct shader_translator
     unsigned loop_labels[NINE_MAX_LOOP_DEPTH];
     unsigned cond_labels[NINE_MAX_COND_DEPTH];
     boolean loop_or_rep[NINE_MAX_LOOP_DEPTH]; /* true: loop, false: rep */
+    boolean predicated_activated;
 
     unsigned *inst_labels; /* LABEL op */
     unsigned num_inst_labels;
@@ -975,7 +979,12 @@ tx_src_param(struct shader_translator *tx, const struct sm1_src_param *param)
         }
         break;
     case D3DSPR_PREDICATE:
-        assert(!"D3DSPR_PREDICATE");
+        if (ureg_dst_is_undef(tx->regs.predicate)) {
+            /* Forbidden to use the predicate register before being set */
+            tx->failure = TRUE;
+            tx->regs.predicate = ureg_DECL_temporary(tx->ureg);
+        }
+        src = ureg_src(tx->regs.predicate);
         break;
     case D3DSPR_SAMPLER:
         assert(param->mod == NINED3DSPSM_NONE);
@@ -1157,11 +1166,15 @@ tx_src_param(struct shader_translator *tx, const struct sm1_src_param *param)
         src = ureg_src(tmp);
         break;
     case NINED3DSPSM_NOT:
-        if (tx->native_integers) {
+        if (tx->native_integers && param->file == D3DSPR_CONSTBOOL) {
             tmp = tx_scratch(tx);
             ureg_NOT(ureg, tmp, src);
             src = ureg_src(tmp);
             break;
+        } else { /* predicate */
+            tmp = tx_scratch(tx);
+            ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(src));
+            src = ureg_src(tmp);
         }
         /* fall through */
     case NINED3DSPSM_COMP:
@@ -1292,7 +1305,9 @@ _tx_dst_param(struct shader_translator *tx, const struct sm1_dst_param *param)
         dst = tx->regs.oDepth; /* XXX: must write .z component */
         break;
     case D3DSPR_PREDICATE:
-        assert(!"D3DSPR_PREDICATE");
+        if (ureg_dst_is_undef(tx->regs.predicate))
+            tx->regs.predicate = ureg_DECL_temporary(tx->ureg);
+        dst = tx->regs.predicate;
         break;
     case D3DSPR_TEMPFLOAT16:
         DBG("unhandled D3DSPR: %u\n", param->file);
@@ -1309,6 +1324,11 @@ _tx_dst_param(struct shader_translator *tx, const struct sm1_dst_param *param)
     if (param->mod & NINED3DSPDM_SATURATE)
         dst = ureg_saturate(dst);
 
+    if (tx->predicated_activated) {
+        tx->regs.predicate_dst = dst;
+        dst = tx->regs.predicate_tmp;
+    }
+
     return dst;
 }
 
@@ -2891,12 +2911,24 @@ DECL_SPECIAL(TEXLDL)
 
 DECL_SPECIAL(SETP)
 {
-    STUB(D3DERR_INVALIDCALL);
+    const unsigned cmp_op = sm1_insn_flags_to_tgsi_setop(tx->insn.flags);
+    struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+    struct ureg_src src[2] = {
+       tx_src_param(tx, &tx->insn.src[0]),
+       tx_src_param(tx, &tx->insn.src[1])
+    };
+    ureg_insn(tx->ureg, cmp_op, &dst, 1, src, 2, 0);
+    return D3D_OK;
 }
 
 DECL_SPECIAL(BREAKP)
 {
-    STUB(D3DERR_INVALIDCALL);
+    struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]);
+    ureg_IF(tx->ureg, src, tx_cond(tx));
+    ureg_BRK(tx->ureg);
+    tx_endcond(tx);
+    ureg_ENDIF(tx->ureg);
+    return D3D_OK;
 }
 
 DECL_SPECIAL(PHASE)
@@ -3323,8 +3355,6 @@ sm1_parse_instruction(struct shader_translator *tx)
     insn->ndst = info->ndst;
     insn->nsrc = info->nsrc;
 
-    assert(!insn->predicated && "TODO: predicated instructions");
-
     /* check version */
     {
         unsigned min = IS_VS ? info->vert_version.min : info->frag_version.min;
@@ -3353,12 +3383,30 @@ sm1_parse_instruction(struct shader_translator *tx)
     sm1_dump_instruction(insn, tx->cond_depth + tx->loop_depth);
     sm1_instruction_check(insn);
 
+    if (insn->predicated) {
+        tx->predicated_activated = true;
+        if (ureg_dst_is_undef(tx->regs.predicate_tmp)) {
+            tx->regs.predicate_tmp = ureg_DECL_temporary(tx->ureg);
+            tx->regs.predicate_dst = ureg_DECL_temporary(tx->ureg);
+        }
+    }
+
     if (info->handler)
         hr = info->handler(tx);
     else
         hr = NineTranslateInstruction_Generic(tx);
     tx_apply_dst0_modifiers(tx);
 
+    if (insn->predicated) {
+        tx->predicated_activated = false;
+        /* TODO: predicate might be allowed on outputs,
+         * which cannot be src. Workaround it. */
+        ureg_CMP(tx->ureg, tx->regs.predicate_dst,
+                 ureg_negate(tx_src_param(tx, &insn->pred)),
+                 ureg_src(tx->regs.predicate_tmp),
+                 ureg_src(tx->regs.predicate_dst));
+    }
+
     if (hr != D3D_OK)
         tx->failure = TRUE;
     tx->num_scratch = 0; /* reset */