mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-01 16:48:07 +02:00
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 <jglisse@redhat.com>
This commit is contained in:
parent
7643f45b10
commit
0db388eedd
4 changed files with 143 additions and 148 deletions
|
|
@ -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_op {
|
||||
unsigned ninput;
|
||||
struct c_operand input[3];
|
||||
struct c_operand output;
|
||||
unsigned opcode;
|
||||
};
|
||||
|
||||
struct c_instruction {
|
||||
struct c_instruction *next, *prev;
|
||||
unsigned opcode;
|
||||
unsigned ninput;
|
||||
struct c_operand input[3];
|
||||
struct c_operand output;
|
||||
unsigned write_mask;
|
||||
void *backend;
|
||||
unsigned nop;
|
||||
struct c_op op[5];
|
||||
};
|
||||
|
||||
struct c_node;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue