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.
This commit is contained in:
Brian Paul
2008-08-18 16:10:01 -06:00
parent 90a1c6e403
commit e3f3e22cf7
4 changed files with 103 additions and 41 deletions

View File

@@ -39,6 +39,7 @@
#include "main/imports.h" #include "main/imports.h"
#include "main/mtypes.h" #include "main/mtypes.h"
#include "main/macros.h"
#include "shader/program.h" #include "shader/program.h"
#include "pipe/p_context.h" #include "pipe/p_context.h"
@@ -71,6 +72,8 @@ struct translated_vertex_program
/** Maps VERT_RESULT_x to slot */ /** Maps VERT_RESULT_x to slot */
GLuint output_to_slot[VERT_RESULT_MAX]; 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 */ /** Pointer to the translated vertex program */
struct st_vertex_program *vp; struct st_vertex_program *vp;
@@ -176,17 +179,22 @@ find_translated_vp(struct st_context *st,
const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten; const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
GLuint numVpOuts = 0; GLuint numVpOuts = 0;
GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE; GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
GLint maxGeneric;
/* Compute mapping of vertex program outputs to slots, which depends /* Compute mapping of vertex program outputs to slots, which depends
* on the fragment program's input->slot mapping. * on the fragment program's input->slot mapping.
*/ */
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
/* set default: */ /* set defaults: */
xvp->output_to_slot[outAttr] = UNUSED; 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) { if (outAttr == VERT_RESULT_HPOS) {
/* always put xformed position into slot zero */ /* always put xformed position into slot zero */
xvp->output_to_slot[VERT_RESULT_HPOS] = 0; 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++; numVpOuts++;
} }
else if (outputsWritten & (1 << outAttr)) { else if (outputsWritten & (1 << outAttr)) {
@@ -195,8 +203,11 @@ find_translated_vp(struct st_context *st,
if (fpInAttrib >= 0) { if (fpInAttrib >= 0) {
GLuint fpInSlot = stfp->input_to_slot[fpInAttrib]; GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
if (fpInSlot != ~0) { if (fpInSlot != ~0) {
/* match this vp output to the fp input */
GLuint vpOutSlot = stfp->input_map[fpInSlot]; GLuint vpOutSlot = stfp->input_map[fpInSlot];
xvp->output_to_slot[outAttr] = vpOutSlot; 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++; numVpOuts++;
} }
} }
@@ -208,19 +219,27 @@ find_translated_vp(struct st_context *st,
emitBFC1 = GL_TRUE; emitBFC1 = GL_TRUE;
} }
#if 0 /*debug*/ #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]); xvp->output_to_slot[outAttr]);
#endif #endif
} }
/* must do these last */ /* must do these last */
if (emitPntSize) if (emitPntSize) {
xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++; 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++; 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_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. /* Unneeded vertex program outputs will go to this slot.
* We could use this info to do dead code elimination in the * 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; 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++) { for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
if (outputsWritten & (1 << 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_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*/ #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]); xvp->output_to_slot[outAttr]);
#endif #endif
@@ -243,7 +281,9 @@ find_translated_vp(struct st_context *st,
assert(stvp->Base.Base.NumInstructions > 1); 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; xvp->vp = stvp;

View File

@@ -294,7 +294,7 @@ st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
} }
stvp = (struct st_vertex_program *) p; 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; st->drawpix.vert_shaders[passColor] = stvp;

View File

