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 <alexdeucher@gmail.com>
This commit is contained in:
Alex Deucher
2011-06-24 18:05:53 -04:00
parent 6062692cc6
commit feec48114b
6 changed files with 61 additions and 30 deletions
+5 -1
View File
@@ -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);
+2
View File
@@ -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);
+1
View File
@@ -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;
+49 -28
View File
@@ -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++) {
+1
View File
@@ -47,6 +47,7 @@ struct r600_shader {
boolean uses_kill;
boolean fs_write_all;
boolean clamp_color;
unsigned nr_cbufs;
};
#endif
+3 -1
View File
@@ -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)