summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <[email protected]>2011-06-24 18:05:53 -0400
committerAlex Deucher <[email protected]>2011-06-24 18:22:47 -0400
commitfeec48114b261f43c8dc94c06cfccea3b6ef1689 (patch)
tree95bf5e0bd3b519065b12ae9dc783dbb7ff732ace
parent6062692cc6cd2a88d854b304d9a85bcf4bab0d11 (diff)
r600g: eg+ support for FS_COLOR0_WRITES_ALL_CBUFS
Evergreen+ don't support multi-writes so we need to emulate it in the shader. Fixes the following piglit tests: fbo-drawbuffers-fragcolor ati_draw_buffers-arbfp-no-option Signed-off-by: Alex Deucher <[email protected]>
-rw-r--r--src/gallium/drivers/r600/evergreen_state.c6
-rw-r--r--src/gallium/drivers/r600/r600_asm.c2
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h1
-rw-r--r--src/gallium/drivers/r600/r600_shader.c77
-rw-r--r--src/gallium/drivers/r600/r600_shader.h1
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c4
6 files changed, 61 insertions, 30 deletions
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index dfe78964929..dc182611482 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -885,6 +885,7 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
/* build states */
rctx->have_depth_fb = 0;
+ rctx->nr_cbufs = state->nr_cbufs;
for (int i = 0; i < state->nr_cbufs; i++) {
evergreen_cb(rctx, rstate, state, i);
}
@@ -1631,7 +1632,10 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader
rshader->output[i].name == TGSI_SEMANTIC_STENCIL)
exports_ps |= 1;
else if (rshader->output[i].name == TGSI_SEMANTIC_COLOR) {
- num_cout++;
+ if (rshader->fs_write_all)
+ num_cout = rshader->nr_cbufs;
+ else
+ num_cout++;
}
}
exports_ps |= S_02884C_EXPORT_COLORS(num_cout);
diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c
index c447a031063..065f955ebcb 100644
--- a/src/gallium/drivers/r600/r600_asm.c
+++ b/src/gallium/drivers/r600/r600_asm.c
@@ -1863,6 +1863,8 @@ void r600_bc_dump(struct r600_bc *bc)
break;
case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
+ case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
+ case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
fprintf(stderr, "%04d %08X EXPORT ", id, bc->bytecode[id]);
fprintf(stderr, "GPR:%X ", cf->output.gpr);
fprintf(stderr, "ELEM_SIZE:%X ", cf->output.elem_size);
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index dc9aad07782..2667c80bcef 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -213,6 +213,7 @@ struct r600_pipe_context {
boolean export_16bpc;
unsigned alpha_ref;
boolean alpha_ref_dirty;
+ unsigned nr_cbufs;
struct r600_textures_info ps_samplers;
struct r600_pipe_fences fences;
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 2e5d4a6c49f..f83d7079b29 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -606,7 +606,7 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
struct r600_bc_output output[32];
unsigned output_done, noutput;
unsigned opcode;
- int i, r = 0, pos0;
+ int i, j, r = 0, pos0;
ctx.bc = &shader->bc;
ctx.shader = shader;
@@ -623,6 +623,8 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
shader->clamp_color = (((ctx.type == TGSI_PROCESSOR_FRAGMENT) && rctx->clamp_fragment_color) ||
((ctx.type == TGSI_PROCESSOR_VERTEX) && rctx->clamp_vertex_color));
+ shader->nr_cbufs = rctx->nr_cbufs;
+
/* register allocations */
/* Values [0,127] correspond to GPR[0..127].
* Values [128,159] correspond to constant buffer bank 0
@@ -767,50 +769,68 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
}
/* export output */
+ j = 0;
for (i = 0, pos0 = 0; i < noutput; i++) {
memset(&output[i], 0, sizeof(struct r600_bc_output));
- output[i].gpr = shader->output[i].gpr;
- output[i].elem_size = 3;
- output[i].swizzle_x = 0;
- output[i].swizzle_y = 1;
- output[i].swizzle_z = 2;
- output[i].swizzle_w = 3;
- output[i].burst_count = 1;
- output[i].barrier = 1;
- output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
- output[i].array_base = i - pos0;
- output[i].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
+ output[i + j].gpr = shader->output[i].gpr;
+ output[i + j].elem_size = 3;
+ output[i + j].swizzle_x = 0;
+ output[i + j].swizzle_y = 1;
+ output[i + j].swizzle_z = 2;
+ output[i + j].swizzle_w = 3;
+ output[i + j].burst_count = 1;
+ output[i + j].barrier = 1;
+ output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
+ output[i + j].array_base = i - pos0;
+ output[i + j].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
switch (ctx.type) {
case TGSI_PROCESSOR_VERTEX:
if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
- output[i].array_base = 60;
- output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
+ output[i + j].array_base = 60;
+ output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
/* position doesn't count in array_base */
pos0++;
}
if (shader->output[i].name == TGSI_SEMANTIC_PSIZE) {
- output[i].array_base = 61;
- output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
+ output[i + j].array_base = 61;
+ output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
/* position doesn't count in array_base */
pos0++;
}
break;
case TGSI_PROCESSOR_FRAGMENT:
if (shader->output[i].name == TGSI_SEMANTIC_COLOR) {
- output[i].array_base = shader->output[i].sid;
- output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+ output[i + j].array_base = shader->output[i].sid;
+ output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+ if (shader->fs_write_all && (shader->family >= CHIP_CEDAR)) {
+ for (j = 1; j < shader->nr_cbufs; j++) {
+ memset(&output[i + j], 0, sizeof(struct r600_bc_output));
+ output[i + j].gpr = shader->output[i].gpr;
+ output[i + j].elem_size = 3;
+ output[i + j].swizzle_x = 0;
+ output[i + j].swizzle_y = 1;
+ output[i + j].swizzle_z = 2;
+ output[i + j].swizzle_w = 3;
+ output[i + j].burst_count = 1;
+ output[i + j].barrier = 1;
+ output[i + j].array_base = shader->output[i].sid + j;
+ output[i + j].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
+ output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+ }
+ j--;
+ }
} else if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
- output[i].array_base = 61;
- output[i].swizzle_x = 2;
- output[i].swizzle_y = 7;
- output[i].swizzle_z = output[i].swizzle_w = 7;
- output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+ output[i + j].array_base = 61;
+ output[i + j].swizzle_x = 2;
+ output[i + j].swizzle_y = 7;
+ output[i + j].swizzle_z = output[i + j].swizzle_w = 7;
+ output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
} else if (shader->output[i].name == TGSI_SEMANTIC_STENCIL) {
- output[i].array_base = 61;
- output[i].swizzle_x = 7;
- output[i].swizzle_y = 1;
- output[i].swizzle_z = output[i].swizzle_w = 7;
- output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+ output[i + j].array_base = 61;
+ output[i + j].swizzle_x = 7;
+ output[i + j].swizzle_y = 1;
+ output[i + j].swizzle_z = output[i + j].swizzle_w = 7;
+ output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
} else {
R600_ERR("unsupported fragment output name %d\n", shader->output[i].name);
r = -EINVAL;
@@ -823,6 +843,7 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
goto out_err;
}
}
+ noutput += j;
/* add fake param output for vertex shader if no param is exported */
if (ctx.type == TGSI_PROCESSOR_VERTEX) {
for (i = 0, pos0 = 0; i < noutput; i++) {
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index c1e00f3b662..76aebf2b1ea 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -47,6 +47,7 @@ struct r600_shader {
boolean uses_kill;
boolean fs_write_all;
boolean clamp_color;
+ unsigned nr_cbufs;
};
#endif
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index f1b0fc32b53..bf4e90ecb2f 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -599,7 +599,9 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
if (rctx->vs_shader->shader.clamp_color != rctx->clamp_vertex_color)
r600_shader_rebuild(ctx, rctx->vs_shader);
- if (rctx->ps_shader->shader.clamp_color != rctx->clamp_fragment_color)
+ if ((rctx->ps_shader->shader.clamp_color != rctx->clamp_fragment_color) ||
+ (rctx->ps_shader->shader.fs_write_all &&
+ (rctx->ps_shader->shader.nr_cbufs != rctx->nr_cbufs)))
r600_shader_rebuild(ctx, rctx->ps_shader);
if (rctx->spi_dirty)