vc4: Add support for gl_FragCoord.
authorEric Anholt <eric@anholt.net>
Tue, 5 Aug 2014 21:24:29 +0000 (14:24 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 11 Aug 2014 21:47:54 +0000 (14:47 -0700)
This isn't passing all tests (glsl-fs-fragcoord-zw-ortho, for example),
but it does get a bunch more tests passing.

v2: Rebase on helpers change.

src/gallium/drivers/vc4/vc4_program.c
src/gallium/drivers/vc4/vc4_qir.c
src/gallium/drivers/vc4/vc4_qir.h
src/gallium/drivers/vc4/vc4_qpu_emit.c
src/gallium/drivers/vc4/vc4_screen.c

index 8109f635e3b3968a3e008ec904badb2efaa3d994..d871dcd88d3759d2e01eaa571a8a4ffa49e5bd26 100644 (file)
@@ -569,6 +569,20 @@ emit_vertex_input(struct tgsi_to_qir *trans, int attr)
         }
 }
 
+static void
+emit_fragcoord_input(struct tgsi_to_qir *trans, int attr)
+{
+        struct qcompile *c = trans->c;
+
+        trans->inputs[attr * 4 + 0] = qir_FRAG_X(c);
+        trans->inputs[attr * 4 + 1] = qir_FRAG_Y(c);
+        trans->inputs[attr * 4 + 2] =
+                qir_FMUL(c,
+                         qir_FRAG_Z(c),
+                         qir_uniform_f(trans, 1.0 / 0xffffff));
+        trans->inputs[attr * 4 + 3] = qir_FRAG_RCP_W(c);
+}
+
 static void
 emit_fragment_input(struct tgsi_to_qir *trans, int attr)
 {
@@ -599,7 +613,12 @@ emit_tgsi_declaration(struct tgsi_to_qir *trans,
                      i <= decl->Range.Last;
                      i++) {
                         if (c->stage == QSTAGE_FRAG) {
-                                emit_fragment_input(trans, i);
+                                if (decl->Semantic.Name ==
+                                    TGSI_SEMANTIC_POSITION) {
+                                        emit_fragcoord_input(trans, i);
+                                } else {
+                                        emit_fragment_input(trans, i);
+                                }
                         } else {
                                 emit_vertex_input(trans, i);
                         }
index 9462da586608521d8a8056906c78bb24a796871e..6509a2bb621e0424414e2d3d25d9fb1402a1847c 100644 (file)
@@ -65,6 +65,11 @@ static const struct qir_op_info qir_op_info[] = {
         [QOP_TLB_COLOR_WRITE] = { "tlb_color", 0, 1, true },
         [QOP_VARY_ADD_C] = { "vary_add_c", 1, 1 },
 
+        [QOP_FRAG_X] = { "frag_x", 1, 0 },
+        [QOP_FRAG_Y] = { "frag_y", 1, 0 },
+        [QOP_FRAG_Z] = { "frag_z", 1, 0 },
+        [QOP_FRAG_RCP_W] = { "frag_rcp_w", 1, 0 },
+
         [QOP_TEX_S] = { "tex_s", 0, 2 },
         [QOP_TEX_T] = { "tex_t", 0, 2 },
         [QOP_TEX_R] = { "tex_r", 0, 2 },
index 5d1f088ee374a94bbe6ed3007a03096d70a42ff2..7d9806268fe9131c6bacdb7e9849dd875eb4d073 100644 (file)
@@ -74,6 +74,11 @@ enum qop {
         QOP_TLB_COLOR_WRITE,
         QOP_VARY_ADD_C,
 
+        QOP_FRAG_X,
+        QOP_FRAG_Y,
+        QOP_FRAG_Z,
+        QOP_FRAG_RCP_W,
+
         /** Texture x coordinate parameter write */
         QOP_TEX_S,
         /** Texture y coordinate parameter write */
@@ -204,6 +209,15 @@ bool qir_opt_algebraic(struct qcompile *c);
 bool qir_opt_copy_propagation(struct qcompile *c);
 bool qir_opt_dead_code(struct qcompile *c);
 
+#define QIR_ALU0(name)                                                   \
+static inline struct qreg                                                \
+qir_##name(struct qcompile *c)                                           \
+{                                                                        \
+        struct qreg t = qir_get_temp(c);                                 \
+        qir_emit(c, qir_inst(QOP_##name, t, c->undef, c->undef));        \
+        return t;                                                        \
+}
+
 #define QIR_ALU1(name)                                                   \
 static inline struct qreg                                                \
 qir_##name(struct qcompile *c, struct qreg a)                            \
@@ -257,6 +271,10 @@ QIR_NODST_2(TEX_S)
 QIR_NODST_2(TEX_T)
 QIR_NODST_2(TEX_R)
 QIR_NODST_2(TEX_B)
+QIR_ALU0(FRAG_X)
+QIR_ALU0(FRAG_Y)
+QIR_ALU0(FRAG_Z)
+QIR_ALU0(FRAG_RCP_W)
 
 static inline struct qreg
 qir_CMP(struct qcompile *c, struct qreg cmp, struct qreg a, struct qreg b)
index 33abf6dcde40f47ac6926b1ce1ea221b79372d27..63f37dd8fa0f210b4c45cda61af7f249dadf1d97 100644 (file)
@@ -213,7 +213,8 @@ vc4_generate_code(struct qcompile *c)
                         if (qinst->src[i].file == QFILE_TEMP)
                                 reg_uses_remaining[qinst->src[i].index]++;
                 }
-                if (qinst->op == QOP_TLB_PASSTHROUGH_Z_WRITE)
+                if (qinst->op == QOP_TLB_PASSTHROUGH_Z_WRITE ||
+                    qinst->op == QOP_FRAG_Z)
                         reg_in_use[3 + 32 + QPU_R_FRAG_PAYLOAD_ZW] = true;
         }
 
@@ -460,6 +461,33 @@ vc4_generate_code(struct qcompile *c)
 
                         break;
 
+                case QOP_FRAG_X:
+                        queue(c, qpu_inst(qpu_a_ITOF(dst,
+                                                     qpu_ra(QPU_R_XY_PIXEL_COORD)),
+                                          qpu_m_NOP()));
+                        break;
+
+                case QOP_FRAG_Y:
+                        queue(c, qpu_inst(qpu_a_ITOF(dst,
+                                                     qpu_rb(QPU_R_XY_PIXEL_COORD)),
+                                          qpu_m_NOP()));
+                        break;
+
+                case QOP_FRAG_Z:
+                        queue(c, qpu_inst(qpu_a_ITOF(dst,
+                                                     qpu_rb(QPU_R_FRAG_PAYLOAD_ZW)),
+                                          qpu_m_NOP()));
+                        break;
+
+                case QOP_FRAG_RCP_W:
+                        queue(c, qpu_inst(qpu_a_MOV(qpu_rb(QPU_W_SFU_RECIP),
+                                                    qpu_ra(QPU_R_FRAG_PAYLOAD_ZW)),
+                                          qpu_m_NOP()));
+
+                        queue(c, qpu_inst(qpu_a_MOV(dst, qpu_r4()),
+                                          qpu_m_NOP()));
+                        break;
+
                 case QOP_TLB_PASSTHROUGH_Z_WRITE:
                         queue(c, qpu_inst(qpu_a_MOV(qpu_ra(QPU_W_TLB_Z),
                                                     qpu_rb(QPU_R_FRAG_PAYLOAD_ZW)),
index 940596e47bd8dc7831862965ba827ae8512914a3..4ddc9acba93b03366092115892142a500749aa9d 100644 (file)
@@ -102,6 +102,10 @@ vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
         case PIPE_CAP_MAX_VIEWPORTS:
                 return 1;
 
+        case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
+        case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
+                return 1;
+
                 /* Unsupported features. */
         case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
         case PIPE_CAP_ANISOTROPIC_FILTER:
@@ -111,8 +115,6 @@ vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
         case PIPE_CAP_TEXTURE_SWIZZLE:
         case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
         case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
-        case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
-        case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
         case PIPE_CAP_SEAMLESS_CUBE_MAP:
         case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
         case PIPE_CAP_TGSI_INSTANCEID: