summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2009-02-18 14:24:14 -0700
committerBrian Paul <[email protected]>2009-02-18 14:28:44 -0700
commitdac19f17f360b730a0e6d651ef2e5b03c59b9b53 (patch)
tree1f78e6d06138398ee5ffe26ed9fe8e88529dde9c
parentbe3813d58adc0060c9f7a13ac7865217b96ea477 (diff)
glsl: fix link failure for variable-indexed varying output arrays
If the vertex shader writes to a varying array with a variable index, mark all the elements of that array as being written. For example, if the vertex shader does: for (i = 0; i < 4; i++) gl_TexCoord[i] = expr; Mark all texcoord outputs as being written, not just the first. Linking will fail if a fragment shader tries to read an input that's not written by the vertex shader. Before this fix, this linker test could fail.
-rw-r--r--src/mesa/shader/slang/slang_link.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index 99f2cbdcc05..152e97a668d 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -495,8 +495,33 @@ _slang_update_inputs_outputs(struct gl_program *prog)
maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1));
}
}
+
if (inst->DstReg.File == PROGRAM_OUTPUT) {
prog->OutputsWritten |= 1 << inst->DstReg.Index;
+ if (inst->DstReg.RelAddr) {
+ /* If the output attribute is indexed with relative addressing
+ * we know that it must be a varying or texcoord such as
+ * gl_TexCoord[i] = v; In this case, mark all the texcoords
+ * or varying outputs as being written. It's not an error if
+ * a vertex shader writes varying vars that aren't used by the
+ * fragment shader. But it is an error for a fragment shader
+ * to use varyings that are not written by the vertex shader.
+ */
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
+ if (inst->DstReg.Index == VERT_RESULT_TEX0) {
+ /* mark all texcoord outputs as written */
+ const GLbitfield mask =
+ ((1 << MAX_TEXTURE_COORD_UNITS) - 1) << VERT_RESULT_TEX0;
+ prog->OutputsWritten |= mask;
+ }
+ else if (inst->DstReg.Index == VERT_RESULT_VAR0) {
+ /* mark all generic varying outputs as written */
+ const GLbitfield mask =
+ ((1 << MAX_VARYING) - 1) << VERT_RESULT_VAR0;
+ prog->OutputsWritten |= mask;
+ }
+ }
+ }
}
else if (inst->DstReg.File == PROGRAM_ADDRESS) {
maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);