From 0f614df7974a7126324a7fa5d80ee5c588a76f03 Mon Sep 17 00:00:00 2001 From: Rune Petersen Date: Fri, 17 Nov 2006 19:08:05 +0000 Subject: [PATCH] r300_select_vertex_shader4: Makes the vertex program output from the fragment input. It makes the driver capable of catching output-input mismatches safely. Primarily based on some of Aapo Tahkola's code. --- src/mesa/drivers/dri/r300/r300_context.h | 24 +- src/mesa/drivers/dri/r300/r300_maos.c | 4 +- src/mesa/drivers/dri/r300/r300_shader.c | 17 +- src/mesa/drivers/dri/r300/r300_state.c | 9 +- src/mesa/drivers/dri/r300/r300_vertexprog.c | 328 +++++++++++++++------------- 5 files changed, 215 insertions(+), 167 deletions(-) diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h index df73cde..2c8120e 100644 --- a/src/mesa/drivers/dri/r300/r300_context.h +++ b/src/mesa/drivers/dri/r300/r300_context.h @@ -592,7 +592,8 @@ struct r300_vertex_shader_state { extern int hw_tcl_on; -#define CURRENT_VERTEX_SHADER(ctx) (ctx->VertexProgram._Current) +//#define CURRENT_VERTEX_SHADER(ctx) (ctx->VertexProgram._Current) +#define CURRENT_VERTEX_SHADER(ctx) (R300_CONTEXT(ctx)->selected_vp) /* Should but doesnt work */ //#define CURRENT_VERTEX_SHADER(ctx) (R300_CONTEXT(ctx)->curr_vp) @@ -607,12 +608,18 @@ extern int hw_tcl_on; /* r300_vertex_shader_state and r300_vertex_program should probably be merged together someday. * Keeping them them seperate for now should ensure fixed pipeline keeps functioning properly. */ + +struct r300_vertex_program_key { + GLuint InputsRead; + GLuint OutputsWritten; +}; + struct r300_vertex_program { - struct gl_vertex_program mesa_program; /* Must be first */ + struct r300_vertex_program *next; + struct r300_vertex_program_key key; int translated; struct r300_vertex_shader_fragment program; - struct r300_vertex_shader_fragment params; int pos_end; int num_temporaries; /* Number of temp vars used by program */ @@ -623,6 +630,12 @@ struct r300_vertex_program { int use_ref_count; }; +struct r300_vertex_program_cont { + struct gl_vertex_program mesa_program; /* Must be first */ + struct r300_vertex_shader_fragment params; + struct r300_vertex_program *progs; +}; + #define PFS_MAX_ALU_INST 64 #define PFS_MAX_TEX_INST 64 #define PFS_MAX_TEX_INDIRECT 4 @@ -797,6 +810,7 @@ struct r300_context { struct r300_cmdbuf cmdbuf; struct r300_state state; struct gl_vertex_program *curr_vp; + struct r300_vertex_program *selected_vp; /* Vertex buffers */ @@ -854,9 +868,9 @@ extern GLboolean r300CreateContext(const __GLcontextModes * glVisual, extern int r300_get_num_verts(r300ContextPtr rmesa, int num_verts, int prim); -void r300_translate_vertex_shader(struct r300_vertex_program *vp); +extern void r300_select_vertex_shader(r300ContextPtr r300); extern void r300InitShaderFuncs(struct dd_function_table *functions); -extern int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp, float *dst); +extern int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program_cont *vp, float *dst); extern int r300Fallback(GLcontext *ctx); extern void radeon_vb_to_rvb(r300ContextPtr rmesa, struct radeon_vertex_buffer *rvb, struct vertex_buffer *vb); diff --git a/src/mesa/drivers/dri/r300/r300_maos.c b/src/mesa/drivers/dri/r300/r300_maos.c index 2fdad51..fcb87cb 100644 --- a/src/mesa/drivers/dri/r300/r300_maos.c +++ b/src/mesa/drivers/dri/r300/r300_maos.c @@ -407,8 +407,8 @@ int r300EmitArrays(GLcontext *ctx) if (hw_tcl_on) { struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); inputs = prog->inputs; - InputsRead = CURRENT_VERTEX_SHADER(ctx)->Base.InputsRead; - OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->Base.OutputsWritten; + InputsRead = CURRENT_VERTEX_SHADER(ctx)->key.InputsRead; + OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten; } else { DECLARE_RENDERINPUTS(inputs_bitset); inputs = r300->state.sw_tcl_inputs; diff --git a/src/mesa/drivers/dri/r300/r300_shader.c b/src/mesa/drivers/dri/r300/r300_shader.c index 576b189..26721e8 100644 --- a/src/mesa/drivers/dri/r300/r300_shader.c +++ b/src/mesa/drivers/dri/r300/r300_shader.c @@ -12,13 +12,13 @@ r300BindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog) { r300ContextPtr rmesa = R300_CONTEXT(ctx); - struct r300_vertex_program *vp=(void *)prog; + struct r300_vertex_program_cont *vp=(void *)prog; switch(target){ case GL_VERTEX_PROGRAM_ARB: - rmesa->curr_vp = (struct gl_vertex_program *)vp; - vp->ref_count++; + //rmesa->curr_vp = (struct gl_vertex_program *)vp; + //vp->ref_count++; #if 0 if((vp->ref_count % 1500) == 0) { fprintf(stderr, "id %p, ref_count %d\n", vp, vp->ref_count); @@ -37,13 +37,13 @@ r300BindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog) static struct gl_program * r300NewProgram(GLcontext *ctx, GLenum target, GLuint id) { - struct r300_vertex_program *vp; + struct r300_vertex_program_cont *vp; struct r300_fragment_program *fp; switch(target){ case GL_VERTEX_STATE_PROGRAM_NV: case GL_VERTEX_PROGRAM_ARB: - vp=CALLOC_STRUCT(r300_vertex_program); + vp=CALLOC_STRUCT(r300_vertex_program_cont); return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id); case GL_FRAGMENT_PROGRAM_ARB: fp=CALLOC_STRUCT(r300_fragment_program); @@ -77,13 +77,14 @@ r300DeleteProgram(GLcontext *ctx, struct gl_program *prog) static void r300ProgramStringNotify(GLcontext *ctx, GLenum target, struct gl_program *prog) { - struct r300_vertex_program *vp=(void *)prog; + struct r300_vertex_program_cont *vp=(void *)prog; struct r300_fragment_program *fp = (struct r300_fragment_program *) prog; switch(target) { case GL_VERTEX_PROGRAM_ARB: - vp->translated = GL_FALSE; - memset(&vp->translated, 0, sizeof(struct r300_vertex_program) - sizeof(struct gl_vertex_program)); + vp->progs = NULL; + /*vp->translated = GL_FALSE; + memset(&vp->translated, 0, sizeof(struct r300_vertex_program) - sizeof(struct gl_vertex_program));*/ /*r300_translate_vertex_shader(vp);*/ break; case GL_FRAGMENT_PROGRAM_ARB: diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index b063364..aa49f05 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -1285,7 +1285,7 @@ void r300_setup_rs_unit(GLcontext *ctx) int i; if(hw_tcl_on) - OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->Base.OutputsWritten; + OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten; else RENDERINPUTS_COPY( OutputsWritten.index_bitset, r300->state.render_inputs_bitset ); @@ -1610,7 +1610,7 @@ void r300SetupVertexProgram(r300ContextPtr rmesa) ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0; R300_STATECHANGE(rmesa, vpp); - param_count = r300VertexProgUpdateParams(ctx, prog, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]); + param_count = r300VertexProgUpdateParams(ctx, (struct r300_vertex_program_cont *)ctx->VertexProgram._Current/*prog*/, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]); bump_vpu_count(rmesa->hw.vpp.cmd, param_count); param_count /= 4; @@ -1669,9 +1669,10 @@ void r300UpdateShaders(r300ContextPtr rmesa) TNL_CONTEXT(ctx)->vb.AttribPtr[i] = rmesa->temp_attrib[i]; } + r300_select_vertex_shader(rmesa); vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); - if (vp->translated == GL_FALSE) - r300_translate_vertex_shader(vp); + /*if (vp->translated == GL_FALSE) + r300_translate_vertex_shader(vp);*/ if (vp->translated == GL_FALSE) { fprintf(stderr, "Failing back to sw-tcl\n"); hw_tcl_on = future_hw_tcl_on = 0; diff --git a/src/mesa/drivers/dri/r300/r300_vertexprog.c b/src/mesa/drivers/dri/r300/r300_vertexprog.c index cc932b8..c38db7e 100644 --- a/src/mesa/drivers/dri/r300/r300_vertexprog.c +++ b/src/mesa/drivers/dri/r300/r300_vertexprog.c @@ -95,7 +95,7 @@ static struct{ }; #undef OPN -int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp, float *dst) +int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program_cont *vp, float *dst) { int pi; struct gl_vertex_program *mesa_vp = &vp->mesa_program; @@ -177,17 +177,9 @@ static unsigned long t_dst_class(enum register_file file) static unsigned long t_dst_index(struct r300_vertex_program *vp, struct prog_dst_register *dst) { - if(dst->File == PROGRAM_OUTPUT) { - if (vp->outputs[dst->Index] != -1) - return vp->outputs[dst->Index]; - else { - WARN_ONCE("Unknown output %d\n", dst->Index); - return 10; - } - }else if(dst->File == PROGRAM_ADDRESS) { - assert(dst->Index == 0); - } - + if(dst->File == PROGRAM_OUTPUT) + return vp->outputs[dst->Index]; + return dst->Index; } @@ -335,6 +327,18 @@ static unsigned long op_operands(enum prog_opcode opcode) return 0; } +static GLboolean valid_dst(struct r300_vertex_program *vp, struct prog_dst_register *dst) +{ + if(dst->File == PROGRAM_OUTPUT && vp->outputs[dst->Index] == -1){ + WARN_ONCE("Output %d not used by fragment program\n", dst->Index); + return GL_FALSE; + }else if(dst->File == PROGRAM_ADDRESS) { + assert(dst->Index == 0); + } + + return GL_TRUE; +} + /* TODO: Get rid of t_src_class call */ #define CMP_SRCS(a, b) ((a.RelAddr != b.RelAddr) || (a.Index != b.Index && \ ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \ @@ -384,10 +388,8 @@ static unsigned long op_operands(enum prog_opcode opcode) u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \ } while (0) -void r300_translate_vertex_shader(struct r300_vertex_program *vp) +static void r300_translate_vertex_shader(struct r300_vertex_program *vp, struct prog_instruction *vpi) { - struct gl_vertex_program *mesa_vp= &vp->mesa_program; - struct prog_instruction *vpi; int i, cur_reg=0; VERTEX_SHADER_INSTRUCTION *o_inst; unsigned long operands; @@ -399,131 +401,9 @@ void r300_translate_vertex_shader(struct r300_vertex_program *vp) int u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; struct prog_src_register src[3]; - if (mesa_vp->Base.NumInstructions == 0) - return; - - if (getenv("R300_VP_SAFETY")) { - WARN_ONCE("R300_VP_SAFETY enabled.\n"); - - vpi = malloc((mesa_vp->Base.NumInstructions + VSF_MAX_FRAGMENT_TEMPS) * sizeof(struct prog_instruction)); - memset(vpi, 0, VSF_MAX_FRAGMENT_TEMPS * sizeof(struct prog_instruction)); - - for (i=0; i < VSF_MAX_FRAGMENT_TEMPS; i++) { - vpi[i].Opcode = OPCODE_MOV; - vpi[i].StringPos = 0; - vpi[i].Data = 0; - - vpi[i].DstReg.File = PROGRAM_TEMPORARY; - vpi[i].DstReg.Index = i; - vpi[i].DstReg.WriteMask = WRITEMASK_XYZW; - vpi[i].DstReg.CondMask = COND_TR; - - vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; - vpi[i].SrcReg[0].Index = 0; - vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE); - } - - memcpy(&vpi[i], mesa_vp->Base.Instructions, mesa_vp->Base.NumInstructions * sizeof(struct prog_instruction)); - - free(mesa_vp->Base.Instructions); - - mesa_vp->Base.Instructions = vpi; - - mesa_vp->Base.NumInstructions += VSF_MAX_FRAGMENT_TEMPS; - vpi = &mesa_vp->Base.Instructions[mesa_vp->Base.NumInstructions-1]; - - assert(vpi->Opcode == OPCODE_END); - } - - if (mesa_vp->IsPositionInvariant) { - struct gl_program_parameter_list *paramList; - GLint tokens[6] = { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX }; - -#ifdef PREFER_DP4 - tokens[5] = STATE_MATRIX; -#else - tokens[5] = STATE_MATRIX_TRANSPOSE; -#endif - paramList = mesa_vp->Base.Parameters; - - vpi = malloc((mesa_vp->Base.NumInstructions + 4) * sizeof(struct prog_instruction)); - memset(vpi, 0, 4 * sizeof(struct prog_instruction)); - - for (i=0; i < 4; i++) { - GLint idx; - tokens[3] = tokens[4] = i; - idx = _mesa_add_state_reference(paramList, tokens); -#ifdef PREFER_DP4 - vpi[i].Opcode = OPCODE_DP4; - vpi[i].StringPos = 0; - vpi[i].Data = 0; - - vpi[i].DstReg.File = PROGRAM_OUTPUT; - vpi[i].DstReg.Index = VERT_RESULT_HPOS; - vpi[i].DstReg.WriteMask = 1 << i; - vpi[i].DstReg.CondMask = COND_TR; - - vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; - vpi[i].SrcReg[0].Index = idx; - vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); - - vpi[i].SrcReg[1].File = PROGRAM_INPUT; - vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; - vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); -#else - if (i == 0) - vpi[i].Opcode = OPCODE_MUL; - else - vpi[i].Opcode = OPCODE_MAD; - - vpi[i].StringPos = 0; - vpi[i].Data = 0; - - if (i == 3) - vpi[i].DstReg.File = PROGRAM_OUTPUT; - else - vpi[i].DstReg.File = PROGRAM_TEMPORARY; - vpi[i].DstReg.Index = 0; - vpi[i].DstReg.WriteMask = 0xf; - vpi[i].DstReg.CondMask = COND_TR; - - vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; - vpi[i].SrcReg[0].Index = idx; - vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); - - vpi[i].SrcReg[1].File = PROGRAM_INPUT; - vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; - vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(i, i, i, i); - - if (i > 0) { - vpi[i].SrcReg[2].File = PROGRAM_TEMPORARY; - vpi[i].SrcReg[2].Index = 0; - vpi[i].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); - } -#endif - } - - memcpy(&vpi[i], mesa_vp->Base.Instructions, mesa_vp->Base.NumInstructions * sizeof(struct prog_instruction)); - - free(mesa_vp->Base.Instructions); - - mesa_vp->Base.Instructions = vpi; - - mesa_vp->Base.NumInstructions += 4; - vpi = &mesa_vp->Base.Instructions[mesa_vp->Base.NumInstructions-1]; - - assert(vpi->Opcode == OPCODE_END); - - mesa_vp->Base.InputsRead |= (1 << VERT_ATTRIB_POS); - mesa_vp->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS); - - //fprintf(stderr, "IsPositionInvariant is set!\n"); - //_mesa_print_program(&mesa_vp->Base); - } - vp->pos_end=0; /* Not supported yet */ vp->program.length=0; - vp->num_temporaries=mesa_vp->Base.NumTemporaries; + /*vp->num_temporaries=mesa_vp->Base.NumTemporaries;*/ for(i=0; i < VERT_ATTRIB_MAX; i++) vp->inputs[i] = -1; @@ -531,42 +411,49 @@ void r300_translate_vertex_shader(struct r300_vertex_program *vp) for(i=0; i < VERT_RESULT_MAX; i++) vp->outputs[i] = -1; - assert(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_HPOS)); + assert(vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)); /* Assign outputs */ - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_HPOS)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)) vp->outputs[VERT_RESULT_HPOS] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_PSIZ)) vp->outputs[VERT_RESULT_PSIZ] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_COL0)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_COL0)) vp->outputs[VERT_RESULT_COL0] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_COL1)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_COL1)) vp->outputs[VERT_RESULT_COL1] = cur_reg++; #if 0 /* Not supported yet */ - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_BFC0)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_BFC0)) vp->outputs[VERT_RESULT_BFC0] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_BFC1)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_BFC1)) vp->outputs[VERT_RESULT_BFC1] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_FOGC)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_FOGC)) vp->outputs[VERT_RESULT_FOGC] = cur_reg++; #endif for(i=VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++) - if(mesa_vp->Base.OutputsWritten & (1 << i)) + if(vp->key.OutputsWritten & (1 << i)) vp->outputs[i] = cur_reg++; vp->translated = GL_TRUE; vp->native = GL_TRUE; o_inst=vp->program.body.i; - for(vpi=mesa_vp->Base.Instructions; vpi->Opcode != OPCODE_END; vpi++, o_inst++){ + for(; vpi->Opcode != OPCODE_END; vpi++, o_inst++){ FREE_TEMPS(); + + if(!valid_dst(vp, &vpi->DstReg)) + { + /* redirect result to unused temp */ + vpi->DstReg.File = PROGRAM_TEMPORARY; + vpi->DstReg.Index = u_temp_i; + } operands=op_operands(vpi->Opcode); are_srcs_scalar=operands & SCALAR_FLAG; @@ -987,3 +874,148 @@ void r300_translate_vertex_shader(struct r300_vertex_program *vp) #endif } +static void position_invariant(struct gl_program *prog) +{ + struct prog_instruction *vpi; + struct gl_program_parameter_list *paramList; + int i; + + GLint tokens[6] = { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX }; + +#ifdef PREFER_DP4 + tokens[5] = STATE_MATRIX; +#else + tokens[5] = STATE_MATRIX_TRANSPOSE; +#endif + paramList = prog->Parameters; + + vpi = malloc((prog->NumInstructions + 4) * sizeof(struct prog_instruction)); + memset(vpi, 0, 4 * sizeof(struct prog_instruction)); + + for (i=0; i < 4; i++) { + GLint idx; + tokens[3] = tokens[4] = i; + idx = _mesa_add_state_reference(paramList, tokens); +#ifdef PREFER_DP4 + vpi[i].Opcode = OPCODE_DP4; + vpi[i].StringPos = 0; + vpi[i].Data = 0; + + vpi[i].DstReg.File = PROGRAM_OUTPUT; + vpi[i].DstReg.Index = VERT_RESULT_HPOS; + vpi[i].DstReg.WriteMask = 1 << i; + vpi[i].DstReg.CondMask = COND_TR; + + vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; + vpi[i].SrcReg[0].Index = idx; + vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); + + vpi[i].SrcReg[1].File = PROGRAM_INPUT; + vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; + vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); +#else + if (i == 0) + vpi[i].Opcode = OPCODE_MUL; + else + vpi[i].Opcode = OPCODE_MAD; + + vpi[i].StringPos = 0; + vpi[i].Data = 0; + + if (i == 3) + vpi[i].DstReg.File = PROGRAM_OUTPUT; + else + vpi[i].DstReg.File = PROGRAM_TEMPORARY; + vpi[i].DstReg.Index = 0; + vpi[i].DstReg.WriteMask = 0xf; + vpi[i].DstReg.CondMask = COND_TR; + + vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; + vpi[i].SrcReg[0].Index = idx; + vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); + + vpi[i].SrcReg[1].File = PROGRAM_INPUT; + vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; + vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(i, i, i, i); + + if (i > 0) { + vpi[i].SrcReg[2].File = PROGRAM_TEMPORARY; + vpi[i].SrcReg[2].Index = 0; + vpi[i].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); + } +#endif + } + + memcpy(&vpi[i], prog->Instructions, prog->NumInstructions * sizeof(struct prog_instruction)); + + free(prog->Instructions); + + prog->Instructions = vpi; + + prog->NumInstructions += 4; + vpi = &prog->Instructions[prog->NumInstructions-1]; + + assert(vpi->Opcode == OPCODE_END); +} + +static struct r300_vertex_program *build_program(struct r300_vertex_program_key *wanted_key, + struct gl_vertex_program *mesa_vp) +{ + struct r300_vertex_program *vp; + + vp = _mesa_calloc(sizeof(*vp)); + _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key)); + + if(mesa_vp->IsPositionInvariant) + position_invariant(&mesa_vp->Base); + + assert(mesa_vp->Base.NumInstructions); + + vp->num_temporaries=mesa_vp->Base.NumTemporaries; + + r300_translate_vertex_shader(vp, mesa_vp->Base.Instructions); + + return vp; +} + +void r300_select_vertex_shader(r300ContextPtr r300) +{ + GLcontext *ctx = ctx = r300->radeon.glCtx; + GLuint InputsRead; + struct r300_vertex_program_key wanted_key = { 0 }; + GLint i; + struct r300_vertex_program_cont *vpc; + struct r300_vertex_program *vp; + + vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current; + InputsRead = ctx->FragmentProgram._Current->Base.InputsRead; + + wanted_key.OutputsWritten |= 1 << VERT_RESULT_HPOS; + + if (InputsRead & FRAG_BIT_COL0) + wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL0; + + if ((InputsRead & FRAG_BIT_COL1) /*|| + (InputsRead & FRAG_BIT_FOGC)*/) + wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL1; + + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + if (InputsRead & (FRAG_BIT_TEX0 << i)) + wanted_key.OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i); + + wanted_key.InputsRead = vpc->mesa_program.Base.InputsRead; + + for (vp = vpc->progs; vp; vp = vp->next) + if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key)) == 0) { + r300->selected_vp = vp; + return ; + } + + //_mesa_print_program(&vpc->mesa_program.Base); + + vp = build_program(&wanted_key, &vpc->mesa_program); + vp->next = vpc->progs; + vpc->progs = vp; + + r300->selected_vp = vp; +} -- 2.7.4