freedreno/ir3: switch fragcoord to sysval
authorRob Clark <robdclark@chromium.org>
Fri, 26 Apr 2019 21:40:17 +0000 (14:40 -0700)
committerRob Clark <robdclark@chromium.org>
Tue, 30 Apr 2019 00:01:01 +0000 (17:01 -0700)
Because who are we kidding... it is a sysval.

Signed-off-by: Rob Clark <robdclark@chromium.org>
src/freedreno/ir3/ir3_compiler_nir.c
src/gallium/drivers/freedreno/freedreno_screen.c

index 34fb7b0969db3858a60dffb626fe7a18dc88d0d4..4e139dc136e16e6b045e307e8eefd83a313b1b51 100644 (file)
@@ -1176,6 +1176,46 @@ get_barycentric_pixel(struct ir3_context *ctx)
        return ctx->ij_pixel;
 }
 
+static struct ir3_instruction *
+get_frag_coord(struct ir3_context *ctx)
+{
+       if (!ctx->frag_coord) {
+               struct ir3_block *b = ctx->block;
+               struct ir3_instruction *xyzw[4];
+               struct ir3_instruction *hw_frag_coord;
+
+               hw_frag_coord = create_input_compmask(ctx, 0, 0xf);
+               ir3_split_dest(ctx->block, xyzw, hw_frag_coord, 0, 4);
+
+               /* for frag_coord.xy, we get unsigned values.. we need
+                * to subtract (integer) 8 and divide by 16 (right-
+                * shift by 4) then convert to float:
+                *
+                *    sub.s tmp, src, 8
+                *    shr.b tmp, tmp, 4
+                *    mov.u32f32 dst, tmp
+                *
+                */
+               for (int i = 0; i < 2; i++) {
+                       xyzw[i] = ir3_SUB_S(b, xyzw[i], 0,
+                                       create_immed(b, 8), 0);
+                       xyzw[i] = ir3_SHR_B(b, xyzw[i], 0,
+                                       create_immed(b, 4), 0);
+                       xyzw[i] = ir3_COV(b, xyzw[i], TYPE_U32, TYPE_F32);
+               }
+
+               ctx->frag_coord = ir3_create_collect(ctx, xyzw, 4);
+
+               add_sysval_input_compmask(ctx,
+                               SYSTEM_VALUE_FRAG_COORD,
+                               0xf, hw_frag_coord);
+
+               ctx->so->frag_coord = true;
+       }
+
+       return ctx->frag_coord;
+}
+
 static void
 emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
 {
@@ -1217,6 +1257,9 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
        case nir_intrinsic_load_ubo:
                emit_intrinsic_load_ubo(ctx, intr, dst);
                break;
+       case nir_intrinsic_load_frag_coord:
+               ir3_split_dest(b, dst, get_frag_coord(ctx), 0, 4);
+               break;
        case nir_intrinsic_load_sample_pos_from_id: {
                /* NOTE: blob seems to always use TYPE_F16 and then cov.f16f32,
                 * but that doesn't seem necessary.
@@ -2298,46 +2341,6 @@ emit_function(struct ir3_context *ctx, nir_function_impl *impl)
        ir3_END(ctx->block);
 }
 
-static struct ir3_instruction *
-create_frag_coord(struct ir3_context *ctx, unsigned comp)
-{
-       struct ir3_block *block = ctx->block;
-       struct ir3_instruction *instr;
-
-       if (!ctx->frag_coord) {
-               ctx->frag_coord = create_input_compmask(ctx, 0, 0xf);
-               /* defer add_sysval_input() until after all inputs created */
-       }
-
-       ir3_split_dest(block, &instr, ctx->frag_coord, comp, 1);
-
-       switch (comp) {
-       case 0: /* .x */
-       case 1: /* .y */
-               /* for frag_coord, we get unsigned values.. we need
-                * to subtract (integer) 8 and divide by 16 (right-
-                * shift by 4) then convert to float:
-                *
-                *    sub.s tmp, src, 8
-                *    shr.b tmp, tmp, 4
-                *    mov.u32f32 dst, tmp
-                *
-                */
-               instr = ir3_SUB_S(block, instr, 0,
-                               create_immed(block, 8), 0);
-               instr = ir3_SHR_B(block, instr, 0,
-                               create_immed(block, 4), 0);
-               instr = ir3_COV(block, instr, TYPE_U32, TYPE_F32);
-
-               return instr;
-       case 2: /* .z */
-       case 3: /* .w */
-       default:
-               /* seems that we can use these as-is: */
-               return instr;
-       }
-}
-
 static void
 setup_input(struct ir3_context *ctx, nir_variable *in)
 {
@@ -2371,9 +2374,7 @@ setup_input(struct ir3_context *ctx, nir_variable *in)
                        unsigned idx = (n * 4) + i + frac;
 
                        if (slot == VARYING_SLOT_POS) {
-                               so->inputs[n].bary = false;
-                               so->frag_coord = true;
-                               instr = create_frag_coord(ctx, i);
+                               ir3_context_error(ctx, "fragcoord should be a sysval!\n");
                        } else if (slot == VARYING_SLOT_PNTC) {
                                /* see for example st_nir_fixup_varying_slots().. this is
                                 * maybe a bit mesa/st specific.  But we need things to line
@@ -2678,11 +2679,6 @@ emit_instructions(struct ir3_context *ctx)
                                0x3, vcoord);
        }
 
-       if (ctx->frag_coord) {
-               add_sysval_input_compmask(ctx, SYSTEM_VALUE_FRAG_COORD,
-                               0xf, ctx->frag_coord);
-       }
-
        /* Setup outputs: */
        nir_foreach_variable(var, &ctx->s->outputs) {
                setup_output(ctx, var);
index d1edf82592c76f46bf4e195db6e7af0aca4d7547..a437afb0d4e68423c93becddb9799d1788f9be98 100644 (file)
@@ -355,6 +355,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
                return 0;
        case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
        case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
+       case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:
                if (is_ir3(screen))
                        return 1;
                return 0;