From: Jerome Glisse Date: Sat, 5 Jun 2010 11:16:50 +0000 (+0200) Subject: r600g: split instruction into scalar X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0db388eedd5a537e783faaa1ba1a1d101d20e647;p=mesa.git r600g: split instruction into scalar Split instruction into scalar in core compiler this simplify the way we translate the instruction in latter stage. Signed-off-by: Jerome Glisse --- diff --git a/src/gallium/drivers/r600/r600_compiler.h b/src/gallium/drivers/r600/r600_compiler.h index 64dab5000be..3de19970c31 100644 --- a/src/gallium/drivers/r600/r600_compiler.h +++ b/src/gallium/drivers/r600/r600_compiler.h @@ -71,7 +71,7 @@ struct c_vector { #define C_SWIZZLE_W 3 #define C_SWIZZLE_0 4 #define C_SWIZZLE_1 5 -#define C_SWIZZLE_D 6 /**< discard */ +#define C_SWIZZLE_D 6 #define C_FILE_NULL 0 #define C_FILE_CONSTANT 1 @@ -247,18 +247,21 @@ struct c_vector { struct c_operand { struct c_vector *vector; - unsigned swizzle[4]; - unsigned flag[4]; + unsigned swizzle; + unsigned flag; }; -struct c_instruction { - struct c_instruction *next, *prev; - unsigned opcode; +struct c_op { unsigned ninput; struct c_operand input[3]; struct c_operand output; - unsigned write_mask; - void *backend; + unsigned opcode; +}; + +struct c_instruction { + struct c_instruction *next, *prev; + unsigned nop; + struct c_op op[5]; }; struct c_node; diff --git a/src/gallium/drivers/r600/r600_compiler_dump.c b/src/gallium/drivers/r600/r600_compiler_dump.c index 9df6a38598e..485032088c8 100644 --- a/src/gallium/drivers/r600/r600_compiler_dump.c +++ b/src/gallium/drivers/r600/r600_compiler_dump.c @@ -229,28 +229,25 @@ static void pindent(unsigned indent) static void c_node_dump(struct c_node *node, unsigned indent) { struct c_instruction *i; - unsigned j; + unsigned j, k; pindent(indent); fprintf(stderr, "# node %s\n", c_get_name(c_opcode_str, node->opcode)); c_list_for_each(i, &node->insts) { - pindent(indent); fprintf(stderr, "%s", c_get_name(c_opcode_str, i->opcode)); - fprintf(stderr, " %s[%d][%s%s%s%s]", - c_get_name(c_file_str, i->output.vector->file), - i->output.vector->id, - c_get_name(c_file_swz, i->output.swizzle[0]), - c_get_name(c_file_swz, i->output.swizzle[1]), - c_get_name(c_file_swz, i->output.swizzle[2]), - c_get_name(c_file_swz, i->output.swizzle[3])); - for (j = 0; j < i->ninput; j++) { - fprintf(stderr, " %s[%d][%s%s%s%s]", - c_get_name(c_file_str, i->input[j].vector->file), - i->input[j].vector->id, - c_get_name(c_file_swz, i->input[j].swizzle[0]), - c_get_name(c_file_swz, i->input[j].swizzle[1]), - c_get_name(c_file_swz, i->input[j].swizzle[2]), - c_get_name(c_file_swz, i->input[j].swizzle[3])); + for (k = 0; k < i->nop; k++) { + pindent(indent); + fprintf(stderr, "%s", c_get_name(c_opcode_str, i->op[k].opcode)); + fprintf(stderr, " %s[%d][%s]", + c_get_name(c_file_str, i->op[k].output.vector->file), + i->op[k].output.vector->id, + c_get_name(c_file_swz, i->op[k].output.swizzle)); + for (j = 0; j < i->op[k].ninput; j++) { + fprintf(stderr, " %s[%d][%s]", + c_get_name(c_file_str, i->op[k].input[j].vector->file), + i->op[k].input[j].vector->id, + c_get_name(c_file_swz, i->op[k].input[j].swizzle)); + } + fprintf(stderr, ";\n"); } - fprintf(stderr, ";\n"); } } diff --git a/src/gallium/drivers/r600/r600_compiler_r600.c b/src/gallium/drivers/r600/r600_compiler_r600.c index 1be5bf2b4a0..623ac043777 100644 --- a/src/gallium/drivers/r600/r600_compiler_r600.c +++ b/src/gallium/drivers/r600/r600_compiler_r600.c @@ -60,16 +60,31 @@ int r600_shader_insert_fetch(struct c_shader *shader) if (vr == NULL) return -ENOMEM; memset(&instruction, 0, sizeof(struct c_instruction)); - instruction.opcode = C_OPCODE_VFETCH; - instruction.write_mask = 0xF; - instruction.ninput = 2; - instruction.output.vector = v; - instruction.input[0].vector = vi; - instruction.input[1].vector = vr; - instruction.output.swizzle[0] = C_SWIZZLE_X; - instruction.output.swizzle[1] = C_SWIZZLE_Y; - instruction.output.swizzle[2] = C_SWIZZLE_Z; - instruction.output.swizzle[3] = C_SWIZZLE_W; + instruction.nop = 4; + instruction.op[0].opcode = C_OPCODE_VFETCH; + instruction.op[1].opcode = C_OPCODE_VFETCH; + instruction.op[2].opcode = C_OPCODE_VFETCH; + instruction.op[3].opcode = C_OPCODE_VFETCH; + instruction.op[0].ninput = 2; + instruction.op[1].ninput = 2; + instruction.op[2].ninput = 2; + instruction.op[3].ninput = 2; + instruction.op[0].output.vector = v; + instruction.op[1].output.vector = v; + instruction.op[2].output.vector = v; + instruction.op[3].output.vector = v; + instruction.op[0].input[0].vector = vi; + instruction.op[0].input[1].vector = vr; + instruction.op[1].input[0].vector = vi; + instruction.op[1].input[1].vector = vr; + instruction.op[2].input[0].vector = vi; + instruction.op[2].input[1].vector = vr; + instruction.op[3].input[0].vector = vi; + instruction.op[3].input[1].vector = vr; + instruction.op[0].output.swizzle = C_SWIZZLE_X; + instruction.op[1].output.swizzle = C_SWIZZLE_Y; + instruction.op[2].output.swizzle = C_SWIZZLE_Z; + instruction.op[3].output.swizzle = C_SWIZZLE_W; r = c_node_add_new_instruction_head(&shader->entry, &instruction); if (r) return r; @@ -316,7 +331,7 @@ static int r600_shader_add_vfetch(struct r600_shader *rshader, if (instruction == NULL) return 0; - if (instruction->opcode != C_OPCODE_VFETCH) + if (instruction->op[0].opcode != C_OPCODE_VFETCH) return 0; if (!c_list_empty(&node->alu)) { rnode = r600_shader_new_node(rshader, node->node); @@ -327,13 +342,13 @@ static int r600_shader_add_vfetch(struct r600_shader *rshader, vfetch = calloc(1, sizeof(struct r600_shader_vfetch)); if (vfetch == NULL) return -ENOMEM; - r = r600_shader_find_gpr(rshader, instruction->output.vector, 0, &vfetch->dst[0]); + r = r600_shader_find_gpr(rshader, instruction->op[0].output.vector, 0, &vfetch->dst[0]); if (r) return r; - r = r600_shader_find_gpr(rshader, instruction->input[0].vector, 0, &vfetch->src[0]); + r = r600_shader_find_gpr(rshader, instruction->op[0].input[0].vector, 0, &vfetch->src[0]); if (r) return r; - r = r600_shader_find_gpr(rshader, instruction->input[1].vector, 0, &vfetch->src[1]); + r = r600_shader_find_gpr(rshader, instruction->op[0].input[1].vector, 0, &vfetch->src[1]); if (r) return r; vfetch->dst[0].chan = C_SWIZZLE_X; @@ -355,7 +370,7 @@ static int r600_node_translate(struct r600_shader *rshader, struct c_node *node) if (rnode == NULL) return -ENOMEM; c_list_for_each(instruction, &node->insts) { - switch (instruction->opcode) { + switch (instruction->op[0].opcode) { case C_OPCODE_VFETCH: r = r600_shader_add_vfetch(rshader, rnode, instruction); if (r) { @@ -414,79 +429,13 @@ static struct r600_shader_alu *r600_shader_insert_alu(struct r600_shader *rshade return alu; } -static int r600_shader_node_add_alu(struct r600_shader *rshader, - struct r600_shader_node *node, - struct r600_shader_alu *alu, - unsigned instruction, - unsigned ninput, - struct r600_shader_operand *dst, - struct r600_shader_operand src[3]) -{ - struct r600_shader_alu *nalu; - unsigned nconstant = 0, nliteral = 0, slot, i; - - /* count number of constant & literal */ - for (i = 0; i < ninput; i++) { - if (src[i].vector->file == C_FILE_IMMEDIATE) { - nliteral++; - nconstant++; - } - } - - slot = dst->chan; - if (r600_instruction_info[instruction].is_trans) { - slot = 4; - } - - /* allocate new alu group if necessary */ - nalu = alu; - if (alu == NULL) { - nalu = r600_shader_insert_alu(rshader, node); - if (nalu == NULL) - return -ENOMEM; - alu = nalu; - } - if ((alu->alu[slot].inst != INST_NOP && - alu->alu[4].inst != INST_NOP) || - (alu->nconstant + nconstant) > 4 || - (alu->nliteral + nliteral) > 4) { - /* neither trans neither dst slot are free need new alu */ - nalu = r600_shader_insert_alu(rshader, node); - if (nalu == NULL) - return -ENOMEM; - alu = nalu; - } - if (alu->alu[slot].inst != INST_NOP) { - slot = 4; - } - - alu->alu[slot].dst = *dst; - alu->alu[slot].inst = instruction; - alu->alu[slot].opcode = r600_instruction_info[instruction].opcode; - alu->alu[slot].is_op3 = r600_instruction_info[instruction].is_op3; - for (i = 0; i < ninput; i++) { - alu->alu[slot].src[i] = src[i]; - if (src[i].vector->file == C_FILE_IMMEDIATE) { - alu->literal[alu->nliteral++] = src[i].vector->channel[0]->value; - alu->literal[alu->nliteral++] = src[i].vector->channel[1]->value; - alu->literal[alu->nliteral++] = src[i].vector->channel[2]->value; - alu->literal[alu->nliteral++] = src[i].vector->channel[3]->value; - } - } - return 0; -} - static int r600_shader_alu_translate(struct r600_shader *rshader, struct r600_shader_node *node, struct c_instruction *instruction) { - struct r600_alu_instruction *ainfo = &r600_alu_instruction[instruction->opcode]; - struct r600_instruction_info *info; - struct r600_shader_alu *alu; struct r600_shader_node *rnode; - int r, i, j; - struct r600_shader_operand dst; - struct r600_shader_operand src[3]; + struct r600_shader_alu *alu; + int i, j, r, comp; if (!c_list_empty(&node->vfetch)) { rnode = r600_shader_new_node(rshader, node->node); @@ -496,40 +445,57 @@ static int r600_shader_alu_translate(struct r600_shader *rshader, } node = rnode; } + + /* initialize alu */ alu = r600_shader_insert_alu(rshader, node); - if (alu == NULL) { - fprintf(stderr, "%s %d instert alu node failed\n", __func__, __LINE__); - return -ENOMEM; - } - for (i = 0; i < 4; i++) { - if (!(instruction->write_mask) || instruction->output.swizzle[i] == C_SWIZZLE_D) - continue; - if (ainfo->instruction == INST_NOP) { - fprintf(stderr, "%s:%d unsupported instruction %d\n", __FILE__, __LINE__, instruction->opcode); - continue; - } - info = &r600_instruction_info[ainfo->instruction]; - r = r600_shader_find_gpr(rshader, instruction->output.vector, - instruction->output.swizzle[i], &dst); - if (r) { - fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__); - return r; + + /* check special operation like lit */ + + /* go through operation */ + for (i = 0; i < instruction->nop; i++) { + struct r600_alu_instruction *ainfo = &r600_alu_instruction[instruction->op[i].opcode]; + struct r600_instruction_info *iinfo = &r600_instruction_info[ainfo->instruction]; + unsigned comp; + + /* check that output is a valid component */ + comp = instruction->op[i].output.swizzle; + switch (comp) { + case C_SWIZZLE_X: + case C_SWIZZLE_Y: + case C_SWIZZLE_Z: + case C_SWIZZLE_W: + break; + case C_SWIZZLE_0: + case C_SWIZZLE_1: + default: + fprintf(stderr, "%s %d invalid output\n", __func__, __LINE__); + return -EINVAL; } - for (j = 0; j < instruction->ninput; j++) { - r = r600_shader_find_gpr(rshader, instruction->input[j].vector, - instruction->input[j].swizzle[i], &src[j]); + alu->alu[comp].inst = ainfo->instruction; + alu->alu[comp].opcode = iinfo->opcode; + alu->alu[comp].is_op3 = iinfo->is_op3; + for (j = 0; j < instruction->op[i].ninput; j++) { + r = r600_shader_find_gpr(rshader, instruction->op[i].input[j].vector, + instruction->op[i].input[j].swizzle, &alu->alu[comp].src[j]); if (r) { fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__); return r; } } - r = r600_shader_node_add_alu(rshader, node, alu, ainfo->instruction, - instruction->ninput, &dst, src); + r = r600_shader_find_gpr(rshader, instruction->op[i].output.vector, + instruction->op[i].output.swizzle, &alu->alu[comp].dst); if (r) { - fprintf(stderr, "%s %d failed\n", __FILE__, __LINE__); + fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__); return r; } } + for (i = instruction->nop; i >= 0; i--) { + if (alu->alu[i].inst != INST_NOP) { + alu->alu[i].last = 1; + alu->nalu = i + 1; + break; + } + } return 0; } @@ -576,12 +542,14 @@ int r600_shader_legalize(struct r600_shader *rshader) struct r600_shader_node *node, *nnode; struct r600_shader_alu *alu, *nalu; +#if 0 c_list_for_each_safe(node, nnode, &rshader->nodes) { c_list_for_each_safe(alu, nalu, &node->alu) { alu->nalu = 5; alu->alu[4].last = 1; } } +#endif return 0; } diff --git a/src/gallium/drivers/r600/r600_compiler_tgsi.c b/src/gallium/drivers/r600/r600_compiler_tgsi.c index 563ca063afe..172cf154a34 100644 --- a/src/gallium/drivers/r600/r600_compiler_tgsi.c +++ b/src/gallium/drivers/r600/r600_compiler_tgsi.c @@ -146,7 +146,7 @@ static int ntransform_instruction(struct tgsi_shader *ts) struct c_shader *shader = ts->shader; struct c_instruction instruction; unsigned opcode; - int i, r; + int i, j, r; if (fi->Instruction.NumDstRegs > 1) { fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__); @@ -192,21 +192,48 @@ static int ntransform_instruction(struct tgsi_shader *ts) } /* FIXME add flow instruction handling */ memset(&instruction, 0, sizeof(struct c_instruction)); - instruction.opcode = opcode; - instruction.ninput = fi->Instruction.NumSrcRegs; - instruction.write_mask = fi->Dst[0].Register.WriteMask; - for (i = 0; i < fi->Instruction.NumSrcRegs; i++) { - instruction.input[i].vector = ts->v[fi->Src[i].Register.File][fi->Src[i].Register.Index]; - instruction.input[i].swizzle[0] = fi->Src[i].Register.SwizzleX; - instruction.input[i].swizzle[1] = fi->Src[i].Register.SwizzleY; - instruction.input[i].swizzle[2] = fi->Src[i].Register.SwizzleZ; - instruction.input[i].swizzle[3] = fi->Src[i].Register.SwizzleW; + instruction.nop = 0; + for (j = 0; j < 4; j++) { + instruction.op[instruction.nop].opcode = opcode; + instruction.op[instruction.nop].ninput = fi->Instruction.NumSrcRegs; + for (i = 0; i < fi->Instruction.NumSrcRegs; i++) { + instruction.op[instruction.nop].input[i].vector = ts->v[fi->Src[i].Register.File][fi->Src[i].Register.Index]; + switch (j) { + case 0: + instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleX; + break; + case 1: + instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleY; + break; + case 2: + instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleZ; + break; + case 3: + instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleW; + break; + default: + return -EINVAL; + } + } + instruction.op[instruction.nop].output.vector = ts->v[fi->Dst[0].Register.File][fi->Dst[0].Register.Index]; + switch (j) { + case 0: + instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_X : C_SWIZZLE_D; + break; + case 1: + instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_Y : C_SWIZZLE_D; + break; + case 2: + instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_Z : C_SWIZZLE_D; + break; + case 3: + instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_W : C_SWIZZLE_D; + break; + default: + return -EINVAL; + } + instruction.nop++; } - instruction.output.vector = ts->v[fi->Dst[0].Register.File][fi->Dst[0].Register.Index]; - instruction.output.swizzle[0] = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_X : C_SWIZZLE_D; - instruction.output.swizzle[1] = (fi->Dst[0].Register.WriteMask & 0x2) ? C_SWIZZLE_Y : C_SWIZZLE_D; - instruction.output.swizzle[2] = (fi->Dst[0].Register.WriteMask & 0x4) ? C_SWIZZLE_Z : C_SWIZZLE_D; - instruction.output.swizzle[3] = (fi->Dst[0].Register.WriteMask & 0x8) ? C_SWIZZLE_W : C_SWIZZLE_D; return c_node_add_new_instruction(ts->node, &instruction); }