@@ -71,15 +71,17 @@ mem_dup(const void *src, uint size)
/** /**
* Translate a Mesa vertex shader into a TGSI shader. * Translate a Mesa vertex shader into a TGSI shader.
* \param outputMapping to map vertex program output registers to TGSI * \param outputMapping to map vertex program output registers (VERT_RESULT_x)
* output slots * to TGSI output slots
* \param tokensOut destination for TGSI tokens * \param tokensOut destination for TGSI tokens
* \return pointer to cached pipe_shader object. * \return pointer to cached pipe_shader object.
*/ */
void void
st_translate_vertex_program(struct st_context *st, st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *stvp, struct st_vertex_program *stvp,
const GLuint outputMapping[]) const GLuint outputMapping[],
const ubyte *outputSemanticName,
const ubyte *outputSemanticIndex)
{ {
struct pipe_context *pipe = st->pipe; struct pipe_context *pipe = st->pipe;
struct tgsi_token tokens[ST_MAX_SHADER_TOKENS]; 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 */ /* initialize output semantics to defaults */
for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
@@ -203,10 +219,6 @@ st_translate_vertex_program(struct st_context *st,
defaultOutputMapping[attr] = slot; defaultOutputMapping[attr] = slot;
} }
/*
printf("Output %u -> slot %u\n", attr, slot);
*/
switch (attr) { switch (attr) {
case VERT_RESULT_HPOS: case VERT_RESULT_HPOS:
assert(slot == 0); assert(slot == 0);
@@ -248,15 +260,21 @@ st_translate_vertex_program(struct st_context *st,
case VERT_RESULT_TEX5: case VERT_RESULT_TEX5:
case VERT_RESULT_TEX6: case VERT_RESULT_TEX6:
case VERT_RESULT_TEX7: case VERT_RESULT_TEX7:
vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; /* fall-through */
vs_output_semantic_index[slot] = num_generic++;
break;
case VERT_RESULT_VAR0: case VERT_RESULT_VAR0:
/* fall-through */ /* fall-through */
default: default:
assert(attr - VERT_RESULT_VAR0 < MAX_VARYING); if (outputSemanticName) {
vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; /* use provided semantic into */
vs_output_semantic_index[slot] = num_generic++; 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_generic = 0;
GLuint num_tokens; 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; uint fs_num_inputs = 0;
ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
@@ -378,23 +394,23 @@ st_translate_fragment_program(struct st_context *st,
switch (attr) { switch (attr) {
case FRAG_ATTRIB_WPOS: case FRAG_ATTRIB_WPOS:
fs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; stfp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
fs_input_semantic_index[slot] = 0; stfp->input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_LINEAR; interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break; break;
case FRAG_ATTRIB_COL0: case FRAG_ATTRIB_COL0:
fs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
fs_input_semantic_index[slot] = 0; stfp->input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_LINEAR; interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break; break;
case FRAG_ATTRIB_COL1: case FRAG_ATTRIB_COL1:
fs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
fs_input_semantic_index[slot] = 1; stfp->input_semantic_index[slot] = 1;
interpMode[slot] = TGSI_INTERPOLATE_LINEAR; interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break; break;
case FRAG_ATTRIB_FOGC: case FRAG_ATTRIB_FOGC:
fs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG; stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
fs_input_semantic_index[slot] = 0; stfp->input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break; break;
case FRAG_ATTRIB_TEX0: case FRAG_ATTRIB_TEX0:
@@ -405,15 +421,15 @@ st_translate_fragment_program(struct st_context *st,
case FRAG_ATTRIB_TEX5: case FRAG_ATTRIB_TEX5:
case FRAG_ATTRIB_TEX6: case FRAG_ATTRIB_TEX6:
case FRAG_ATTRIB_TEX7: case FRAG_ATTRIB_TEX7:
fs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
fs_input_semantic_index[slot] = num_generic++; stfp->input_semantic_index[slot] = num_generic++;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break; break;
case FRAG_ATTRIB_VAR0: case FRAG_ATTRIB_VAR0:
/* fall-through */ /* fall-through */
default: default:
fs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
fs_input_semantic_index[slot] = num_generic++; stfp->input_semantic_index[slot] = num_generic++;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
} }
} }
@@ -467,8 +483,8 @@ st_translate_fragment_program(struct st_context *st,
/* inputs */ /* inputs */
fs_num_inputs, fs_num_inputs,
inputMapping, inputMapping,
fs_input_semantic_name, stfp->input_semantic_name,
fs_input_semantic_index, stfp->input_semantic_index,
interpMode, interpMode,
/* outputs */ /* outputs */
fs_num_outputs, fs_num_outputs,

View File

@@ -58,6 +58,9 @@ struct st_fragment_program
/** map FP input back to VP output */ /** map FP input back to VP output */
GLuint input_map[PIPE_MAX_SHADER_INPUTS]; 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; struct pipe_shader_state state;
void *driver_shader; void *driver_shader;
@@ -143,6 +146,9 @@ st_translate_fragment_program(struct st_context *st,
extern void extern void
st_translate_vertex_program(struct st_context *st, st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *vp, 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 #endif