diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index e5055afd1bd..1657c577395 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -673,6 +673,11 @@ static inline struct r300_fragment_shader *r300_fs(struct r300_context *r300) return (struct r300_fragment_shader*)r300->fs.state; } +static inline struct r300_vertex_shader *r300_vs(struct r300_context *r300) +{ + return (struct r300_vertex_shader*)r300->vs_state.state; +} + static inline void r300_mark_atom_dirty(struct r300_context *r300, struct r300_atom *atom) { diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index efb1cc792dd..f6212582c2a 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -1103,7 +1103,7 @@ void r300_emit_vap_invariant_state(struct r300_context *r300, void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) { - struct r300_vertex_shader* vs = (struct r300_vertex_shader*)state; + struct r300_vertex_shader_code* vs = ((struct r300_vertex_shader*)state)->shader; struct r300_vertex_program_code* code = &vs->code; struct r300_screen* r300screen = r300->screen; unsigned instruction_count = code->length / 4; @@ -1160,10 +1160,9 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) void r300_emit_vs_constants(struct r300_context* r300, unsigned size, void *state) { - unsigned count = - ((struct r300_vertex_shader*)r300->vs_state.state)->externals_count; + unsigned count = r300_vs(r300)->shader->externals_count; struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; - struct r300_vertex_shader *vs = (struct r300_vertex_shader*)r300->vs_state.state; + struct r300_vertex_shader_code *vs = r300_vs(r300)->shader; unsigned i; int imm_first = vs->externals_count; int imm_end = vs->code.constants.Count; diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 89af36c9c6c..687029fc2fe 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -1973,6 +1973,8 @@ static void* r300_create_vs_state(struct pipe_context* pipe, vs->state.tokens = tgsi_dup_tokens(vs->state.tokens); } + if (!vs->first) + vs->first = vs->shader = CALLOC_STRUCT(r300_vertex_shader_code); if (r300->screen->caps.has_tcl) { r300_init_vs_outputs(r300, vs); r300_translate_vertex_shader(r300, vs); @@ -2003,17 +2005,17 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) if (r300->screen->caps.has_tcl) { unsigned fc_op_dwords = r300->screen->caps.is_r500 ? 3 : 2; r300_mark_atom_dirty(r300, &r300->vs_state); - r300->vs_state.size = vs->code.length + 9 + + r300->vs_state.size = vs->shader->code.length + 9 + (R300_VS_MAX_FC_OPS * fc_op_dwords + 4); r300_mark_atom_dirty(r300, &r300->vs_constants); r300->vs_constants.size = 2 + - (vs->externals_count ? vs->externals_count * 4 + 3 : 0) + - (vs->immediates_count ? vs->immediates_count * 4 + 3 : 0); + (vs->shader->externals_count ? vs->shader->externals_count * 4 + 3 : 0) + + (vs->shader->immediates_count ? vs->shader->immediates_count * 4 + 3 : 0); ((struct r300_constant_buffer*)r300->vs_constants.state)->remap_table = - vs->code.constants_remap_table; + vs->shader->code.constants_remap_table; r300_mark_atom_dirty(r300, &r300->pvs_flush); } else { @@ -2028,8 +2030,13 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; if (r300->screen->caps.has_tcl) { - rc_constants_destroy(&vs->code.constants); - FREE(vs->code.constants_remap_table); + while (vs->shader) { + rc_constants_destroy(&vs->shader->code.constants); + FREE(vs->shader->code.constants_remap_table); + vs->shader = vs->shader->next; + FREE(vs->first); + vs->first = vs->shader; + } } else { draw_delete_vertex_shader(r300->draw, (struct draw_vertex_shader*)vs->draw_vs); @@ -2081,8 +2088,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, if (shader == PIPE_SHADER_VERTEX) { if (r300->screen->caps.has_tcl) { - struct r300_vertex_shader *vs = - (struct r300_vertex_shader*)r300->vs_state.state; + struct r300_vertex_shader_code *vs = r300_vs(r300)->shader; if (!vs) { cbuf->buffer_base = 0; diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 970f97c9ae2..6bcdb26780b 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -54,7 +54,7 @@ static void r300_draw_emit_attrib(struct r300_context* r300, enum attrib_emit emit, int index) { - struct r300_vertex_shader* vs = r300->vs_state.state; + struct r300_vertex_shader_code* vs = r300_vs(r300)->shader; struct tgsi_shader_info* info = &vs->info; int output; @@ -66,7 +66,7 @@ static void r300_draw_emit_attrib(struct r300_context* r300, static void r300_draw_emit_all_attribs(struct r300_context* r300) { - struct r300_vertex_shader* vs = r300->vs_state.state; + struct r300_vertex_shader_code* vs = r300_vs(r300)->shader; struct r300_shader_semantics* vs_outputs = &vs->outputs; int i, gen_count; @@ -303,7 +303,7 @@ static void r500_rs_tex_write(struct r300_rs_block* rs, int id, int fp_offset) * and error. */ static void r300_update_rs_block(struct r300_context *r300) { - struct r300_vertex_shader *vs = r300->vs_state.state; + struct r300_vertex_shader_code *vs = r300_vs(r300)->shader; struct r300_shader_semantics *vs_outputs = &vs->outputs; struct r300_shader_semantics *fs_inputs = &r300_fs(r300)->shader->inputs; struct r300_rs_block rs = {0}; diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 0ea2d4631ee..ebcbf57a1b6 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -105,7 +105,7 @@ static void r300_shader_read_vs_outputs( static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) { - struct r300_vertex_shader * vs = c->UserData; + struct r300_vertex_shader_code * vs = c->UserData; struct r300_shader_semantics* outputs = &vs->outputs; struct tgsi_shader_info* info = &vs->info; int i, reg = 0; @@ -173,13 +173,13 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) void r300_init_vs_outputs(struct r300_context *r300, struct r300_vertex_shader *vs) { - tgsi_scan_shader(vs->state.tokens, &vs->info); - r300_shader_read_vs_outputs(r300, &vs->info, &vs->outputs); + tgsi_scan_shader(vs->state.tokens, &vs->shader->info); + r300_shader_read_vs_outputs(r300, &vs->shader->info, &vs->shader->outputs); } static void r300_dummy_vertex_shader( struct r300_context* r300, - struct r300_vertex_shader* shader) + struct r300_vertex_shader* vs) { struct ureg_program *ureg; struct ureg_dst dst; @@ -194,20 +194,21 @@ static void r300_dummy_vertex_shader( ureg_MOV(ureg, dst, imm); ureg_END(ureg); - shader->state.tokens = tgsi_dup_tokens(ureg_finalize(ureg)); + vs->state.tokens = tgsi_dup_tokens(ureg_finalize(ureg)); ureg_destroy(ureg); - shader->dummy = TRUE; - r300_init_vs_outputs(r300, shader); - r300_translate_vertex_shader(r300, shader); + vs->shader->dummy = TRUE; + r300_init_vs_outputs(r300, vs); + r300_translate_vertex_shader(r300, vs); } void r300_translate_vertex_shader(struct r300_context *r300, - struct r300_vertex_shader *vs) + struct r300_vertex_shader *shader) { struct r300_vertex_program_compiler compiler; struct tgsi_to_rc ttr; unsigned i; + struct r300_vertex_shader_code *vs = shader->shader; /* Setup the compiler */ memset(&compiler, 0, sizeof(compiler)); @@ -230,7 +231,7 @@ void r300_translate_vertex_shader(struct r300_context *r300, if (compiler.Base.Debug & RC_DBG_LOG) { DBG(r300, DBG_VP, "r300: Initial vertex program\n"); - tgsi_dump(vs->state.tokens, 0); + tgsi_dump(shader->state.tokens, 0); } /* Translate TGSI to our internal representation */ @@ -238,12 +239,12 @@ void r300_translate_vertex_shader(struct r300_context *r300, ttr.info = &vs->info; ttr.use_half_swizzles = FALSE; - r300_tgsi_to_rc(&ttr, vs->state.tokens); + r300_tgsi_to_rc(&ttr, shader->state.tokens); if (ttr.error) { fprintf(stderr, "r300 VP: Cannot translate a shader. " "Using a dummy shader instead.\n"); - r300_dummy_vertex_shader(r300, vs); + r300_dummy_vertex_shader(r300, shader); return; } @@ -270,7 +271,7 @@ void r300_translate_vertex_shader(struct r300_context *r300, } rc_destroy(&compiler.Base); - r300_dummy_vertex_shader(r300, vs); + r300_dummy_vertex_shader(r300, shader); return; } diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index 3bd0fd66775..91f377a2477 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -33,9 +33,8 @@ struct r300_context; -struct r300_vertex_shader { +struct r300_vertex_shader_code { /* Parent class */ - struct pipe_shader_state state; struct tgsi_shader_info info; struct r300_shader_semantics outputs; @@ -44,6 +43,8 @@ struct r300_vertex_shader { * compilation failure. */ boolean dummy; + boolean wpos; + /* Numbers of constants for each type. */ unsigned externals_count; unsigned immediates_count; @@ -52,6 +53,19 @@ struct r300_vertex_shader { /* Machine code (if translated) */ struct r300_vertex_program_code code; + struct r300_vertex_shader_code *next; +}; + +struct r300_vertex_shader { + /* Parent class */ + struct pipe_shader_state state; + + /* Currently-bound vertex shader. */ + struct r300_vertex_shader_code *shader; + + /* List of the same shaders compiled with different states. */ + struct r300_vertex_shader_code *first; + /* SWTCL-specific. */ void *draw_vs; }; diff --git a/src/gallium/drivers/r300/r300_vs_draw.c b/src/gallium/drivers/r300/r300_vs_draw.c index 29590bae325..0975e86fa6f 100644 --- a/src/gallium/drivers/r300/r300_vs_draw.c +++ b/src/gallium/drivers/r300/r300_vs_draw.c @@ -374,6 +374,6 @@ void r300_draw_init_vertex_shader(struct r300_context *r300, r300_init_vs_outputs(r300, vs); /* Make the last generic be WPOS. */ - vs->outputs.wpos = vs->outputs.generic[transform.last_generic + 1]; - vs->outputs.generic[transform.last_generic + 1] = ATTR_UNUSED; + vs->shader->outputs.wpos = vs->shader->outputs.generic[transform.last_generic + 1]; + vs->shader->outputs.generic[transform.last_generic + 1] = ATTR_UNUSED; }