mesa: glsl: fix linking of varying vars which are arrays
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 15 Aug 2008 21:00:18 +0000 (15:00 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 15 Aug 2008 21:00:18 +0000 (15:00 -0600)
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_link.c

index db25106..f96c655 100644 (file)
@@ -3727,6 +3727,8 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
       if (dbg) printf("UNIFORM (sz %d) ", totalSize);
    }
    else if (var->type.qualifier == SLANG_QUAL_VARYING) {
+      const GLint totalSize = array_size(size, var->array_len);
+
       /* varyings must be float, vec or mat */
       if (!_slang_type_is_float_vec_mat(var->type.specifier.type) &&
           var->type.specifier.type != SLANG_SPEC_ARRAY) {
@@ -3744,10 +3746,10 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
 
       if (prog) {
          /* user-defined varying */
-         GLint varyingLoc = _mesa_add_varying(prog->Varying, varName, size);
+         GLint varyingLoc = _mesa_add_varying(prog->Varying, varName, totalSize);
          GLuint swizzle = _slang_var_swizzle(size, 0);
          store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
-                                           size, swizzle);
+                                           totalSize, swizzle);
       }
       else {
          /* pre-defined varying, like gl_Color or gl_TexCoord */
index d96380e..e33272e 100644 (file)
 #include "slang_link.h"
 
 
+/**
+ * Record a linking error.
+ */
+static void
+link_error(struct gl_shader_program *shProg, const char *msg)
+{
+   if (shProg->InfoLog) {
+      _mesa_free(shProg->InfoLog);
+   }
+   shProg->InfoLog = _mesa_strdup(msg);
+   shProg->LinkStatus = GL_FALSE;
+}
+
+
 
 /**
  * Linking varying vars involves rearranging varying vars so that the
@@ -52,7 +66,6 @@ static GLboolean
 link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
 {
    GLuint *map, i, firstVarying, newFile;
-   GLbitfield varsWritten, varsRead;
 
    map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint));
    if (!map)
@@ -60,14 +73,13 @@ link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
 
    for (i = 0; i < prog->Varying->NumParameters; i++) {
       /* see if this varying is in the linked varying list */
-      const struct gl_program_parameter *var
-         = prog->Varying->Parameters + i;
-
+      const struct gl_program_parameter *var = prog->Varying->Parameters + i;
       GLint j = _mesa_lookup_parameter_index(shProg->Varying, -1, var->Name);
       if (j >= 0) {
          /* already in list, check size */
          if (var->Size != shProg->Varying->Parameters[j].Size) {
             /* error */
+            link_error(shProg, "mismatched varying variable types");
             return GL_FALSE;
          }
       }
@@ -75,9 +87,19 @@ link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
          /* not already in linked list */
          j = _mesa_add_varying(shProg->Varying, var->Name, var->Size);
       }
-      ASSERT(j >= 0);
 
-      map[i] = j;
+      /* map varying[i] to varying[j].
+       * Note: the loop here takes care of arrays or large (sz>4) vars.
+       */
+      {
+         GLint sz = var->Size;
+         while (sz > 0) {
+            /*printf("Link varying from %d to %d\n", i, j);*/
+            map[i++] = j++;
+            sz -= 4;
+         }
+         i--; /* go back one */
+      }
    }
 
 
@@ -96,9 +118,6 @@ link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
       newFile = PROGRAM_INPUT;
    }
 
-   /* keep track of which varying vars we read and write */
-   varsWritten = varsRead = 0x0;
-
    /* OK, now scan the program/shader instructions looking for varying vars,
     * replacing the old index with the new index.
     */
@@ -109,30 +128,22 @@ link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
       if (inst->DstReg.File == PROGRAM_VARYING) {
          inst->DstReg.File = newFile;
          inst->DstReg.Index = map[ inst->DstReg.Index ] + firstVarying;
-         varsWritten |= (1 << 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;
-            varsRead |= (1 << inst->SrcReg[j].Index);
          }
       }
    }
 
-   if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
-      prog->OutputsWritten |= varsWritten;
-      /*printf("VERT OUTPUTS: 0x%x \n", varsWritten);*/
-   }
-   else {
-      assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
-      prog->InputsRead |= varsRead;
-      /*printf("FRAG INPUTS: 0x%x\n", varsRead);*/
-   }
-
    free(map);
 
+   /* these will get recomputed before linking is completed */
+   prog->InputsRead = 0x0;
+   prog->OutputsWritten = 0x0;
+
    return GL_TRUE;
 }
 
@@ -382,21 +393,6 @@ fragment_program(struct gl_program *prog)
 
 
 /**
- * Record a linking error.
- */
-static void
-link_error(struct gl_shader_program *shProg, const char *msg)
-{
-   if (shProg->InfoLog) {
-      _mesa_free(shProg->InfoLog);
-   }
-   shProg->InfoLog = _mesa_strdup(msg);
-   shProg->LinkStatus = GL_FALSE;
-}
-
-
-
-/**
  * Shader linker.  Currently:
  *
  * 1. The last attached vertex shader and fragment shader are linked.
@@ -478,10 +474,14 @@ _slang_link(GLcontext *ctx,
    }
 
    /* link varying vars */
-   if (shProg->VertexProgram)
-      link_varying_vars(shProg, &shProg->VertexProgram->Base);
-   if (shProg->FragmentProgram)
-      link_varying_vars(shProg, &shProg->FragmentProgram->Base);
+   if (shProg->VertexProgram) {
+      if (!link_varying_vars(shProg, &shProg->VertexProgram->Base))
+         return;
+   }
+   if (shProg->FragmentProgram) {
+      if (!link_varying_vars(shProg, &shProg->FragmentProgram->Base))
+         return;
+   }
 
    /* link uniform vars */
    if (shProg->VertexProgram)