mesa: rework vertex shader output / fragment shader input attribute matching
Before, if a vertex shader's outputs didn't exactly match a fragment shader's inputs we could wind up with invalid TGSI shader declarations. For example: Before patch: DCL OUT[0], POSITION DCL OUT[1], COLOR[1] DCL OUT[2], GENERIC[0] DCL OUT[3], GENERIC[0] <- note duplicate [0] DCL OUT[4], GENERIC[2] After patch: DCL OUT[0], POSITION DCL OUT[1], COLOR[1] DCL OUT[2], GENERIC[0] DCL OUT[3], GENERIC[1] DCL OUT[4], GENERIC[2]
This commit is contained in:
@@ -175,11 +175,12 @@ find_translated_vp(struct st_context *st,
|
|||||||
|
|
||||||
/* See if we need to translate vertex program to TGSI form */
|
/* See if we need to translate vertex program to TGSI form */
|
||||||
if (xvp->serialNo != stvp->serialNo) {
|
if (xvp->serialNo != stvp->serialNo) {
|
||||||
GLuint outAttr, dummySlot;
|
GLuint outAttr;
|
||||||
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;
|
GLbitfield usedGenerics = 0x0;
|
||||||
|
GLbitfield usedOutputSlots = 0x0;
|
||||||
|
|
||||||
/* 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.
|
||||||
@@ -192,10 +193,12 @@ find_translated_vp(struct st_context *st,
|
|||||||
|
|
||||||
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;
|
GLuint slot = 0;
|
||||||
|
xvp->output_to_slot[VERT_RESULT_HPOS] = slot;
|
||||||
xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
|
xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
|
||||||
xvp->output_to_semantic_index[outAttr] = 0;
|
xvp->output_to_semantic_index[outAttr] = 0;
|
||||||
numVpOuts++;
|
numVpOuts++;
|
||||||
|
usedOutputSlots |= (1 << slot);
|
||||||
}
|
}
|
||||||
else if (outputsWritten & (1 << outAttr)) {
|
else if (outputsWritten & (1 << outAttr)) {
|
||||||
/* see if the frag prog wants this vert output */
|
/* see if the frag prog wants this vert output */
|
||||||
@@ -209,6 +212,12 @@ find_translated_vp(struct st_context *st,
|
|||||||
xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
|
xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
|
||||||
xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
|
xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
|
||||||
numVpOuts++;
|
numVpOuts++;
|
||||||
|
usedOutputSlots |= (1 << vpOutSlot);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#if 0 /*debug*/
|
||||||
|
printf("VP output %d not used by FP\n", outAttr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (outAttr == VERT_RESULT_PSIZ)
|
else if (outAttr == VERT_RESULT_PSIZ)
|
||||||
@@ -226,45 +235,49 @@ find_translated_vp(struct st_context *st,
|
|||||||
|
|
||||||
/* must do these last */
|
/* must do these last */
|
||||||
if (emitPntSize) {
|
if (emitPntSize) {
|
||||||
xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++;
|
GLuint slot = numVpOuts++;
|
||||||
|
xvp->output_to_slot[VERT_RESULT_PSIZ] = slot;
|
||||||
xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
|
xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
|
||||||
xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
|
xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
|
||||||
|
usedOutputSlots |= (1 << slot);
|
||||||
}
|
}
|
||||||
if (emitBFC0) {
|
if (emitBFC0) {
|
||||||
xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++;
|
GLuint slot = numVpOuts++;
|
||||||
|
xvp->output_to_slot[VERT_RESULT_BFC0] = slot;
|
||||||
xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
|
xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
|
||||||
xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
|
xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
|
||||||
|
usedOutputSlots |= (1 << slot);
|
||||||
}
|
}
|
||||||
if (emitBFC1) {
|
if (emitBFC1) {
|
||||||
xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++;
|
GLuint slot = numVpOuts++;
|
||||||
|
xvp->output_to_slot[VERT_RESULT_BFC1] = slot;
|
||||||
xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR;
|
xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR;
|
||||||
xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1;
|
xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1;
|
||||||
|
usedOutputSlots |= (1 << slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unneeded vertex program outputs will go to this slot.
|
/* build usedGenerics mask */
|
||||||
* We could use this info to do dead code elimination in the
|
usedGenerics = 0x0;
|
||||||
* vertex program.
|
|
||||||
*/
|
|
||||||
dummySlot = numVpOuts;
|
|
||||||
|
|
||||||
/* find max GENERIC slot index */
|
|
||||||
maxGeneric = -1;
|
|
||||||
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
|
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
|
||||||
if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
|
if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
|
||||||
maxGeneric = MAX2(maxGeneric,
|
usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]);
|
||||||
xvp->output_to_semantic_index[outAttr]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Map vert program outputs that aren't used to the dummy slot
|
/* For each vertex program output that doesn't match up to a fragment
|
||||||
* (and an unused generic attribute slot).
|
* program input, map the vertex program output to a free slot and
|
||||||
|
* free generic attribute.
|
||||||
*/
|
*/
|
||||||
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;
|
GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1;
|
||||||
|
GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1;
|
||||||
|
usedGenerics |= (1 << freeGeneric);
|
||||||
|
usedOutputSlots |= (1 << freeSlot);
|
||||||
|
xvp->output_to_slot[outAttr] = freeSlot;
|
||||||
xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
|
xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
|
||||||
xvp->output_to_semantic_index[outAttr] = maxGeneric + 1;
|
xvp->output_to_semantic_index[outAttr] = freeGeneric;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user