[PATCH 11/21] etnaviv: compiler: add code emitter for alu operations
Philipp Zabel
p.zabel at pengutronix.de
Tue Jun 5 14:38:35 UTC 2018
From: Michael Tretter <m.tretter at pengutronix.de>
Start emitting ALU instructions for nir_alu_instr structures from the
NIR shader's main function implementation.
Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel at pengutronix.de>
---
.../drivers/etnaviv/etnaviv_compiler.c | 290 ++++++++++++++++++
1 file changed, 290 insertions(+)
diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler.c b/src/gallium/drivers/etnaviv/etnaviv_compiler.c
index 59caff435e64..129c9115e783 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_compiler.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_compiler.c
@@ -1937,6 +1937,293 @@ etna_compile_pass_generate_code(struct etna_compile *c)
tgsi_parse_free(&ctx);
}
+static void
+translate_alu_sources(struct etna_compile *c, struct nir_alu_instr *instr,
+ struct etna_inst_src src[3])
+{
+ const nir_op_info *info = &nir_op_infos[instr->op];
+
+ for (unsigned i = 0; i < info->num_inputs; i++) {
+ nir_alu_src nir_src = instr->src[i];
+ if (nir_src.src.is_ssa) {
+ nir_const_value *val = NULL;
+ if (nir_src.src.ssa->parent_instr->type == nir_instr_type_intrinsic) {
+ nir_intrinsic_instr *intr = nir_instr_as_intrinsic(nir_src.src.ssa->parent_instr);
+ // int indirect_offset = intr->src[0];
+ src[i].use = 1;
+ src[i].swiz = INST_SWIZ(nir_src.swizzle[0], nir_src.swizzle[1],
+ nir_src.swizzle[2], nir_src.swizzle[3]);
+ src[i].reg = nir_intrinsic_base(intr);
+ src[i].rgroup = INST_RGROUP_UNIFORM_0;
+ } else {
+ val = nir_src_as_const_value(nir_src.src);
+ src[i] = alloc_imm_vec4u(c, ETNA_IMMEDIATE_CONSTANT, val->u32);
+ src[i].swiz = INST_SWIZ(nir_src.swizzle[0], nir_src.swizzle[1],
+ nir_src.swizzle[2], nir_src.swizzle[3]);
+ }
+ } else {
+ src[i].use = 1;
+ src[i].swiz = INST_SWIZ(nir_src.swizzle[0], nir_src.swizzle[1],
+ nir_src.swizzle[2], nir_src.swizzle[3]);
+ src[i].rgroup = INST_RGROUP_TEMP;
+ src[i].reg = nir_src.src.reg.reg->index;
+ src[i].amode = INST_AMODE_DIRECT;
+ src[i].neg = nir_src.negate;
+ }
+ }
+}
+
+static void
+etna_emit_alu(struct etna_compile *c, nir_alu_instr *instr)
+{
+ const nir_op_info *info = &nir_op_infos[instr->op];
+
+ struct etna_inst_dst dst;
+ struct etna_inst_src src[3] = {};
+
+ nir_alu_dest nir_dest = instr->dest;
+
+ dst.use = 1;
+ dst.reg = nir_dest.dest.reg.reg->index;
+ dst.comps = nir_dest.write_mask;
+
+ translate_alu_sources(c, instr, src);
+
+ switch (instr->op) {
+ case nir_op_fceil:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_CEIL,
+ .dst = dst,
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_ffloor:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_FLOOR,
+ .dst = dst,
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_fmov:
+ case nir_op_imov:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_MOV,
+ .dst = dst,
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_frcp:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_RCP,
+ .dst = dst,
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_frsq:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_RSQ,
+ .dst = dst,
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_fmul:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_MUL,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ });
+ break;
+ case nir_op_fadd:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_ADD,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[2] = src[1],
+ });
+ break;
+ case nir_op_fdot2:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_DP2,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ });
+ break;
+ case nir_op_fdot3:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_DP3,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ });
+ break;
+ case nir_op_ffma:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_MAD,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ .src[2] = src[2],
+ });
+ break;
+ case nir_op_fmin:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_SELECT,
+ .cond = INST_CONDITION_GT,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_fmax:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_SELECT,
+ .cond = INST_CONDITION_LT,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_ffract:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_FRC,
+ .dst = dst,
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_fsqrt:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_SQRT,
+ .dst = dst,
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_fexp2:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_EXP,
+ .dst = dst,
+ .src[2] = src[0],
+ });
+ break;
+ case nir_op_seq:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_SET,
+ .cond = INST_CONDITION_EQ,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ });
+ break;
+ case nir_op_sge:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_SET,
+ .cond = INST_CONDITION_GE,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ });
+ break;
+ case nir_op_slt:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_SET,
+ .cond = INST_CONDITION_LT,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ });
+ break;
+ case nir_op_sne:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_SET,
+ .cond = INST_CONDITION_NE,
+ .dst = dst,
+ .src[0] = src[0],
+ .src[1] = src[1],
+ });
+ break;
+ default:
+ BUG("Unhandled nir_alu_instr: %s\n", info->name);
+ assert(0);
+ break;
+ }
+
+ return;
+}
+
+static void
+etna_emit_intr(struct etna_compile *c, nir_intrinsic_instr *intr)
+{
+ switch (intr->intrinsic) {
+ case nir_intrinsic_nop:
+ emit_inst(c, &(struct etna_inst) {
+ .opcode = INST_OPCODE_NOP,
+ });
+ break;
+ default:
+ /* Nothing to do */
+ break;
+ }
+}
+
+static void
+etna_emit_instr(struct etna_compile *c, nir_instr *instr)
+{
+ switch (instr->type) {
+ case nir_instr_type_alu:
+ etna_emit_alu(c, nir_instr_as_alu(instr));
+ break;
+ case nir_instr_type_intrinsic:
+ etna_emit_intr(c, nir_instr_as_intrinsic(instr));
+ break;
+ case nir_instr_type_load_const:
+ /* Nothing to do */
+ break;
+ default:
+ BUG("Unhandled nir_instr: %d", instr->type);
+ assert(0);
+ break;
+ }
+}
+
+static void
+etna_emit_block(struct etna_compile *c, nir_block *nblock)
+{
+ nir_foreach_instr(instr, nblock) {
+ etna_emit_instr(c, instr);
+ }
+}
+
+static void
+etna_emit_cf_list(struct etna_compile *c, struct exec_list *list)
+{
+ foreach_list_typed(nir_cf_node, node, node, list) {
+ switch (node->type) {
+ case nir_cf_node_block:
+ etna_emit_block(c, nir_cf_node_as_block(node));
+ break;
+ default:
+ BUG("Unhandled nir node type %d\n", node->type);
+ assert(0);
+ break;
+ }
+ }
+}
+
+static void
+etna_emit_function(struct etna_compile *c, nir_function_impl *func_impl)
+{
+ /* Handle only main function */
+ assert(strcmp(func_impl->function->name, "main") == 0);
+
+ etna_emit_cf_list(c, &func_impl->body);
+ etna_emit_block(c, func_impl->end_block);
+
+ return;
+}
+
static void
etna_setup_registers_from_nir(struct etna_compile *c, struct etna_shader_variant *v)
{
@@ -2117,6 +2404,9 @@ etna_compile_shader_nir(struct etna_compile *c, struct etna_shader_variant *v)
etna_setup_uniforms_from_nir(c, v);
etna_setup_inputs_from_nir(c, v);
etna_setup_outputs_from_nir(c, v);
+
+ impl = nir_shader_get_entrypoint(c->s);
+ etna_emit_function(c, impl);
}
/* Look up register by semantic */
--
2.17.1
More information about the etnaviv
mailing list