From da327afb2a4a9b8e1c047ff12aebbd75d71b1b64 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 26 Apr 2019 14:40:17 -0700 Subject: [PATCH] freedreno/ir3: switch fragcoord to sysval Because who are we kidding... it is a sysval. Signed-off-by: Rob Clark --- src/freedreno/ir3/ir3_compiler_nir.c | 92 +++++++++---------- .../drivers/freedreno/freedreno_screen.c | 1 + 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 34fb7b0969d..4e139dc136e 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -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); diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index d1edf82592c..a437afb0d4e 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -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; -- 2.30.2