diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2013-09-30 17:09:19 +0200 |
---|---|---|
committer | Lucas Stach <l.stach@pengutronix.de> | 2014-07-28 12:33:37 +0200 |
commit | a61c6481ef883b0d97c4807ff3e7e3cc42189b9b (patch) | |
tree | 8676547543178c820b0adbafecb4df8c32fc241d | |
parent | fc6a00cf6dde2531bd17bb534f5e5b576632b08e (diff) | |
download | mesa-a61c6481ef883b0d97c4807ff3e7e3cc42189b9b.tar.gz mesa-a61c6481ef883b0d97c4807ff3e7e3cc42189b9b.tar.xz |
sync etna driver to 296195c
-rw-r--r-- | src/gallium/drivers/etna/etna_asm.c | 8 | ||||
-rw-r--r-- | src/gallium/drivers/etna/etna_asm.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/etna/etna_compiler.c | 77 | ||||
-rw-r--r-- | src/gallium/drivers/etna/etna_debug.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/etna/etna_pipe.c | 4 |
5 files changed, 80 insertions, 17 deletions
diff --git a/src/gallium/drivers/etna/etna_asm.c b/src/gallium/drivers/etna/etna_asm.c index 65816fc840..c4a4802806 100644 --- a/src/gallium/drivers/etna/etna_asm.c +++ b/src/gallium/drivers/etna/etna_asm.c @@ -26,7 +26,7 @@ #include <etnaviv/isa.xml.h> /* Return whether the rgroup is one of the uniforms */ -static inline int rgroup_is_uniform(unsigned rgroup) +int etna_rgroup_is_uniform(unsigned rgroup) { return rgroup == INST_RGROUP_UNIFORM_0 || rgroup == INST_RGROUP_UNIFORM_1; @@ -41,9 +41,9 @@ static bool check_uniforms(const struct etna_inst *inst) unsigned uni_rgroup = -1; unsigned uni_reg = -1; bool conflict = false; - for(int src=0; src<3; ++src) + for(int src=0; src<ETNA_NUM_SRC; ++src) { - if(rgroup_is_uniform(inst->src[src].rgroup)) + if(etna_rgroup_is_uniform(inst->src[src].rgroup)) { if(uni_reg == -1) /* first uniform used */ { @@ -68,7 +68,7 @@ int etna_assemble(uint32_t *out, const struct etna_inst *inst) if(!check_uniforms(inst)) { - DBG("warning: generating instruction that accesses two different uniforms"); + BUG("error: generating instruction that accesses two different uniforms"); } out[0] = VIV_ISA_WORD_0_OPCODE(inst->opcode) | diff --git a/src/gallium/drivers/etna/etna_asm.h b/src/gallium/drivers/etna/etna_asm.h index 6d7def63c8..ad2e0751e7 100644 --- a/src/gallium/drivers/etna/etna_asm.h +++ b/src/gallium/drivers/etna/etna_asm.h @@ -91,5 +91,8 @@ int etna_assemble(uint32_t *out, const struct etna_inst *inst); */ int etna_assemble_set_imm(uint32_t *out, uint32_t imm); +/* Return whether the rgroup is one of the uniforms */ +int etna_rgroup_is_uniform(unsigned rgroup); + #endif diff --git a/src/gallium/drivers/etna/etna_compiler.c b/src/gallium/drivers/etna/etna_compiler.c index fba7a8981c..d0a281c77c 100644 --- a/src/gallium/drivers/etna/etna_compiler.c +++ b/src/gallium/drivers/etna/etna_compiler.c @@ -153,6 +153,7 @@ struct etna_compile_data /* Temporary register for use within translated TGSI instruction, * only allocated when needed. */ + int inner_temps; /* number of inner temps used; only up to one available at this point */ struct etna_native_reg inner_temp; /* Fields for handling nested conditionals */ @@ -572,10 +573,70 @@ static void etna_compile_pass_optimize_outputs(struct etna_compile_data *cd, con tgsi_parse_free(&ctx); } +/* Get temporary to be used within one TGSI instruction. + * The first time that this function is called the temporary will be allocated. + * Each call to this function will return the same temporary. + */ +static struct etna_native_reg etna_compile_get_inner_temp(struct etna_compile_data *cd) +{ + if(cd->inner_temps) + BUG("Multiple inner temporaries (%i) requested in one instruction", cd->inner_temps + 1); + if(!cd->inner_temp.valid) + cd->inner_temp = alloc_new_native_reg(cd); + cd->inner_temps += 1; + return cd->inner_temp; +} + /* emit instruction and append to program */ -static void emit_inst(struct etna_compile_data *cd, const struct etna_inst *inst) +static void emit_inst(struct etna_compile_data *cd, struct etna_inst *inst) { assert(cd->inst_ptr <= ETNA_MAX_INSTRUCTIONS); + + /* Check for uniform conflicts (each instruction can only access one uniform), + * if detected, use an intermediate temporary */ + unsigned uni_rgroup = -1; + unsigned uni_reg = -1; + + for(int src=0; src<ETNA_NUM_SRC; ++src) + { + if(etna_rgroup_is_uniform(inst->src[src].rgroup)) + { + if(uni_reg == -1) /* first unique uniform used */ + { + uni_rgroup = inst->src[src].rgroup; + uni_reg = inst->src[src].reg; + } else { /* second or later; check that it is a re-use */ + if(uni_rgroup != inst->src[src].rgroup || + uni_reg != inst->src[src].reg) + { + DBG_F(ETNA_DBG_COMPILER_MSGS, + "perf warning: instruction that accesses different uniforms, need to generate extra MOV"); + struct etna_native_reg inner_temp = etna_compile_get_inner_temp(cd); + + /* Generate move instruction to temporary */ + etna_assemble(&cd->code[cd->inst_ptr*4], &(struct etna_inst) { + .opcode = INST_OPCODE_MOV, + .dst.use = 1, + .dst.comps = INST_COMPS_X | INST_COMPS_Y | INST_COMPS_Z | INST_COMPS_W, + .dst.reg = inner_temp.id, + .src[2] = inst->src[src] + }); + cd->inst_ptr ++; + + /* Modify instruction to use temp register instead of uniform */ + inst->src[src].use = 1; + inst->src[src].rgroup = INST_RGROUP_TEMP; + inst->src[src].reg = inner_temp.id; + inst->src[src].swiz = INST_SWIZ_IDENTITY; /* swizzling happens on MOV */ + inst->src[src].neg = 0; /* negation happens on MOV */ + inst->src[src].abs = 0; /* abs happens on MOV */ + inst->src[src].amode = 0; /* amode effects happen on MOV */ + } + } + } + } + + /* Finally assemble the actual instruction */ etna_assemble(&cd->code[cd->inst_ptr*4], inst); cd->inst_ptr ++; } @@ -672,17 +733,6 @@ static void label_mark_use(struct etna_compile_data *cd, struct etna_compile_lab cd->lbl_usage[cd->inst_ptr] = label; } -/* Get temporary to be used within one TGSI instruction. - * The first time that this function is called the temporary will be allocated. - * Each call to this function will return the same temporary. - */ -static struct etna_native_reg etna_compile_get_inner_temp(struct etna_compile_data *cd) -{ - if(!cd->inner_temp.valid) - cd->inner_temp = alloc_new_native_reg(cd); - return cd->inner_temp; -} - /* Pass -- compile instructions */ static void etna_compile_pass_generate_code(struct etna_compile_data *cd, const struct tgsi_token *tokens) { @@ -696,6 +746,9 @@ static void etna_compile_pass_generate_code(struct etna_compile_data *cd, const { tgsi_parse_token(&ctx); const struct tgsi_full_instruction *inst = 0; + /* No inner temps used yet for this instruction, clear counter */ + cd->inner_temps = 0; + switch(ctx.FullToken.Token.Type) { case TGSI_TOKEN_TYPE_INSTRUCTION: diff --git a/src/gallium/drivers/etna/etna_debug.h b/src/gallium/drivers/etna/etna_debug.h index 1274ffcba6..df6f792c7c 100644 --- a/src/gallium/drivers/etna/etna_debug.h +++ b/src/gallium/drivers/etna/etna_debug.h @@ -27,6 +27,7 @@ #include <stdint.h> #include <stdlib.h> +#include <stdio.h> #include "util/u_debug.h" /* Logging */ @@ -63,6 +64,10 @@ extern uint32_t etna_mesa_debug; /* set in etna_screen.c from ETNA_DEBUG */ debug_printf("%s:%d: "fmt "\n", \ __FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0) +/* A serious bug, show this even in non-debug mode */ +#define BUG(fmt, ...) \ + do { printf("%s:%d: "fmt "\n", \ + __FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0) #endif diff --git a/src/gallium/drivers/etna/etna_pipe.c b/src/gallium/drivers/etna/etna_pipe.c index e5b20a0f3e..a3c52221b8 100644 --- a/src/gallium/drivers/etna/etna_pipe.c +++ b/src/gallium/drivers/etna/etna_pipe.c @@ -954,7 +954,9 @@ static void etna_pipe_set_framebuffer_state(struct pipe_context *pipe, /* merged with depth_stencil_alpha */ if((cbuf->surf.address & 63) || (((cbuf->surf.stride*4) & 63) && cbuf->surf.height > 4)) { - /* XXX Must get temporary surface here. + /* XXX Must make temporary surface here. + * Need the same mechanism on gc2000 when we want to do mipmap generation by + * rendering to levels > 1 due to multitiled / tiled conversion. */ printf("%s: Alignment error, trying to render to %08x with tile stride %i\n", __func__, cbuf->surf.address, cbuf->surf.stride*4); |