diff options
Diffstat (limited to 'src/gallium/drivers/freedreno/ir3')
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c | 185 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3_ra.c | 41 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3_shader.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3_shader.h | 4 |
4 files changed, 79 insertions, 166 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c index 44ee5b2c4a4..e4979a60a02 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c @@ -71,7 +71,7 @@ struct ir3_context { struct ir3_instruction *frag_vcoord; /* for fragment shaders, for gl_FrontFacing and gl_FragCoord: */ - struct ir3_instruction *frag_face, *frag_coord[4]; + struct ir3_instruction *frag_face, *frag_coord; /* For vertex shaders, keep track of the system values sources */ struct ir3_instruction *vertex_id, *basevertex, *instance_id; @@ -781,43 +781,6 @@ create_frag_input(struct ir3_context *ctx, bool use_ldlv) } static struct ir3_instruction * -create_frag_coord(struct ir3_context *ctx, unsigned comp) -{ - struct ir3_block *block = ctx->block; - struct ir3_instruction *instr; - - compile_assert(ctx, !ctx->frag_coord[comp]); - - ctx->frag_coord[comp] = create_input(ctx, 0); - - 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, ctx->frag_coord[comp], 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 ctx->frag_coord[comp]; - } -} - -static struct ir3_instruction * create_driver_param(struct ir3_context *ctx, enum ir3_driver_param dp) { /* first four vec4 sysval's reserved for UBOs: */ @@ -2448,6 +2411,7 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr) if (!ctx->frag_face) { ctx->so->frag_face = true; ctx->frag_face = create_input(ctx, 0); + add_sysval_input(ctx, SYSTEM_VALUE_FRONT_FACE, ctx->frag_face); ctx->frag_face->regs[0]->flags |= IR3_REG_HALF; } /* for fragface, we get -1 for back and 0 for front. However this is @@ -3229,6 +3193,46 @@ 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 */ + } + + 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) { @@ -3406,7 +3410,7 @@ max_drvloc(struct exec_list *vars) } static const unsigned max_sysvals[SHADER_MAX] = { - [SHADER_FRAGMENT] = 8, + [SHADER_FRAGMENT] = 24, // TODO [SHADER_VERTEX] = 16, [SHADER_COMPUTE] = 16, // TODO how many do we actually need? }; @@ -3433,17 +3437,17 @@ emit_instructions(struct ir3_context *ctx) ninputs -= max_sysvals[ctx->so->type]; - /* for fragment shader, we have a single input register (usually - * r0.xy) which is used as the base for bary.f varying fetch instrs: + /* for fragment shader, the vcoord input register is used as the + * base for bary.f varying fetch instrs: */ + struct ir3_instruction *vcoord = NULL; if (ctx->so->type == SHADER_FRAGMENT) { - // TODO maybe a helper for fi since we need it a few places.. - struct ir3_instruction *instr; - instr = ir3_instr_create(ctx->block, OPC_META_FI); - ir3_reg_create(instr, 0, 0); - ir3_reg_create(instr, 0, IR3_REG_SSA); /* r0.x */ - ir3_reg_create(instr, 0, IR3_REG_SSA); /* r0.y */ - ctx->frag_vcoord = instr; + struct ir3_instruction *xy[2]; + + vcoord = create_input_compmask(ctx, 0, 0x3); + split_dest(ctx->block, xy, vcoord, 0, 2); + + ctx->frag_vcoord = create_collect(ctx, xy, 2); } /* Setup inputs: */ @@ -3451,6 +3455,19 @@ emit_instructions(struct ir3_context *ctx) setup_input(ctx, var); } + /* Defer add_sysval_input() stuff until after setup_inputs(), + * because sysvals need to be appended after varyings: + */ + if (vcoord) { + add_sysval_input_compmask(ctx, SYSTEM_VALUE_VARYING_COORD, + 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); @@ -3470,76 +3487,26 @@ emit_instructions(struct ir3_context *ctx) emit_function(ctx, fxn); } -/* from NIR perspective, we actually have inputs. But most of the "inputs" - * for a fragment shader are just bary.f instructions. The *actual* inputs - * from the hw perspective are the frag_vcoord and optionally frag_coord and - * frag_face. +/* from NIR perspective, we actually have varying inputs. But the varying + * inputs, from an IR standpoint, are just bary.f/ldlv instructions. The + * only actual inputs are the sysvals. */ static void fixup_frag_inputs(struct ir3_context *ctx) { struct ir3_shader_variant *so = ctx->so; struct ir3 *ir = ctx->ir; - struct ir3_instruction **inputs; - struct ir3_instruction *instr; - int n, regid = 0; - - ir->ninputs = 0; - - n = 4; /* always have frag_vcoord */ - n += COND(so->frag_face, 4); - n += COND(so->frag_coord, 4); + unsigned i = 0; - inputs = ir3_alloc(ctx->ir, n * (sizeof(struct ir3_instruction *))); + /* sysvals should appear at the end of the inputs, drop everything else: */ + while ((i < so->inputs_count) && !so->inputs[i].sysval) + i++; - if (so->frag_face) { - /* this ultimately gets assigned to hr0.x so doesn't conflict - * with frag_coord/frag_vcoord.. - */ - inputs[ir->ninputs++] = ctx->frag_face; - ctx->frag_face->regs[0]->num = 0; + /* at IR level, inputs are always blocks of 4 scalars: */ + i *= 4; - /* remaining channels not used, but let's avoid confusing - * other parts that expect inputs to come in groups of vec4 - */ - inputs[ir->ninputs++] = NULL; - inputs[ir->ninputs++] = NULL; - inputs[ir->ninputs++] = NULL; - } - - /* since we don't know where to set the regid for frag_coord, - * we have to use r0.x for it. But we don't want to *always* - * use r1.x for frag_vcoord as that could increase the register - * footprint on simple shaders: - */ - if (so->frag_coord) { - ctx->frag_coord[0]->regs[0]->num = regid++; - ctx->frag_coord[1]->regs[0]->num = regid++; - ctx->frag_coord[2]->regs[0]->num = regid++; - ctx->frag_coord[3]->regs[0]->num = regid++; - - inputs[ir->ninputs++] = ctx->frag_coord[0]; - inputs[ir->ninputs++] = ctx->frag_coord[1]; - inputs[ir->ninputs++] = ctx->frag_coord[2]; - inputs[ir->ninputs++] = ctx->frag_coord[3]; - } - - /* we always have frag_vcoord: */ - so->pos_regid = regid; - - /* r0.x */ - instr = create_input(ctx, ir->ninputs); - instr->regs[0]->num = regid++; - inputs[ir->ninputs++] = instr; - ctx->frag_vcoord->regs[1]->instr = instr; - - /* r0.y */ - instr = create_input(ctx, ir->ninputs); - instr->regs[0]->num = regid++; - inputs[ir->ninputs++] = instr; - ctx->frag_vcoord->regs[2]->instr = instr; - - ir->inputs = inputs; + ir->inputs = &ir->inputs[i]; + ir->ninputs -= i; } /* Fixup tex sampler state for astc/srgb workaround instructions. We diff --git a/src/gallium/drivers/freedreno/ir3/ir3_ra.c b/src/gallium/drivers/freedreno/ir3/ir3_ra.c index 74d85eaf8e2..83bc375aeb5 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_ra.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_ra.c @@ -1047,49 +1047,10 @@ ra_block_alloc(struct ir3_ra_ctx *ctx, struct ir3_block *block) static int ra_alloc(struct ir3_ra_ctx *ctx) { - unsigned n = 0; - - /* frag shader inputs get pre-assigned, since we have some - * constraints/unknowns about setup for some of these regs: - */ - if (ctx->type == SHADER_FRAGMENT) { - struct ir3 *ir = ctx->ir; - unsigned i = 0, j; - if (ctx->frag_face && (i < ir->ninputs) && ir->inputs[i]) { - struct ir3_instruction *instr = ir->inputs[i]; - int cls = size_to_class(1, true, false); - unsigned name = __ra_name(ctx, cls, instr); - unsigned reg = ctx->set->gpr_to_ra_reg[cls][0]; - - /* if we have frag_face, it gets hr0.x */ - ra_set_node_reg(ctx->g, name, reg); - i += 4; - } - - j = 0; - for (; i < ir->ninputs; i++) { - struct ir3_instruction *instr = ir->inputs[i]; - if (instr) { - struct ir3_ra_instr_data *id = &ctx->instrd[instr->ip]; - - if (id->defn == instr) { - unsigned name, reg; - - name = ra_name(ctx, id); - reg = ctx->set->gpr_to_ra_reg[id->cls][j]; - - ra_set_node_reg(ctx->g, name, reg); - j += id->sz; - } - } - } - n = j; - } - /* pre-assign array elements: */ list_for_each_entry (struct ir3_array, arr, &ctx->ir->array_list, node) { - unsigned base = n; + unsigned base = 0; if (arr->end_ip == 0) continue; diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.c b/src/gallium/drivers/freedreno/ir3/ir3_shader.c index b0663d5c5ca..7bb4263b177 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.c @@ -97,18 +97,6 @@ fixup_regfootprint(struct ir3_shader_variant *v) int32_t regid = (v->outputs[i].regid + 3) >> 2; v->info.max_reg = MAX2(v->info.max_reg, regid); } - - if (v->type == SHADER_FRAGMENT) { - /* NOTE: not sure how to turn pos_regid off.. but this could - * be, for example, r1.x while max reg used by the shader is - * r0.*, in which case we need to fixup the reg footprint: - */ - v->info.max_reg = MAX2(v->info.max_reg, v->pos_regid >> 2); - if (v->frag_coord) - debug_assert(v->info.max_reg >= 0); /* hard coded r0.x */ - if (v->frag_face) - debug_assert(v->info.max_half_reg >= 0); /* hr0.x */ - } } /* wrapper for ir3_assemble() which does some info fixup based on @@ -518,7 +506,8 @@ ir3_shader_disasm(struct ir3_shader_variant *so, uint32_t *bin, FILE *out) dump_output(out, so, VARYING_SLOT_PSIZ, "psize"); break; case SHADER_FRAGMENT: - dump_reg(out, "pos (bary)", so->pos_regid); + dump_reg(out, "pos (bary)", + ir3_find_sysval_regid(so, SYSTEM_VALUE_VARYING_COORD)); dump_output(out, so, FRAG_RESULT_DEPTH, "posz"); if (so->color0_mrt) { dump_output(out, so, FRAG_RESULT_COLOR, "color"); diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.h b/src/gallium/drivers/freedreno/ir3/ir3_shader.h index 93182c710c2..507e89c4735 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.h +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.h @@ -251,10 +251,6 @@ struct ir3_shader_variant { * + From the vert shader, we only need the output regid */ - /* for frag shader, pos_regid holds the frag_vcoord, ie. what is passed - * to bary.f instructions - */ - uint8_t pos_regid; bool frag_coord, frag_face, color0_mrt; /* NOTE: for input/outputs, slot is: |