NV30/NV40 CMP and SCS src == dst handling
authorLuca Barbieri <luca@luca-barbieri.com>
Sat, 26 Dec 2009 07:12:15 +0000 (08:12 +0100)
committerYounes Manton <younes.m@gmail.com>
Mon, 28 Dec 2009 22:59:00 +0000 (17:59 -0500)
CMP and SCS can produce incorrect results if the source and
destination are the same.
This patch should fix the issues.
CMP is fixed by predicating both moves.
SCS by changing the order if the source component is X.

src/gallium/drivers/nv30/nv30_fragprog.c
src/gallium/drivers/nv40/nv40_fragprog.c

index 40965a97723b5c2cfe2927ab60c4d3c7b3b0d079..dc4e583ce9dea37dca51aea5dbc34aeb6ab6e485 100644 (file)
@@ -435,10 +435,11 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
                arith(fpc, sat, ADD, dst, mask, src[0], src[1], none);
                break;
        case TGSI_OPCODE_CMP:
-               tmp = temp(fpc);
-               arith(fpc, sat, MOV, dst, mask, src[2], none, none);
+               tmp = nv30_sr(NV30SR_NONE, 0);
                tmp.cc_update = 1;
                arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none);
+               dst.cc_test = NV30_VP_INST_COND_GE;
+               arith(fpc, sat, MOV, dst, mask, src[2], none, none);
                dst.cc_test = NV30_VP_INST_COND_LT;
                arith(fpc, sat, MOV, dst, mask, src[1], none, none);
                break;
@@ -517,13 +518,28 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
                arith(fpc, sat, RSQ, dst, mask, abs(swz(src[0], X, X, X, X)), none, none);
                break;
        case TGSI_OPCODE_SCS:
-               if (mask & MASK_X) {
-                       arith(fpc, sat, COS, dst, MASK_X,
-                             swz(src[0], X, X, X, X), none, none);
+               /* avoid overwriting the source */
+               if(src[0].swz[SWZ_X] != SWZ_X)
+               {
+                       if (mask & MASK_X) {
+                               arith(fpc, sat, COS, dst, MASK_X,
+                                     swz(src[0], X, X, X, X), none, none);
+                       }
+                       if (mask & MASK_Y) {
+                               arith(fpc, sat, SIN, dst, MASK_Y,
+                                     swz(src[0], X, X, X, X), none, none);
+                       }
                }
-               if (mask & MASK_Y) {
-                       arith(fpc, sat, SIN, dst, MASK_Y,
-                             swz(src[0], X, X, X, X), none, none);
+               else
+               {
+                       if (mask & MASK_Y) {
+                               arith(fpc, sat, SIN, dst, MASK_Y,
+                                     swz(src[0], X, X, X, X), none, none);
+                       }
+                       if (mask & MASK_X) {
+                               arith(fpc, sat, COS, dst, MASK_X,
+                                     swz(src[0], X, X, X, X), none, none);
+                       }
                }
                break;
        case TGSI_OPCODE_SIN:
index 1bf16726d105e1314a20b84290a94bf58e8d9aab..468d3509a987c77bdcb65bdc7519c3241fa56ff5 100644 (file)
@@ -445,10 +445,11 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc,
                arith(fpc, sat, ADD, dst, mask, src[0], src[1], none);
                break;
        case TGSI_OPCODE_CMP:
-               tmp = temp(fpc);
-               arith(fpc, sat, MOV, dst, mask, src[2], none, none);
+               tmp = nv40_sr(NV40SR_NONE, 0);
                tmp.cc_update = 1;
                arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none);
+               dst.cc_test = NV40_VP_INST_COND_GE;
+               arith(fpc, sat, MOV, dst, mask, src[2], none, none);
                dst.cc_test = NV40_VP_INST_COND_LT;
                arith(fpc, sat, MOV, dst, mask, src[1], none, none);
                break;
@@ -573,13 +574,28 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc,
                      neg(swz(tmp, X, X, X, X)), none, none);
                break;
        case TGSI_OPCODE_SCS:
-               if (mask & MASK_X) {
-                       arith(fpc, sat, COS, dst, MASK_X,
-                             swz(src[0], X, X, X, X), none, none);
+               /* avoid overwriting the source */
+               if(src[0].swz[SWZ_X] != SWZ_X)
+               {
+                       if (mask & MASK_X) {
+                               arith(fpc, sat, COS, dst, MASK_X,
+                                     swz(src[0], X, X, X, X), none, none);
+                       }
+                       if (mask & MASK_Y) {
+                               arith(fpc, sat, SIN, dst, MASK_Y,
+                                     swz(src[0], X, X, X, X), none, none);
+                       }
                }
-               if (mask & MASK_Y) {
-                       arith(fpc, sat, SIN, dst, MASK_Y,
-                             swz(src[0], X, X, X, X), none, none);
+               else
+               {
+                       if (mask & MASK_Y) {
+                               arith(fpc, sat, SIN, dst, MASK_Y,
+                                     swz(src[0], X, X, X, X), none, none);
+                       }
+                       if (mask & MASK_X) {
+                               arith(fpc, sat, COS, dst, MASK_X,
+                                     swz(src[0], X, X, X, X), none, none);
+                       }
                }
                break;
        case TGSI_OPCODE_SEQ: