r600g: add initial bank swizzle support.
this is ported from r600c mostly, bank swizzling is real messy and I don't think I got enough sleep last night to fully understand it.
This commit is contained in:
parent
48e789d71e
commit
bf346f065c
|
@ -28,6 +28,57 @@
|
|||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu)
|
||||
{
|
||||
if(alu->is_op3)
|
||||
return 3;
|
||||
|
||||
switch (alu->inst) {
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP:
|
||||
return 0;
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLNE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETNE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4_IEEE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE:
|
||||
return 2;
|
||||
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_TRUNC:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_IEEE:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN:
|
||||
case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS:
|
||||
return 1;
|
||||
|
||||
default: R600_ERR(
|
||||
"Need instruction operand number for 0x%x.\n", alu->inst);
|
||||
};
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id);
|
||||
|
||||
static struct r600_bc_cf *r600_bc_cf(void)
|
||||
|
@ -50,6 +101,7 @@ static struct r600_bc_alu *r600_bc_alu(void)
|
|||
if (alu == NULL)
|
||||
return NULL;
|
||||
LIST_INITHEAD(&alu->list);
|
||||
LIST_INITHEAD(&alu->bs_list);
|
||||
return alu;
|
||||
}
|
||||
|
||||
|
@ -129,10 +181,219 @@ int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const unsigned bank_swizzle_vec[8] = {SQ_ALU_VEC_210, //000
|
||||
SQ_ALU_VEC_120, //001
|
||||
SQ_ALU_VEC_102, //010
|
||||
|
||||
SQ_ALU_VEC_201, //011
|
||||
SQ_ALU_VEC_012, //100
|
||||
SQ_ALU_VEC_021, //101
|
||||
|
||||
SQ_ALU_VEC_012, //110
|
||||
SQ_ALU_VEC_012}; //111
|
||||
|
||||
const unsigned bank_swizzle_scl[8] = {SQ_ALU_SCL_210, //000
|
||||
SQ_ALU_SCL_122, //001
|
||||
SQ_ALU_SCL_122, //010
|
||||
|
||||
SQ_ALU_SCL_221, //011
|
||||
SQ_ALU_SCL_212, //100
|
||||
SQ_ALU_SCL_122, //101
|
||||
|
||||
SQ_ALU_SCL_122, //110
|
||||
SQ_ALU_SCL_122}; //111
|
||||
|
||||
static int init_gpr(struct r600_bc_alu *alu)
|
||||
{
|
||||
int cycle, component;
|
||||
/* set up gpr use */
|
||||
for (cycle = 0; cycle < NUM_OF_CYCLES; cycle++)
|
||||
for (component = 0; component < NUM_OF_COMPONENTS; component++)
|
||||
alu->hw_gpr[cycle][component] = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int reserve_gpr(struct r600_bc_alu *alu, unsigned sel, unsigned chan, unsigned cycle)
|
||||
{
|
||||
if (alu->hw_gpr[cycle][chan] < 0)
|
||||
alu->hw_gpr[cycle][chan] = sel;
|
||||
else if (alu->hw_gpr[cycle][chan] != (int)sel) {
|
||||
R600_ERR("Another scalar operation has already used GPR read port for channel\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cycle_for_scalar_bank_swizzle(const int swiz, const int sel, unsigned *p_cycle)
|
||||
{
|
||||
int table[3];
|
||||
int ret = 0;
|
||||
switch (swiz) {
|
||||
case SQ_ALU_SCL_210:
|
||||
table[0] = 2; table[1] = 1; table[2] = 0;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
case SQ_ALU_SCL_122:
|
||||
table[0] = 1; table[1] = 2; table[2] = 2;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
case SQ_ALU_SCL_212:
|
||||
table[0] = 2; table[1] = 1; table[2] = 2;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
case SQ_ALU_SCL_221:
|
||||
table[0] = 2; table[1] = 2; table[2] = 1;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
R600_ERR("bad scalar bank swizzle value\n");
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cycle_for_vector_bank_swizzle(const int swiz, const int sel, unsigned *p_cycle)
|
||||
{
|
||||
int table[3];
|
||||
int ret;
|
||||
|
||||
switch (swiz) {
|
||||
case SQ_ALU_VEC_012:
|
||||
table[0] = 0; table[1] = 1; table[2] = 2;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
case SQ_ALU_VEC_021:
|
||||
table[0] = 0; table[1] = 2; table[2] = 1;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
case SQ_ALU_VEC_120:
|
||||
table[0] = 1; table[1] = 2; table[2] = 0;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
case SQ_ALU_VEC_102:
|
||||
table[0] = 1; table[1] = 0; table[2] = 2;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
case SQ_ALU_VEC_201:
|
||||
table[0] = 2; table[1] = 0; table[2] = 1;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
case SQ_ALU_VEC_210:
|
||||
table[0] = 2; table[1] = 1; table[2] = 0;
|
||||
*p_cycle = table[sel];
|
||||
break;
|
||||
default:
|
||||
R600_ERR("bad vector bank swizzle value\n");
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int is_const(int sel)
|
||||
{
|
||||
if (sel > 255 && sel < 512)
|
||||
return 1;
|
||||
if (sel >= V_SQ_ALU_SRC_0 && sel <= V_SQ_ALU_SRC_LITERAL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_chan_counter(struct r600_bc_alu *alu, int *chan_counter)
|
||||
{
|
||||
int num_src;
|
||||
int i;
|
||||
int channel_swizzle;
|
||||
|
||||
num_src = r600_bc_get_num_operands(alu);
|
||||
|
||||
for (i = 0; i < num_src; i++) {
|
||||
channel_swizzle = alu->src[i].chan;
|
||||
if ((alu->src[i].sel > 0 && alu->src[i].sel < 128) && channel_swizzle <= 3)
|
||||
chan_counter[channel_swizzle]++;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* we need something like this I think - but this is bogus */
|
||||
int check_read_slots(struct r600_bc *bc, struct r600_bc_alu *alu_first)
|
||||
{
|
||||
struct r600_bc_alu *alu;
|
||||
int chan_counter[4] = { 0 };
|
||||
|
||||
update_chan_counter(alu_first, chan_counter);
|
||||
|
||||
LIST_FOR_EACH_ENTRY(alu, &alu_first->bs_list, bs_list) {
|
||||
update_chan_counter(alu, chan_counter);
|
||||
}
|
||||
|
||||
if (chan_counter[0] > 3 ||
|
||||
chan_counter[1] > 3 ||
|
||||
chan_counter[2] > 3 ||
|
||||
chan_counter[3] > 3) {
|
||||
R600_ERR("needed to split instruction for input ran out of banks %x %d %d %d %d\n",
|
||||
alu_first->inst, chan_counter[0], chan_counter[1], chan_counter[2], chan_counter[3]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int check_scalar(struct r600_bc *bc, struct r600_bc_alu *alu)
|
||||
{
|
||||
unsigned swizzle_key;
|
||||
|
||||
swizzle_key = (is_const(alu->src[0].sel) ? 4 : 0 ) +
|
||||
(is_const(alu->src[1].sel) ? 2 : 0 ) +
|
||||
(is_const(alu->src[2].sel) ? 1 : 0 );
|
||||
|
||||
alu->bank_swizzle = bank_swizzle_scl[swizzle_key];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_vector(struct r600_bc *bc, struct r600_bc_alu *alu)
|
||||
{
|
||||
unsigned swizzle_key;
|
||||
|
||||
swizzle_key = (is_const(alu->src[0].sel) ? 4 : 0 ) +
|
||||
(is_const(alu->src[1].sel) ? 2 : 0 ) +
|
||||
(is_const(alu->src[2].sel) ? 1 : 0 );
|
||||
|
||||
alu->bank_swizzle = bank_swizzle_vec[swizzle_key];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_and_set_bank_swizzle(struct r600_bc *bc, struct r600_bc_alu *alu_first)
|
||||
{
|
||||
struct r600_bc_alu *alu;
|
||||
int num_instr = 1;
|
||||
|
||||
init_gpr(alu_first);
|
||||
|
||||
LIST_FOR_EACH_ENTRY(alu, &alu_first->bs_list, bs_list) {
|
||||
num_instr++;
|
||||
}
|
||||
|
||||
if (num_instr == 1) {
|
||||
check_scalar(bc, alu_first);
|
||||
|
||||
} else {
|
||||
/* check_read_slots(bc, bc->cf_last->curr_bs_head);*/
|
||||
check_vector(bc, alu_first);
|
||||
LIST_FOR_EACH_ENTRY(alu, &alu_first->bs_list, bs_list) {
|
||||
check_vector(bc, alu);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int type)
|
||||
{
|
||||
struct r600_bc_alu *nalu = r600_bc_alu();
|
||||
struct r600_bc_alu *lalu;
|
||||
struct r600_bc_alu *curr_bs_head;
|
||||
int i, r;
|
||||
|
||||
if (nalu == NULL)
|
||||
|
@ -151,6 +412,12 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int
|
|||
}
|
||||
bc->cf_last->inst = (type << 3);
|
||||
}
|
||||
if (!bc->cf_last->curr_bs_head) {
|
||||
bc->cf_last->curr_bs_head = nalu;
|
||||
LIST_INITHEAD(&nalu->bs_list);
|
||||
} else {
|
||||
LIST_ADDTAIL(&nalu->bs_list, &bc->cf_last->curr_bs_head->bs_list);
|
||||
}
|
||||
if (alu->last && (bc->cf_last->ndw >> 1) >= 124) {
|
||||
bc->force_add_cf = 1;
|
||||
}
|
||||
|
@ -185,6 +452,11 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int
|
|||
if (bc->use_mem_constant)
|
||||
bc->cf_last->kcache0_mode = 2;
|
||||
|
||||
/* process cur ALU instructions for bank swizzle */
|
||||
if (alu->last) {
|
||||
check_and_set_bank_swizzle(bc, bc->cf_last->curr_bs_head);
|
||||
bc->cf_last->curr_bs_head = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -365,7 +637,7 @@ static int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsign
|
|||
S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
|
||||
S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
|
||||
S_SQ_ALU_WORD1_OP3_ALU_INST(alu->inst) |
|
||||
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
|
||||
S_SQ_ALU_WORD1_BANK_SWIZZLE(alu->bank_swizzle);
|
||||
} else {
|
||||
bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
|
||||
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
|
||||
|
@ -375,7 +647,7 @@ static int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsign
|
|||
S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
|
||||
S_SQ_ALU_WORD1_OP2_WRITE_MASK(alu->dst.write) |
|
||||
S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) |
|
||||
S_SQ_ALU_WORD1_BANK_SWIZZLE(0) |
|
||||
S_SQ_ALU_WORD1_BANK_SWIZZLE(alu->bank_swizzle) |
|
||||
S_SQ_ALU_WORD1_OP2_UPDATE_EXECUTE_MASK(alu->predicate) |
|
||||
S_SQ_ALU_WORD1_OP2_UPDATE_PRED(alu->predicate);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#include "radeon.h"
|
||||
#include "util/u_double_list.h"
|
||||
|
||||
#define NUM_OF_CYCLES 3
|
||||
#define NUM_OF_COMPONENTS 4
|
||||
|
||||
struct r600_bc_alu_src {
|
||||
unsigned sel;
|
||||
unsigned chan;
|
||||
|
@ -44,6 +47,7 @@ struct r600_bc_alu_dst {
|
|||
|
||||
struct r600_bc_alu {
|
||||
struct list_head list;
|
||||
struct list_head bs_list; /* bank swizzle list */
|
||||
struct r600_bc_alu_src src[3];
|
||||
struct r600_bc_alu_dst dst;
|
||||
unsigned inst;
|
||||
|
@ -52,7 +56,9 @@ struct r600_bc_alu {
|
|||
unsigned predicate;
|
||||
unsigned nliteral;
|
||||
unsigned literal_added;
|
||||
unsigned bank_swizzle;
|
||||
u32 value[4];
|
||||
int hw_gpr[NUM_OF_CYCLES][NUM_OF_COMPONENTS];
|
||||
};
|
||||
|
||||
struct r600_bc_tex {
|
||||
|
@ -125,6 +131,7 @@ struct r600_bc_cf {
|
|||
struct list_head tex;
|
||||
struct list_head vtx;
|
||||
struct r600_bc_output output;
|
||||
struct r600_bc_alu *curr_bs_head;
|
||||
};
|
||||
|
||||
#define FC_NONE 0
|
||||
|
|
|
@ -455,4 +455,16 @@
|
|||
|
||||
#define V_SQ_REL_ABSOLUTE 0
|
||||
#define V_SQ_REL_RELATIVE 1
|
||||
|
||||
#define SQ_ALU_VEC_012 0x00
|
||||
#define SQ_ALU_VEC_021 0x01
|
||||
#define SQ_ALU_VEC_120 0x02
|
||||
#define SQ_ALU_VEC_102 0x03
|
||||
#define SQ_ALU_VEC_201 0x04
|
||||
#define SQ_ALU_VEC_210 0x05
|
||||
|
||||
#define SQ_ALU_SCL_210 0x00000000
|
||||
#define SQ_ALU_SCL_122 0x00000001
|
||||
#define SQ_ALU_SCL_212 0x00000002
|
||||
#define SQ_ALU_SCL_221 0x00000003
|
||||
#endif
|
||||
|
|
|
@ -51,7 +51,7 @@ int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id)
|
|||
S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
|
||||
S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
|
||||
S_SQ_ALU_WORD1_OP3_ALU_INST(alu->inst) |
|
||||
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
|
||||
S_SQ_ALU_WORD1_BANK_SWIZZLE(alu->bank_swizzle);
|
||||
} else {
|
||||
bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
|
||||
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
|
||||
|
@ -61,7 +61,7 @@ int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id)
|
|||
S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
|
||||
S_SQ_ALU_WORD1_OP2_WRITE_MASK(alu->dst.write) |
|
||||
S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) |
|
||||
S_SQ_ALU_WORD1_BANK_SWIZZLE(0) |
|
||||
S_SQ_ALU_WORD1_BANK_SWIZZLE(alu->bank_swizzle) |
|
||||
S_SQ_ALU_WORD1_OP2_UPDATE_EXECUTE_MASK(alu->predicate) |
|
||||
S_SQ_ALU_WORD1_OP2_UPDATE_PRED(alu->predicate);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue