diff options
author | Dave Airlie <[email protected]> | 2015-11-30 10:01:41 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2015-12-07 09:58:59 +1000 |
commit | 2b25d9ac7f364259058bf8098ebd40c7c484bcd7 (patch) | |
tree | 19258f49149392da31acd484c7445bc9da4bce28 | |
parent | 4f83184eff9358a72f5d48dd16771c553f914ed0 (diff) |
r600: add support for GDS clause to the assembler.
This just adds enough for the tessellation shaders,
which require TF_WRITE to work.
Signed-off-by: Dave Airlie <[email protected]>
-rw-r--r-- | src/gallium/drivers/r600/eg_asm.c | 23 | ||||
-rw-r--r-- | src/gallium/drivers/r600/eg_sq.h | 21 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_asm.c | 82 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_asm.h | 23 |
4 files changed, 148 insertions, 1 deletions
diff --git a/src/gallium/drivers/r600/eg_asm.c b/src/gallium/drivers/r600/eg_asm.c index c32d317a1a5..f55564973bf 100644 --- a/src/gallium/drivers/r600/eg_asm.c +++ b/src/gallium/drivers/r600/eg_asm.c @@ -193,3 +193,26 @@ int egcm_load_index_reg(struct r600_bytecode *bc, unsigned id, bool inside_alu_c return 0; } + +int eg_bytecode_gds_build(struct r600_bytecode *bc, struct r600_bytecode_gds *gds, unsigned id) +{ + unsigned opcode = r600_isa_fetch_opcode(bc->isa->hw_class, gds->op) >> 8; + bc->bytecode[id++] = S_SQ_MEM_GDS_WORD0_MEM_INST(2) | + S_SQ_MEM_GDS_WORD0_MEM_OP(opcode) | + S_SQ_MEM_GDS_WORD0_SRC_GPR(gds->src_gpr) | + S_SQ_MEM_GDS_WORD0_SRC_REL(gds->src_rel) | + S_SQ_MEM_GDS_WORD0_SRC_SEL_X(gds->src_sel_x) | + S_SQ_MEM_GDS_WORD0_SRC_SEL_Y(gds->src_sel_y) | + S_SQ_MEM_GDS_WORD0_SRC_SEL_Z(gds->src_sel_z); + + bc->bytecode[id++] = S_SQ_MEM_GDS_WORD1_DST_GPR(gds->dst_gpr) | + S_SQ_MEM_GDS_WORD1_DST_REL(gds->dst_rel) | + S_SQ_MEM_GDS_WORD1_GDS_OP(gds->gds_op) | + S_SQ_MEM_GDS_WORD1_SRC_GPR(gds->src_gpr2); + + bc->bytecode[id++] = S_SQ_MEM_GDS_WORD2_DST_SEL_X(gds->dst_sel_x) | + S_SQ_MEM_GDS_WORD2_DST_SEL_Y(gds->dst_sel_y) | + S_SQ_MEM_GDS_WORD2_DST_SEL_Z(gds->dst_sel_z) | + S_SQ_MEM_GDS_WORD2_DST_SEL_W(gds->dst_sel_w); + return 0; +} diff --git a/src/gallium/drivers/r600/eg_sq.h b/src/gallium/drivers/r600/eg_sq.h index 97e230f56c7..3074cfe97d2 100644 --- a/src/gallium/drivers/r600/eg_sq.h +++ b/src/gallium/drivers/r600/eg_sq.h @@ -514,6 +514,27 @@ #define G_SQ_TEX_WORD2_SRC_SEL_W(x) (((x) >> 29) & 0x7) #define C_SQ_TEX_WORD2_SRC_SEL_W 0x1FFFFFFF +#define P_SQ_MEM_GDS_WORD0 +#define S_SQ_MEM_GDS_WORD0_MEM_INST(x) (((x) & 0x1f) << 0) +#define S_SQ_MEM_GDS_WORD0_MEM_OP(x) (((x) & 0x7) << 8) +#define S_SQ_MEM_GDS_WORD0_SRC_GPR(x) (((x) & 0x7f) << 11) +#define S_SQ_MEM_GDS_WORD0_SRC_REL(x) (((x) & 0x3) << 18) +#define S_SQ_MEM_GDS_WORD0_SRC_SEL_X(x) (((x) & 0x7) << 20) +#define S_SQ_MEM_GDS_WORD0_SRC_SEL_Y(x) (((x) & 0x7) << 23) +#define S_SQ_MEM_GDS_WORD0_SRC_SEL_Z(x) (((x) & 0x7) << 26) + +#define P_SQ_MEM_GDS_WORD1 +#define S_SQ_MEM_GDS_WORD1_DST_GPR(x) (((x) & 0x7f) << 0) +#define S_SQ_MEM_GDS_WORD1_DST_REL(x) (((x) & 0x3) << 7) +#define S_SQ_MEM_GDS_WORD1_GDS_OP(x) (((x) & 0x3f) << 9) +#define S_SQ_MEM_GDS_WORD1_SRC_GPR(x) (((x) & 0x7f) << 16) + +#define P_SQ_MEM_GDS_WORD2 +#define S_SQ_MEM_GDS_WORD2_DST_SEL_X(x) (((x) & 0x7) << 0) +#define S_SQ_MEM_GDS_WORD2_DST_SEL_Y(x) (((x) & 0x7) << 3) +#define S_SQ_MEM_GDS_WORD2_DST_SEL_Z(x) (((x) & 0x7) << 6) +#define S_SQ_MEM_GDS_WORD2_DST_SEL_W(x) (((x) & 0x7) << 9) + #define V_SQ_CF_COND_ACTIVE 0x00 #define V_SQ_CF_COND_FALSE 0x01 #define V_SQ_CF_COND_BOOL 0x02 diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c index cf18f6db907..2471f8a4694 100644 --- a/src/gallium/drivers/r600/r600_asm.c +++ b/src/gallium/drivers/r600/r600_asm.c @@ -61,6 +61,7 @@ static struct r600_bytecode_cf *r600_bytecode_cf(void) LIST_INITHEAD(&cf->alu); LIST_INITHEAD(&cf->vtx); LIST_INITHEAD(&cf->tex); + LIST_INITHEAD(&cf->gds); return cf; } @@ -94,6 +95,16 @@ static struct r600_bytecode_tex *r600_bytecode_tex(void) return tex; } +static struct r600_bytecode_gds *r600_bytecode_gds(void) +{ + struct r600_bytecode_gds *gds = CALLOC_STRUCT(r600_bytecode_gds); + + if (gds == NULL) + return NULL; + LIST_INITHEAD(&gds->list); + return gds; +} + static unsigned stack_entry_size(enum radeon_family chip) { /* Wavefront size: * 64: R600/RV670/RV770/Cypress/R740/Barts/Turks/Caicos/ @@ -1412,6 +1423,33 @@ int r600_bytecode_add_tex(struct r600_bytecode *bc, const struct r600_bytecode_t return 0; } +int r600_bytecode_add_gds(struct r600_bytecode *bc, const struct r600_bytecode_gds *gds) +{ + struct r600_bytecode_gds *ngds = r600_bytecode_gds(); + int r; + + if (ngds == NULL) + return -ENOMEM; + memcpy(ngds, gds, sizeof(struct r600_bytecode_gds)); + + if (bc->cf_last == NULL || + bc->cf_last->op != CF_OP_GDS || + bc->force_add_cf) { + r = r600_bytecode_add_cf(bc); + if (r) { + free(ngds); + return r; + } + bc->cf_last->op = CF_OP_GDS; + } + + LIST_ADDTAIL(&ngds->list, &bc->cf_last->gds); + bc->cf_last->ndw += 4; /* each GDS uses 4 dwords */ + if ((bc->cf_last->ndw / 4) >= r600_bytecode_num_tex_and_vtx_instructions(bc)) + bc->force_add_cf = 1; + return 0; +} + int r600_bytecode_add_cfinst(struct r600_bytecode *bc, unsigned op) { int r; @@ -1623,6 +1661,7 @@ int r600_bytecode_build(struct r600_bytecode *bc) struct r600_bytecode_alu *alu; struct r600_bytecode_vtx *vtx; struct r600_bytecode_tex *tex; + struct r600_bytecode_gds *gds; uint32_t literal[4]; unsigned nliteral; unsigned addr; @@ -1701,6 +1740,14 @@ int r600_bytecode_build(struct r600_bytecode *bc) return r; addr += 4; } + } else if (cf->op == CF_OP_GDS) { + assert(bc->chip_class >= EVERGREEN); + LIST_FOR_EACH_ENTRY(gds, &cf->gds, list) { + r = eg_bytecode_gds_build(bc, gds, addr); + if (r) + return r; + addr += 4; + } } else if (cf->op == CF_OP_TEX) { LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) { assert(bc->chip_class >= EVERGREEN); @@ -1731,6 +1778,7 @@ void r600_bytecode_clear(struct r600_bytecode *bc) struct r600_bytecode_alu *alu = NULL, *next_alu; struct r600_bytecode_tex *tex = NULL, *next_tex; struct r600_bytecode_tex *vtx = NULL, *next_vtx; + struct r600_bytecode_gds *gds = NULL, *next_gds; LIST_FOR_EACH_ENTRY_SAFE(alu, next_alu, &cf->alu, list) { free(alu); @@ -1750,6 +1798,12 @@ void r600_bytecode_clear(struct r600_bytecode *bc) LIST_INITHEAD(&cf->vtx); + LIST_FOR_EACH_ENTRY_SAFE(gds, next_gds, &cf->gds, list) { + free(gds); + } + + LIST_INITHEAD(&cf->gds); + free(cf); } @@ -1911,6 +1965,7 @@ void r600_bytecode_disasm(struct r600_bytecode *bc) struct r600_bytecode_alu *alu = NULL; struct r600_bytecode_vtx *vtx = NULL; struct r600_bytecode_tex *tex = NULL; + struct r600_bytecode_gds *gds = NULL; unsigned i, id, ngr = 0, last; uint32_t literal[4]; @@ -2194,6 +2249,33 @@ void r600_bytecode_disasm(struct r600_bytecode *bc) id += 4; } + + LIST_FOR_EACH_ENTRY(gds, &cf->gds, list) { + int o = 0; + o += fprintf(stderr, " %04d %08X %08X %08X ", id, bc->bytecode[id], + bc->bytecode[id + 1], bc->bytecode[id + 2]); + + o += fprintf(stderr, "%s ", r600_isa_fetch(gds->op)->name); + + if (gds->op != FETCH_OP_TF_WRITE) { + o += fprintf(stderr, "R%d.", gds->dst_gpr); + o += print_swizzle(gds->dst_sel_x); + o += print_swizzle(gds->dst_sel_y); + o += print_swizzle(gds->dst_sel_z); + o += print_swizzle(gds->dst_sel_w); + } + + o += fprintf(stderr, ", R%d.", gds->src_gpr); + o += print_swizzle(gds->src_sel_x); + o += print_swizzle(gds->src_sel_y); + o += print_swizzle(gds->src_sel_z); + + if (gds->op != FETCH_OP_TF_WRITE) { + o += fprintf(stderr, ", R%d.", gds->src_gpr2); + } + fprintf(stderr, "\n"); + id += 4; + } } fprintf(stderr, "--------------------------------------\n"); diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h index d48ad1ebf01..f786bab3d59 100644 --- a/src/gallium/drivers/r600/r600_asm.h +++ b/src/gallium/drivers/r600/r600_asm.h @@ -115,6 +115,24 @@ struct r600_bytecode_vtx { unsigned buffer_index_mode; }; +struct r600_bytecode_gds { + struct list_head list; + unsigned op; + unsigned gds_op; + unsigned src_gpr; + unsigned src_rel; + unsigned src_sel_x; + unsigned src_sel_y; + unsigned src_sel_z; + unsigned src_gpr2; + unsigned dst_gpr; + unsigned dst_rel; + unsigned dst_sel_x; + unsigned dst_sel_y; + unsigned dst_sel_z; + unsigned dst_sel_w; +}; + struct r600_bytecode_output { unsigned array_base; unsigned array_size; @@ -159,6 +177,7 @@ struct r600_bytecode_cf { struct list_head alu; struct list_head tex; struct list_head vtx; + struct list_head gds; struct r600_bytecode_output output; struct r600_bytecode_alu *curr_bs_head; struct r600_bytecode_alu *prev_bs_head; @@ -233,7 +252,7 @@ struct r600_bytecode { /* eg_asm.c */ int eg_bytecode_cf_build(struct r600_bytecode *bc, struct r600_bytecode_cf *cf); int egcm_load_index_reg(struct r600_bytecode *bc, unsigned id, bool inside_alu_clause); - +int eg_bytecode_gds_build(struct r600_bytecode *bc, struct r600_bytecode_gds *gds, unsigned id); /* r600_asm.c */ void r600_bytecode_init(struct r600_bytecode *bc, enum chip_class chip_class, @@ -246,6 +265,8 @@ int r600_bytecode_add_vtx(struct r600_bytecode *bc, const struct r600_bytecode_vtx *vtx); int r600_bytecode_add_tex(struct r600_bytecode *bc, const struct r600_bytecode_tex *tex); +int r600_bytecode_add_gds(struct r600_bytecode *bc, + const struct r600_bytecode_gds *gds); int r600_bytecode_add_output(struct r600_bytecode *bc, const struct r600_bytecode_output *output); int r600_bytecode_build(struct r600_bytecode *bc); |