The current GLSL linker puts varyings in slots starting from *_VAR0, leaving the *_TEX slots used only for gl_TexCoord[i].
This results in TGSI programs that start using generic input/outputs with index 10. Unfortunately, some drivers (e.g. pre-nv50 nouveau) support only 8 vertex program outputs, and this causes GLSL to not work at all. On other cards, GLSL works, but 8 varying slots are lost. This patch solves the problem by modifying the GLSL linker to allocate varyings in texcoord slots that neither vertex nor fragment shader uses. Note that the GLSL linker is the only place where this can be done, because it is the only place that sees both the vertex and fragment programs at once. The only known issue is that if the GLSL program has an indirect reference to gl_TexCoord[i], no varyings will be put in texcoord slots. This may or may not be desirable. This makes (a subset of) GLSL work on NV30/NV40 and improves the chances of complex programs working on other cards. Signed-off-by: Luca Barbieri <l...@luca-barbieri.com> --- src/mesa/shader/slang/slang_link.c | 62 ++++++++++++++++++++++++++--------- 1 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index ed27821..889a811 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -99,9 +99,9 @@ bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit) */ static GLboolean link_varying_vars(GLcontext *ctx, - struct gl_shader_program *shProg, struct gl_program *prog) + struct gl_shader_program *shProg, struct gl_program *prog, GLbyte* varying_slots) { - GLuint *map, i, firstVarying, newFile; + GLuint *map, i, firstTex, firstVarying, newFile; GLbitfield *inOutFlags; map = (GLuint *) _mesa_malloc(prog->Varying->NumParameters * sizeof(GLuint)); @@ -114,13 +114,15 @@ link_varying_vars(GLcontext *ctx, * Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT. */ if (prog->Target == GL_VERTEX_PROGRAM_ARB) { - firstVarying = VERT_RESULT_VAR0; + firstTex = VERT_RESULT_TEX0; + firstVarying = VERT_RESULT_VAR0 - 8; newFile = PROGRAM_OUTPUT; inOutFlags = prog->OutputFlags; } else { assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB); - firstVarying = FRAG_ATTRIB_VAR0; + firstTex = FRAG_ATTRIB_TEX0; + firstVarying = FRAG_ATTRIB_VAR0 - 8; newFile = PROGRAM_INPUT; inOutFlags = prog->InputFlags; } @@ -173,9 +175,12 @@ link_varying_vars(GLcontext *ctx, { GLint sz = var->Size; while (sz > 0) { - inOutFlags[firstVarying + j] = var->Flags; + int v = varying_slots[j]; + v += ((v < 8) ? firstTex : firstVarying); + inOutFlags[v] = var->Flags; /*printf("Link varying from %d to %d\n", i, j);*/ - map[i++] = j++; + map[i++] = v; + ++j; sz -= 4; } i--; /* go back one */ @@ -192,13 +197,13 @@ link_varying_vars(GLcontext *ctx, if (inst->DstReg.File == PROGRAM_VARYING) { inst->DstReg.File = newFile; - inst->DstReg.Index = map[ inst->DstReg.Index ] + firstVarying; + inst->DstReg.Index = map[ inst->DstReg.Index ]; } for (j = 0; j < 3; j++) { if (inst->SrcReg[j].File == PROGRAM_VARYING) { inst->SrcReg[j].File = newFile; - inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstVarying; + inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ]; } } } @@ -790,14 +795,39 @@ _slang_link(GLcontext *ctx, ASSERT(shProg->FragmentProgram->Base.RefCount == 1); } - /* link varying vars */ - if (shProg->VertexProgram) { - if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base)) - return; - } - if (shProg->FragmentProgram) { - if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base)) - return; + { + GLuint texcoord_mask = 0; + GLbyte varying_slots[MAX_VARYING]; + GLuint next_varying = 0; + + if(shProg->VertexProgram) + { + _slang_update_inputs_outputs(&shProg->VertexProgram->Base); + texcoord_mask |= (shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_TEX0) & 0xff; + } + if(shProg->FragmentProgram) + { + _slang_update_inputs_outputs(&shProg->FragmentProgram->Base); + texcoord_mask |= (shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_TEX0) & 0xff; + } + + /* Allocate varying slots, excluding slot i if gl_TexCoord[i] is used by the shaders */ + for(i = 0; i < MAX_VARYING; ++i) + { + for(; (1 << next_varying) & texcoord_mask; ++next_varying) + {} + varying_slots[i] = next_varying++; + } + + /* link varying vars */ + if (shProg->VertexProgram) { + if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base, varying_slots)) + return; + } + if (shProg->FragmentProgram) { + if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base, varying_slots)) + return; + } } /* link uniform vars */ -- 1.6.3.3 ------------------------------------------------------------------------------ Throughout its 18-year history, RSA Conference consistently attracts the world's best and brightest in the field, creating opportunities for Conference attendees to learn about information security's most important issues through interactions with peers, luminaries and emerging and established companies. http://p.sf.net/sfu/rsaconf-dev2dev _______________________________________________ Mesa3d-dev mailing list Mesa3d-dev@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mesa3d-dev