From e3f3e22cf7e9af4c5416d37329b7b8ee50f0cfcb Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 18 Aug 2008 16:10:01 -0600 Subject: gallium: fix vertex program output translation/mapping bug In some cases, the vertex program output's semantic info didn't match up with the fragment program's input semantic info. This info is now explicitly passed into the st_translate_fragment_program() function. --- src/mesa/state_tracker/st_atom_shader.c | 60 ++++++++++++++++++++----- src/mesa/state_tracker/st_cb_drawpixels.c | 2 +- src/mesa/state_tracker/st_program.c | 74 +++++++++++++++++++------------ src/mesa/state_tracker/st_program.h | 8 +++- 4 files changed, 103 insertions(+), 41 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 4fa304ede0..6594e59e94 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -39,6 +39,7 @@ #include "main/imports.h" #include "main/mtypes.h" +#include "main/macros.h" #include "shader/program.h" #include "pipe/p_context.h" @@ -71,6 +72,8 @@ struct translated_vertex_program /** Maps VERT_RESULT_x to slot */ GLuint output_to_slot[VERT_RESULT_MAX]; + ubyte output_to_semantic_name[VERT_RESULT_MAX]; + ubyte output_to_semantic_index[VERT_RESULT_MAX]; /** Pointer to the translated vertex program */ struct st_vertex_program *vp; @@ -176,17 +179,22 @@ find_translated_vp(struct st_context *st, const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten; GLuint numVpOuts = 0; GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE; + GLint maxGeneric; /* Compute mapping of vertex program outputs to slots, which depends * on the fragment program's input->slot mapping. */ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { - /* set default: */ + /* set defaults: */ xvp->output_to_slot[outAttr] = UNUSED; + xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT; + xvp->output_to_semantic_index[outAttr] = 99; if (outAttr == VERT_RESULT_HPOS) { /* always put xformed position into slot zero */ xvp->output_to_slot[VERT_RESULT_HPOS] = 0; + xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION; + xvp->output_to_semantic_index[outAttr] = 0; numVpOuts++; } else if (outputsWritten & (1 << outAttr)) { @@ -195,8 +203,11 @@ find_translated_vp(struct st_context *st, if (fpInAttrib >= 0) { GLuint fpInSlot = stfp->input_to_slot[fpInAttrib]; if (fpInSlot != ~0) { + /* match this vp output to the fp input */ GLuint vpOutSlot = stfp->input_map[fpInSlot]; xvp->output_to_slot[outAttr] = vpOutSlot; + xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot]; + xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot]; numVpOuts++; } } @@ -208,19 +219,27 @@ find_translated_vp(struct st_context *st, emitBFC1 = GL_TRUE; } #if 0 /*debug*/ - printf("assign output_to_slot[%d] = %d\n", outAttr, + printf("assign vp output_to_slot[%d] = %d\n", outAttr, xvp->output_to_slot[outAttr]); #endif } /* must do these last */ - if (emitPntSize) + if (emitPntSize) { xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++; - if (emitBFC0) + xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE; + xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0; + } + if (emitBFC0) { xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++; - if (emitBFC1) + xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; + xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0; + } + if (emitBFC1) { xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++; - + xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; + xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1; + } /* Unneeded vertex program outputs will go to this slot. * We could use this info to do dead code elimination in the @@ -228,14 +247,33 @@ find_translated_vp(struct st_context *st, */ dummySlot = numVpOuts; - /* Map vert program outputs that aren't used to the dummy slot */ + /* find max GENERIC slot index */ + maxGeneric = -1; + for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { + if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) { + maxGeneric = MAX2(maxGeneric, + xvp->output_to_semantic_index[outAttr]); + } + } + + /* Map vert program outputs that aren't used to the dummy slot + * (and an unused generic attribute slot). + */ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { if (outputsWritten & (1 << outAttr)) { - if (xvp->output_to_slot[outAttr] == UNUSED) + if (xvp->output_to_slot[outAttr] == UNUSED) { xvp->output_to_slot[outAttr] = dummySlot; + xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC; + xvp->output_to_semantic_index[outAttr] = maxGeneric + 1; + } + + assert(xvp->output_to_semantic_name[outAttr] != TGSI_SEMANTIC_COUNT); + assert(xvp->output_to_semantic_index[outAttr] != 99); } + + #if 0 /*debug*/ - printf("output_to_slot[%d] = %d\n", outAttr, + printf("vp output_to_slot[%d] = %d\n", outAttr, xvp->output_to_slot[outAttr]); #endif @@ -243,7 +281,9 @@ find_translated_vp(struct st_context *st, assert(stvp->Base.Base.NumInstructions > 1); - st_translate_vertex_program(st, stvp, xvp->output_to_slot); + st_translate_vertex_program(st, stvp, xvp->output_to_slot, + xvp->output_to_semantic_name, + xvp->output_to_semantic_index); xvp->vp = stvp; diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index db0c9fbd09..0c5e21d4ff 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -294,7 +294,7 @@ st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor) } stvp = (struct st_vertex_program *) p; - st_translate_vertex_program(st, stvp, NULL); + st_translate_vertex_program(st, stvp, NULL, NULL, NULL); st->drawpix.vert_shaders[passColor] = stvp; diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 59314a3232..325d95e865 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -71,15 +71,17 @@ mem_dup(const void *src, uint size) /** * Translate a Mesa vertex shader into a TGSI shader. - * \param outputMapping to map vertex program output registers to TGSI - * output slots + * \param outputMapping to map vertex program output registers (VERT_RESULT_x) + * to TGSI output slots * \param tokensOut destination for TGSI tokens * \return pointer to cached pipe_shader object. */ void st_translate_vertex_program(struct st_context *st, struct st_vertex_program *stvp, - const GLuint outputMapping[]) + const GLuint outputMapping[], + const ubyte *outputSemanticName, + const ubyte *outputSemanticIndex) { struct pipe_context *pipe = st->pipe; struct tgsi_token tokens[ST_MAX_SHADER_TOKENS]; @@ -172,6 +174,20 @@ st_translate_vertex_program(struct st_context *st, } } +#if 0 + if (outputMapping && outputSemanticName) { + printf("VERT_RESULT written out_slot semantic_name semantic_index\n"); + for (attr = 0; attr < VERT_RESULT_MAX; attr++) { + printf(" %-2d %c %3d %2d %2d\n", + attr, + ((stvp->Base.Base.OutputsWritten & (1 << attr)) ? 'Y' : ' '), + outputMapping[attr], + outputSemanticName[attr], + outputSemanticIndex[attr]); + } + } +#endif + /* initialize output semantics to defaults */ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; @@ -203,10 +219,6 @@ st_translate_vertex_program(struct st_context *st, defaultOutputMapping[attr] = slot; } - /* - printf("Output %u -> slot %u\n", attr, slot); - */ - switch (attr) { case VERT_RESULT_HPOS: assert(slot == 0); @@ -248,15 +260,21 @@ st_translate_vertex_program(struct st_context *st, case VERT_RESULT_TEX5: case VERT_RESULT_TEX6: case VERT_RESULT_TEX7: - vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - vs_output_semantic_index[slot] = num_generic++; - break; + /* fall-through */ case VERT_RESULT_VAR0: /* fall-through */ default: - assert(attr - VERT_RESULT_VAR0 < MAX_VARYING); - vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - vs_output_semantic_index[slot] = num_generic++; + if (outputSemanticName) { + /* use provided semantic into */ + assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT); + vs_output_semantic_name[slot] = outputSemanticName[attr]; + vs_output_semantic_index[slot] = outputSemanticIndex[attr]; + } + else { + /* use default semantic info */ + vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + vs_output_semantic_index[slot] = num_generic++; + } } } } @@ -347,8 +365,6 @@ st_translate_fragment_program(struct st_context *st, GLuint num_generic = 0; GLuint num_tokens; - ubyte fs_input_semantic_name[PIPE_MAX_SHADER_INPUTS]; - ubyte fs_input_semantic_index[PIPE_MAX_SHADER_INPUTS]; uint fs_num_inputs = 0; ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; @@ -378,23 +394,23 @@ st_translate_fragment_program(struct st_context *st, switch (attr) { case FRAG_ATTRIB_WPOS: - fs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; - fs_input_semantic_index[slot] = 0; + stfp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; + stfp->input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; case FRAG_ATTRIB_COL0: - fs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - fs_input_semantic_index[slot] = 0; + stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + stfp->input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; case FRAG_ATTRIB_COL1: - fs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - fs_input_semantic_index[slot] = 1; + stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + stfp->input_semantic_index[slot] = 1; interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; case FRAG_ATTRIB_FOGC: - fs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG; - fs_input_semantic_index[slot] = 0; + stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; + stfp->input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; case FRAG_ATTRIB_TEX0: @@ -405,15 +421,15 @@ st_translate_fragment_program(struct st_context *st, case FRAG_ATTRIB_TEX5: case FRAG_ATTRIB_TEX6: case FRAG_ATTRIB_TEX7: - fs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - fs_input_semantic_index[slot] = num_generic++; + stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + stfp->input_semantic_index[slot] = num_generic++; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; case FRAG_ATTRIB_VAR0: /* fall-through */ default: - fs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - fs_input_semantic_index[slot] = num_generic++; + stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + stfp->input_semantic_index[slot] = num_generic++; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; } } @@ -467,8 +483,8 @@ st_translate_fragment_program(struct st_context *st, /* inputs */ fs_num_inputs, inputMapping, - fs_input_semantic_name, - fs_input_semantic_index, + stfp->input_semantic_name, + stfp->input_semantic_index, interpMode, /* outputs */ fs_num_outputs, diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 086e9391aa..078e2c42a6 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -58,6 +58,9 @@ struct st_fragment_program /** map FP input back to VP output */ GLuint input_map[PIPE_MAX_SHADER_INPUTS]; + ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; + ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; + struct pipe_shader_state state; void *driver_shader; @@ -143,6 +146,9 @@ st_translate_fragment_program(struct st_context *st, extern void st_translate_vertex_program(struct st_context *st, struct st_vertex_program *vp, - const GLuint vert_output_to_slot[]); + const GLuint vert_output_to_slot[], + const ubyte *fs_input_semantic_name, + const ubyte *fs_input_semantic_index); + #endif -- cgit v1.2.3