summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2013-09-30 17:09:19 +0200
committerLucas Stach <l.stach@pengutronix.de>2014-07-28 12:33:37 +0200
commita61c6481ef883b0d97c4807ff3e7e3cc42189b9b (patch)
tree8676547543178c820b0adbafecb4df8c32fc241d
parentfc6a00cf6dde2531bd17bb534f5e5b576632b08e (diff)
downloadmesa-a61c6481ef883b0d97c4807ff3e7e3cc42189b9b.tar.gz
mesa-a61c6481ef883b0d97c4807ff3e7e3cc42189b9b.tar.xz
sync etna driver to 296195c
-rw-r--r--src/gallium/drivers/etna/etna_asm.c8
-rw-r--r--src/gallium/drivers/etna/etna_asm.h3
-rw-r--r--src/gallium/drivers/etna/etna_compiler.c77
-rw-r--r--src/gallium/drivers/etna/etna_debug.h5
-rw-r--r--src/gallium/drivers/etna/etna_pipe.c4
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);