From dac19f17f360b730a0e6d651ef2e5b03c59b9b53 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 18 Feb 2009 14:24:14 -0700 Subject: 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. --- src/mesa/shader/slang/slang_link.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/mesa/shader/slang') diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 99f2cbdcc0..152e97a668 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); -- cgit v1.2.3