From 26f67a272b6668258fe3552a675414502e077dd9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 24 Dec 2009 16:05:44 +0100 Subject: [PATCH] r300g: disable the rasterization of WPOS if it's unused by the FS --- src/gallium/drivers/r300/r300_state.c | 12 +++- src/gallium/drivers/r300/r300_state_derived.c | 18 ++---- src/gallium/drivers/r300/r300_vs.c | 56 ++++++++++++------- src/gallium/drivers/r300/r300_vs.h | 6 ++ 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index ad8e210dcd8..affd0b45910 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -556,6 +556,10 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) r300->fs = fs; r300_pick_fragment_shader(r300); + if (r300->vs && r300_vertex_shader_setup_wpos(r300)) { + r300->dirty_state |= R300_NEW_VERTEX_FORMAT; + } + r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS; } @@ -974,7 +978,13 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) } r300->vs = vs; - r300->dirty_state |= R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS; + if (r300->fs) { + r300_vertex_shader_setup_wpos(r300); + } + + r300->dirty_state |= + R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS | + R300_NEW_VERTEX_FORMAT; } else { draw_flush(r300->draw); draw_bind_vertex_shader(r300->draw, diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 242716fcccb..2a12a02e18a 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -411,23 +411,13 @@ static void r300_update_rs_block(struct r300_context* r300, } /* Rasterize WPOS. */ - if (vs_outputs->wpos != ATTR_UNUSED) { - /* Always rasterize if it's written by the VS, - * otherwise it locks up. */ + /* If the FS doesn't need it, it's not written by the VS. */ + if (fs_inputs->wpos != ATTR_UNUSED) { rX00_rs_tex(rs, tex_count, tex_count, FALSE); + rX00_rs_tex_write(rs, tex_count, fp_offset); - /* Write it to the FS input register if it's used by the FS. */ - if (fs_inputs->wpos != ATTR_UNUSED) { - rX00_rs_tex_write(rs, tex_count, fp_offset); - fp_offset++; - } + fp_offset++; tex_count++; - } else { - /* Skip the FS input register, leave it uninitialized. */ - /* If we try to set it to (0,0,0,1), it will lock up. */ - if (fs_inputs->wpos != ATTR_UNUSED) { - fp_offset++; - } } /* Rasterize at least one color, or bad things happen. */ diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 57531fc554f..3512a6dc760 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -22,6 +22,7 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "r300_vs.h" +#include "r300_fs.h" #include "r300_context.h" #include "r300_screen.h" @@ -90,10 +91,10 @@ static void r300_shader_read_vs_outputs( } } -static void r300_shader_vap_output_fmt( - struct r300_shader_semantics* vs_outputs, - uint* hwfmt) +static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs) { + struct r300_shader_semantics* vs_outputs = &vs->outputs; + uint32_t* hwfmt = vs->hwfmt; int i, gen_count; /* Do the actual vertex_info setup. @@ -146,15 +147,11 @@ static void r300_shader_vap_output_fmt( gen_count++; } - /* WPOS. */ - if (vs_outputs->wpos != ATTR_UNUSED) { - hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count); - hwfmt[3] |= (4 << (3 * gen_count)); - gen_count++; - } - /* XXX magic */ assert(gen_count <= 8); + + /* WPOS. */ + vs->wpos_tex_output = gen_count; } /* Sets up stream mapping to equivalent VS outputs if TCL is bypassed @@ -211,9 +208,6 @@ static void r300_stream_locations_notcl( gen_count++; } - /* XXX magic */ - assert(gen_count <= 8); - for (; tabi < 16;) { stream_loc[tabi++] = -1; } @@ -296,7 +290,6 @@ void r300_translate_vertex_shader(struct r300_context* r300, { struct r300_vertex_program_compiler compiler; struct tgsi_to_rc ttr; - boolean use_wpos = TRUE; /* Initialize. */ r300_shader_read_vs_outputs(&vs->info, &vs->outputs); @@ -319,15 +312,13 @@ void r300_translate_vertex_shader(struct r300_context* r300, r300_tgsi_to_rc(&ttr, vs->state.tokens); - compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+use_wpos)); + compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1)); compiler.SetHwInputOutput = &set_vertex_inputs_outputs; /* Insert the WPOS output. */ - if (use_wpos) { - r300_insert_wpos(&compiler, &vs->outputs); - } + r300_insert_wpos(&compiler, &vs->outputs); - r300_shader_vap_output_fmt(&vs->outputs, vs->hwfmt); + r300_shader_vap_output_fmt(vs); r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl); /* Invoke the compiler */ @@ -342,3 +333,30 @@ void r300_translate_vertex_shader(struct r300_context* r300, rc_destroy(&compiler.Base); vs->translated = TRUE; } + +boolean r300_vertex_shader_setup_wpos(struct r300_context* r300) +{ + struct r300_vertex_shader* vs = r300->vs; + int tex_output = r300->vs->wpos_tex_output; + uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output; + uint32_t* hwfmt = vs->hwfmt; + + if (r300->fs->inputs.wpos != ATTR_UNUSED) { + /* Enable WPOS in VAP. */ + if (!(hwfmt[1] & tex_fmt)) { + hwfmt[1] |= tex_fmt; + hwfmt[3] |= (4 << (3 * tex_output)); + + assert(tex_output < 8); + return TRUE; + } + } else { + /* Disable WPOS in VAP. */ + if (hwfmt[1] & tex_fmt) { + hwfmt[1] &= ~tex_fmt; + hwfmt[3] &= ~(4 << (3 * tex_output)); + return TRUE; + } + } + return FALSE; +} diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index 67e9db5366f..18cfeee3cd4 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -43,6 +43,9 @@ struct r300_vertex_shader { /* Stream locations for SWTCL or if TCL is bypassed. */ int stream_loc_notcl[16]; + /* Output stream location for WPOS. */ + int wpos_tex_output; + /* Has this shader been translated yet? */ boolean translated; @@ -53,4 +56,7 @@ struct r300_vertex_shader { void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs); +/* Return TRUE if VAP (hwfmt) needs to be re-emitted. */ +boolean r300_vertex_shader_setup_wpos(struct r300_context* r300); + #endif /* R300_VS_H */ -- 2.30.2