r300g: add support for color0 writes to all bound color buffers.

Thanks to Marek Olšák for making my initial attempt actually work.

Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Dave Airlie 2010-12-18 10:40:33 +10:00
parent 07498075b5
commit 4e52e8f746
5 changed files with 54 additions and 9 deletions

View file

@ -697,7 +697,8 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias);
enum r300_fb_state_change {
R300_CHANGED_FB_STATE = 0,
R300_CHANGED_CBZB_FLAG,
R300_CHANGED_ZCLEAR_FLAG
R300_CHANGED_ZCLEAR_FLAG,
R300_CHANGED_MULTIWRITE
};
void r300_mark_fb_state_dirty(struct r300_context *r300,

View file

@ -369,6 +369,8 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
struct r300_surface* surf;
unsigned i;
boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
uint32_t rb3d_cctl = 0;
CS_LOCALS(r300);
BEGIN_CS(size);
@ -376,11 +378,13 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
/* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers, which is not
* what we usually want. */
if (r300->screen->caps.is_r500) {
OUT_CS_REG(R300_RB3D_CCTL,
R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE);
} else {
OUT_CS_REG(R300_RB3D_CCTL, 0);
rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE;
}
if (r300_fragment_shader_writes_all(r300_fs(r300))) {
rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs);
}
OUT_CS_REG(R300_RB3D_CCTL, rb3d_cctl);
/* Set up colorbuffers. */
for (i = 0; i < fb->nr_cbufs; i++) {
@ -482,15 +486,21 @@ void r300_emit_fb_state_pipelined(struct r300_context *r300,
{
struct pipe_framebuffer_state* fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
unsigned i;
unsigned i, num_cbufs = fb->nr_cbufs;
CS_LOCALS(r300);
/* If we use the multiwrite feature, the colorbuffers 2,3,4 must be
* marked as UNUSED in the US block. */
if (r300_fragment_shader_writes_all(r300_fs(r300))) {
num_cbufs = MIN2(num_cbufs, 1);
}
BEGIN_CS(size);
/* Colorbuffer format in the US block.
* (must be written after unpipelined regs) */
OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4);
for (i = 0; i < fb->nr_cbufs; i++) {
for (i = 0; i < num_cbufs; i++) {
OUT_CS(r300_surface(fb->cbufs[i])->format);
}
for (; i < 4; i++) {

View file

@ -395,6 +395,13 @@ static void r300_translate_fragment_shader(
find_output_registers(&compiler, shader);
shader->write_all = FALSE;
for (i = 0; i < shader->info.num_properties; i++) {
if (shader->info.properties[i].name == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) {
shader->write_all = TRUE;
}
}
if (compiler.Base.Debug & RC_DBG_LOG) {
DBG(r300, DBG_FP, "r300: Initial fragment program\n");
tgsi_dump(tokens, 0);

View file

@ -54,6 +54,9 @@ struct r300_fragment_shader_code {
uint32_t *cb_code;
struct r300_fragment_shader_code* next;
boolean write_all;
};
struct r300_fragment_shader {
@ -81,4 +84,10 @@ static INLINE boolean r300_fragment_shader_writes_depth(struct r300_fragment_sha
return (fs->shader->code.writes_depth) ? TRUE : FALSE;
}
static INLINE boolean r300_fragment_shader_writes_all(struct r300_fragment_shader *fs)
{
if (!fs)
return FALSE;
return (fs->shader->write_all) ? TRUE : FALSE;
}
#endif /* R300_FS_H */

View file

@ -686,13 +686,22 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
struct pipe_framebuffer_state *state = r300->fb_state.state;
boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
/* What is marked as dirty depends on the enum r300_fb_state_change. */
r300_mark_atom_dirty(r300, &r300->gpu_flush);
r300_mark_atom_dirty(r300, &r300->fb_state);
r300_mark_atom_dirty(r300, &r300->hyperz_state);
/* What is marked as dirty depends on the enum r300_fb_state_change. */
if (change == R300_CHANGED_FB_STATE) {
r300_mark_atom_dirty(r300, &r300->aa_state);
}
if (change == R300_CHANGED_FB_STATE ||
change == R300_CHANGED_CBZB_FLAG ||
change == R300_CHANGED_ZCLEAR_FLAG) {
r300_mark_atom_dirty(r300, &r300->hyperz_state);
}
if (change == R300_CHANGED_FB_STATE ||
change == R300_CHANGED_MULTIWRITE) {
r300_mark_atom_dirty(r300, &r300->fb_state_pipelined);
}
@ -876,16 +885,25 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
{
struct r300_context* r300 = r300_context(pipe);
struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader;
struct pipe_framebuffer_state *fb = r300->fb_state.state;
boolean last_multi_write;
if (fs == NULL) {
r300->fs.state = NULL;
return;
}
last_multi_write = r300_fragment_shader_writes_all(r300_fs(r300));
r300->fs.state = fs;
r300_pick_fragment_shader(r300);
r300_mark_fs_code_dirty(r300);
if (fb->nr_cbufs > 1 &&
last_multi_write != r300_fragment_shader_writes_all(fs)) {
r300_mark_fb_state_dirty(r300, R300_CHANGED_MULTIWRITE);
}
r300_mark_atom_dirty(r300, &r300->rs_block_state); /* Will be updated before the emission. */
}