etnaviv: nir: use store_deref instead of store_output

Allows some simplification.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
This commit is contained in:
Jonathan Marek 2019-09-12 12:28:28 -04:00
parent d92689c46f
commit 8f1b2ea7a9
2 changed files with 59 additions and 70 deletions

View File

@ -49,9 +49,6 @@ struct etna_compile {
const struct etna_specs *specs;
struct etna_shader_variant *variant;
/* register assigned to each output, indexed by driver_location */
unsigned output_reg[ETNA_NUM_INPUTS];
/* block # to instr index */
unsigned *block_ptr;
@ -75,18 +72,6 @@ struct etna_compile {
static void
etna_lower_io(nir_shader *shader, struct etna_shader_variant *v)
{
bool rb_swap = shader->info.stage == MESA_SHADER_FRAGMENT && v->key.frag_rb_swap;
unsigned color_location = 0;
nir_foreach_variable(var, &shader->outputs) {
switch (var->data.location) {
case FRAG_RESULT_COLOR:
case FRAG_RESULT_DATA0:
color_location = var->data.driver_location;
break;
}
}
nir_foreach_function(function, shader) {
nir_builder b;
nir_builder_init(&b, function->impl);
@ -113,16 +98,24 @@ etna_lower_io(nir_shader *shader, struct etna_shader_variant *v)
nir_src_for_ssa(ssa),
ssa->parent_instr);
} break;
case nir_intrinsic_store_output: {
if (!rb_swap || nir_intrinsic_base(intr) != color_location)
case nir_intrinsic_store_deref: {
if (shader->info.stage != MESA_SHADER_FRAGMENT || !v->key.frag_rb_swap)
break;
nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
assert(deref->deref_type == nir_deref_type_var);
if (deref->var->data.location != FRAG_RESULT_COLOR &&
deref->var->data.location != FRAG_RESULT_DATA0)
break;
b.cursor = nir_before_instr(instr);
nir_ssa_def *ssa = nir_mov(&b, intr->src[0].ssa);
nir_ssa_def *ssa = nir_mov(&b, intr->src[1].ssa);
nir_alu_instr *alu = nir_instr_as_alu(ssa->parent_instr);
alu->src[0].swizzle[0] = 2;
alu->src[0].swizzle[2] = 0;
nir_instr_rewrite_src(instr, &intr->src[0], nir_src_for_ssa(ssa));
nir_instr_rewrite_src(instr, &intr->src[1], nir_src_for_ssa(ssa));
} break;
case nir_intrinsic_load_uniform: {
/* multiply by 16 and convert to int */
@ -558,9 +551,39 @@ etna_emit_discard(struct etna_compile *c, struct etna_inst_src condition)
}
static void
etna_emit_output(struct etna_compile *c, unsigned index, struct etna_inst_src src)
etna_emit_output(struct etna_compile *c, nir_variable *var, struct etna_inst_src src)
{
c->output_reg[index] = src.reg;
struct etna_shader_io_file *sf = &c->variant->outfile;
if (is_fs(c)) {
switch (var->data.location) {
case FRAG_RESULT_COLOR:
case FRAG_RESULT_DATA0: /* DATA0 is used by gallium shaders for color */
c->variant->ps_color_out_reg = src.reg;
break;
case FRAG_RESULT_DEPTH:
c->variant->ps_depth_out_reg = src.reg;
break;
default:
unreachable("Unsupported fs output");
}
return;
}
switch (var->data.location) {
case VARYING_SLOT_POS:
c->variant->vs_pos_out_reg = src.reg;
break;
case VARYING_SLOT_PSIZ:
c->variant->vs_pointsize_out_reg = src.reg;
break;
default:
sf->reg[sf->num_reg].reg = src.reg;
sf->reg[sf->num_reg].slot = var->data.location;
sf->reg[sf->num_reg].num_components = glsl_get_components(var->type);
sf->num_reg++;
break;
}
}
static void
@ -715,7 +738,7 @@ etna_compile_shader_nir(struct etna_shader_variant *v)
assert(sf->num_reg == count);
}
NIR_PASS_V(s, nir_lower_io, nir_var_all, etna_glsl_type_size,
NIR_PASS_V(s, nir_lower_io, ~nir_var_shader_out, etna_glsl_type_size,
(nir_lower_io_options)0);
OPT_V(s, nir_lower_regs_to_ssa);
@ -809,23 +832,7 @@ etna_compile_shader_nir(struct etna_shader_variant *v)
if (s->info.stage == MESA_SHADER_FRAGMENT) {
v->input_count_unk8 = 31; /* XXX what is this */
nir_foreach_variable(var, &s->outputs) {
unsigned reg = c->output_reg[var->data.driver_location];
switch (var->data.location) {
case FRAG_RESULT_COLOR:
case FRAG_RESULT_DATA0: /* DATA0 is used by gallium shaders for color */
v->ps_color_out_reg = reg;
break;
case FRAG_RESULT_DEPTH:
v->ps_depth_out_reg = reg;
break;
default:
compile_error(c, "Unsupported fs output %s\n", gl_frag_result_name(var->data.location));
}
}
assert(v->ps_depth_out_reg <= 0);
v->outfile.num_reg = 0;
ralloc_free(c->nir);
FREE(c);
return true;
@ -833,27 +840,6 @@ etna_compile_shader_nir(struct etna_shader_variant *v)
v->input_count_unk8 = DIV_ROUND_UP(v->infile.num_reg + 4, 16); /* XXX what is this */
sf = &v->outfile;
sf->num_reg = 0;
nir_foreach_variable(var, &s->outputs) {
unsigned native = c->output_reg[var->data.driver_location];
if (var->data.location == VARYING_SLOT_POS) {
v->vs_pos_out_reg = native;
continue;
}
if (var->data.location == VARYING_SLOT_PSIZ) {
v->vs_pointsize_out_reg = native;
continue;
}
sf->reg[sf->num_reg].reg = native;
sf->reg[sf->num_reg].slot = var->data.location;
sf->reg[sf->num_reg].num_components = glsl_get_components(var->type);
sf->num_reg++;
}
/* fill in "mystery meat" load balancing value. This value determines how
* work is scheduled between VS and PS
* in the unified shader architecture. More precisely, it is determined from

View File

@ -580,7 +580,7 @@ dest_for_instr(nir_instr *instr)
dest = &nir_instr_as_alu(instr)->dest.dest;
break;
case nir_instr_type_tex:
dest =&nir_instr_as_tex(instr)->dest;
dest = &nir_instr_as_tex(instr)->dest;
break;
case nir_instr_type_intrinsic: {
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
@ -588,7 +588,9 @@ dest_for_instr(nir_instr *instr)
intr->intrinsic == nir_intrinsic_load_input ||
intr->intrinsic == nir_intrinsic_load_instance_id)
dest = &intr->dest;
}
} break;
case nir_instr_type_deref:
return NULL;
default:
break;
}
@ -649,7 +651,7 @@ set_src_live(nir_src *src, void *void_state)
if (src->is_ssa) {
nir_instr *instr = src->ssa->parent_instr;
if (is_sysval(instr))
if (is_sysval(instr) || instr->type == nir_instr_type_deref)
return true;
switch (instr->type) {
@ -784,7 +786,7 @@ live_defs(nir_function_impl *impl, struct live_def *defs, unsigned *live_map)
/* output live till the end */
if (instr->type == nir_instr_type_intrinsic) {
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic == nir_intrinsic_store_output)
if (intr->intrinsic == nir_intrinsic_store_deref)
state.index = ~0u;
}
@ -928,11 +930,11 @@ ra_assign(struct state *state, nir_shader *shader)
unsigned reg;
switch (intr->intrinsic) {
case nir_intrinsic_store_output: {
case nir_intrinsic_store_deref: {
/* don't want output to be swizzled
* TODO: better would be to set the type to X/XY/XYZ/XYZW
*/
ra_set_node_class(g, live_map[src_index(impl, &intr->src[0])], REG_CLASS_VEC4);
ra_set_node_class(g, live_map[src_index(impl, &intr->src[1])], REG_CLASS_VEC4);
} continue;
case nir_intrinsic_load_input:
reg = nir_intrinsic_base(intr) * NUM_REG_TYPES + (unsigned[]) {
@ -1075,12 +1077,12 @@ static void
emit_intrinsic(struct state *state, nir_intrinsic_instr * intr)
{
switch (intr->intrinsic) {
case nir_intrinsic_store_output:
emit(output, nir_intrinsic_base(intr), get_src(state, &intr->src[0]));
case nir_intrinsic_store_deref:
emit(output, nir_src_as_deref(intr->src[0])->var, get_src(state, &intr->src[1]));
break;
case nir_intrinsic_discard_if:
emit(discard, get_src(state, &intr->src[0]));
break;
break;
case nir_intrinsic_discard:
emit(discard, SRC_DISABLE);
break;
@ -1119,6 +1121,7 @@ emit_instr(struct state *state, nir_instr * instr)
assert(nir_instr_is_last(instr));
case nir_instr_type_load_const:
case nir_instr_type_ssa_undef:
case nir_instr_type_deref:
break;
default:
assert(0);
@ -1440,8 +1443,8 @@ emit_shader(nir_shader *shader, const struct emit_options *options,
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
switch (intr->intrinsic) {
case nir_intrinsic_store_output: {
nir_src *src = &intr->src[0];
case nir_intrinsic_store_deref: {
nir_src *src = &intr->src[1];
if (nir_src_is_const(*src) || is_sysval(src->ssa->parent_instr)) {
b.cursor = nir_before_instr(instr);
nir_instr_rewrite_src(instr, src, nir_src_for_ssa(nir_mov(&b, src->ssa)));