mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-04 04:00:39 +02:00
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:
parent
07498075b5
commit
4e52e8f746
5 changed files with 54 additions and 9 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue