diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 6bcdb26780b..2e45fb0c7d2 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -1061,6 +1061,41 @@ static void r300_validate_fragment_shader(struct r300_context *r300) } } +static void r300_pick_vertex_shader(struct r300_context *r300) +{ + struct r300_vertex_shader_code *ptr; + struct r300_vertex_shader *vs = r300_vs(r300); + + if (r300->vs_state.state) { + bool wpos = r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED; + + if (!vs->first) { + /* Build the vertex shader for the first time. */ + vs->first = vs->shader = CALLOC_STRUCT(r300_vertex_shader_code); + vs->first->wpos = wpos; + r300_translate_vertex_shader(r300, vs); + r300_mark_atom_dirty(r300, &r300->rs_block_state); + return; + } + /* Pick the vertex shader based on whether we need wpos */ + if (vs->first->wpos != wpos) { + if (vs->first->next && vs->first->next->wpos == wpos) { + ptr = vs->first->next; + vs->first->next = NULL; + ptr->next = vs->first; + vs->first = vs->shader = ptr; + } else { + ptr = CALLOC_STRUCT(r300_vertex_shader_code); + ptr->next = vs->first; + vs->first = vs->shader = ptr; + vs->shader->wpos = wpos; + r300_translate_vertex_shader(r300, vs); + } + r300_mark_atom_dirty(r300, &r300->rs_block_state); + } + } +} + void r300_update_derived_state(struct r300_context* r300) { if (r300->textures_state.dirty) { @@ -1069,6 +1104,8 @@ void r300_update_derived_state(struct r300_context* r300) } r300_validate_fragment_shader(r300); + if (r300->screen->caps.has_tcl) + r300_pick_vertex_shader(r300); if (r300->rs_block_state.dirty) { r300_update_rs_block(r300); diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 22dfe68e1c5..365ae218869 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -99,7 +99,7 @@ static void r300_shader_read_vs_outputs( } } - /* WPOS is a straight copy of POSITION and it's always emitted. */ + /* WPOS is a straight copy of POSITION */ vs_outputs->wpos = i; } @@ -167,7 +167,8 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) } /* WPOS. */ - c->code->outputs[outputs->wpos] = reg++; + if (vs->wpos) + c->code->outputs[outputs->wpos] = reg++; } void r300_init_vs_outputs(struct r300_context *r300, @@ -253,11 +254,12 @@ void r300_translate_vertex_shader(struct r300_context *r300, compiler.Base.remove_unused_constants = TRUE; } - compiler.RequiredOutputs = ~(~0U << (vs->info.num_outputs + 1)); + compiler.RequiredOutputs = ~(~0U << (vs->info.num_outputs + (vs->wpos ? 1 : 0))); compiler.SetHwInputOutput = &set_vertex_inputs_outputs; /* Insert the WPOS output. */ - rc_copy_output(&compiler.Base, 0, vs->outputs.wpos); + if (vs->wpos) + rc_copy_output(&compiler.Base, 0, vs->outputs.wpos); /* Invoke the compiler */ r3xx_compile_vertex_program(&compiler);