summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/freedreno/ir3/ir3_compiler.c')
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_compiler.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
index 707bad54796..1bfc347374f 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
@@ -102,6 +102,11 @@ struct ir3_compile_context {
/* for calculating input/output positions/linkages: */
unsigned next_inloc;
+ /* a4xx (at least patchlevel 0) cannot seem to flat-interpolate
+ * so we need to use ldlv.u32 to load the varying directly:
+ */
+ bool flat_bypass;
+
unsigned num_internal_temps;
struct tgsi_src_register internal_temps[8];
@@ -198,9 +203,13 @@ compile_init(struct ir3_compile_context *ctx, struct ir3_shader_variant *so,
} else if (ir3_shader_gpuid(so->shader) >= 400) {
/* a4xx seems to have *no* sam.p */
lconfig.lower_TXP = ~0; /* lower all txp */
+ /* need special handling for "flat" */
+ ctx->flat_bypass = true;
} else {
/* a3xx just needs to avoid sam.p for 3d tex */
lconfig.lower_TXP = (1 << TGSI_TEXTURE_3D);
+ /* no special handling for "flat" */
+ ctx->flat_bypass = false;
}
ctx->tokens = tgsi_transform_lowering(&lconfig, tokens, &ctx->info);
@@ -2778,11 +2787,23 @@ decl_semantic(const struct tgsi_declaration_semantic *sem)
static struct ir3_instruction *
decl_in_frag_bary(struct ir3_compile_context *ctx, unsigned regid,
- unsigned j, unsigned inloc)
+ unsigned j, unsigned inloc, bool use_ldlv)
{
struct ir3_instruction *instr;
struct ir3_register *src;
+ if (use_ldlv) {
+ /* ldlv.u32 dst, l[#inloc], 1 */
+ instr = instr_create(ctx, 6, OPC_LDLV);
+ instr->cat6.type = TYPE_U32;
+ instr->cat6.iim_val = 1;
+ ir3_reg_create(instr, regid, 0); /* dummy dst */
+ ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = inloc;
+ ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 1;
+
+ return instr;
+ }
+
/* bary.f dst, #inloc, r0.x */
instr = instr_create(ctx, 2, OPC_BARY_F);
ir3_reg_create(instr, regid, 0); /* dummy dst */
@@ -2976,9 +2997,31 @@ decl_in(struct ir3_compile_context *ctx, struct tgsi_full_declaration *decl)
so->frag_face = true;
instr = decl_in_frag_face(ctx, r + j, j);
} else {
+ bool use_ldlv = false;
+
+ /* I don't believe it is valid to not have Interp
+ * on a normal frag shader input, and various parts
+ * that that handle flat/smooth shading make this
+ * assumption as well.
+ */
+ compile_assert(ctx, decl->Declaration.Interpolate);
+
+ if (ctx->flat_bypass) {
+ switch (decl->Interp.Interpolate) {
+ case TGSI_INTERPOLATE_COLOR:
+ if (!ctx->so->key.rasterflat)
+ break;
+ /* fallthrough */
+ case TGSI_INTERPOLATE_CONSTANT:
+ use_ldlv = true;
+ break;
+ }
+ }
+
so->inputs[n].bary = true;
+
instr = decl_in_frag_bary(ctx, r + j, j,
- so->inputs[n].inloc + j - 8);
+ so->inputs[n].inloc + j - 8, use_ldlv);
}
} else {
instr = create_input(ctx->block, NULL, (i * 4) + j);