diff options
| author | Brian Paul <brian.paul@tungstengraphics.com> | 2008-09-16 15:50:44 -0600 | 
|---|---|---|
| committer | Brian Paul <brian.paul@tungstengraphics.com> | 2008-09-16 15:50:44 -0600 | 
| commit | e53296c928d80c6627a9551345c160533aa1a19e (patch) | |
| tree | 28816070035898254f694606907d9197a27b2770 /src/mesa | |
| parent | 37607aeaf8b0fd35213635ba1c3743b6e059d48f (diff) | |
mesa: rework GLSL vertex attribute binding
Calls to glBindAttribLocation() should not take effect until the next time
that glLinkProgram() is called.
gl_shader_program::Attributes now just contains user-defined bindings.
gl_shader_program::VertexProgram->Attributes contains the actual/final bindings.
Diffstat (limited to 'src/mesa')
| -rw-r--r-- | src/mesa/main/mtypes.h | 4 | ||||
| -rw-r--r-- | src/mesa/shader/shader_api.c | 62 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_link.c | 139 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_link.h | 8 | 
4 files changed, 110 insertions, 103 deletions
| diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 71a4ca55bc..2fc169493b 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2143,12 +2143,14 @@ struct gl_shader_program     GLuint NumShaders;          /**< number of attached shaders */     struct gl_shader **Shaders; /**< List of attached the shaders */ +   /** User-defined attribute bindings (glBindAttribLocation) */ +   struct gl_program_parameter_list *Attributes; +     /* post-link info: */     struct gl_vertex_program *VertexProgram;     /**< Linked vertex program */     struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */     struct gl_uniform_list *Uniforms;     struct gl_program_parameter_list *Varying; -   struct gl_program_parameter_list *Attributes; /**< Vertex attributes */     GLboolean LinkStatus;   /**< GL_LINK_STATUS */     GLboolean Validated;     GLchar *InfoLog; diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index a86ef56c65..decdec53ed 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -1,6 +1,6 @@  /*   * Mesa 3-D graphics library - * Version:  7.1 + * Version:  7.2   *   * Copyright (C) 2004-2008  Brian Paul   All Rights Reserved.   * @@ -497,10 +497,14 @@ _mesa_get_attrib_location(GLcontext *ctx, GLuint program,     if (!name)        return -1; -   if (shProg->Attributes) { -      GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name); -      if (i >= 0) { -         return shProg->Attributes->Parameters[i].StateIndexes[0]; +   if (shProg->VertexProgram) { +      const struct gl_program_parameter_list *attribs = +         shProg->VertexProgram->Base.Attributes; +      if (attribs) { +         GLint i = _mesa_lookup_parameter_index(attribs, -1, name); +         if (i >= 0) { +            return attribs->Parameters[i].StateIndexes[0]; +         }        }     }     return -1; @@ -513,7 +517,7 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,  {     struct gl_shader_program *shProg;     const GLint size = -1; /* unknown size */ -   GLint i, oldIndex; +   GLint i;     GLenum datatype = GL_FLOAT_VEC4;     shProg = _mesa_lookup_shader_program_err(ctx, program, @@ -536,14 +540,6 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,        return;     } -   if (shProg->LinkStatus) { -      /* get current index/location for the attribute */ -      oldIndex = _mesa_get_attrib_location(ctx, program, name); -   } -   else { -      oldIndex = -1; -   } -     /* this will replace the current value if it's already in the list */     i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);     if (i < 0) { @@ -551,12 +547,10 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,        return;     } -   if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) { -      /* If the index changed, need to search/replace references to that attribute -       * in the vertex program. -       */ -      _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index); -   } +   /* +    * Note that this attribute binding won't go into effect until +    * glLinkProgram is called again. +    */  } @@ -798,24 +792,29 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,                          GLsizei maxLength, GLsizei *length, GLint *size,                          GLenum *type, GLchar *nameOut)  { +   const struct gl_program_parameter_list *attribs = NULL;     struct gl_shader_program *shProg;     shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");     if (!shProg)        return; -   if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) { +   if (shProg->VertexProgram) +      attribs = shProg->VertexProgram->Base.Attributes; + +   if (!attribs || index >= attribs->NumParameters) {        _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");        return;     } -   copy_string(nameOut, maxLength, length, -               shProg->Attributes->Parameters[index].Name); +   copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name); +     if (size) -      *size = shProg->Attributes->Parameters[index].Size -         / sizeof_glsl_type(shProg->Attributes->Parameters[index].DataType); +      *size = attribs->Parameters[index].Size +         / sizeof_glsl_type(attribs->Parameters[index].DataType); +     if (type) -      *type = shProg->Attributes->Parameters[index].DataType; +      *type = attribs->Parameters[index].DataType;  } @@ -937,6 +936,7 @@ static void  _mesa_get_programiv(GLcontext *ctx, GLuint program,                      GLenum pname, GLint *params)  { +   const struct gl_program_parameter_list *attribs;     struct gl_shader_program *shProg        = _mesa_lookup_shader_program(ctx, program); @@ -945,6 +945,11 @@ _mesa_get_programiv(GLcontext *ctx, GLuint program,        return;     } +   if (shProg->VertexProgram) +      attribs = shProg->VertexProgram->Base.Attributes; +   else +      attribs = NULL; +     switch (pname) {     case GL_DELETE_STATUS:        *params = shProg->DeletePending; @@ -962,11 +967,10 @@ _mesa_get_programiv(GLcontext *ctx, GLuint program,        *params = shProg->NumShaders;        break;     case GL_ACTIVE_ATTRIBUTES: -      *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0; +      *params = attribs ? attribs->NumParameters : 0;        break;     case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: -      *params = _mesa_longest_parameter_name(shProg->Attributes, -                                             PROGRAM_INPUT) + 1; +      *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;        break;     case GL_ACTIVE_UNIFORMS:        *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0; diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 57dbfc2388..30035b4fee 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -1,8 +1,8 @@  /*   * Mesa 3-D graphics library - * Version:  6.5.3 + * Version:  7.2   * - * Copyright (C) 2007  Brian Paul   All Rights Reserved. + * Copyright (C) 2008  Brian Paul   All Rights Reserved.   *   * Permission is hereby granted, free of charge, to any person obtaining a   * copy of this software and associated documentation files (the "Software"), @@ -215,74 +215,110 @@ link_uniform_vars(struct gl_shader_program *shProg,   * For example, if the vertex shader declared "attribute vec4 foobar" we'll   * allocate a generic vertex attribute for "foobar" and plug that value into   * the vertex program instructions. + * But if the user called glBindAttributeLocation(), those bindings will + * have priority.   */  static GLboolean  _slang_resolve_attributes(struct gl_shader_program *shProg, -                          struct gl_program *prog) +                          const struct gl_program *origProg, +                          struct gl_program *linkedProg)  { +   GLint attribMap[MAX_VERTEX_ATTRIBS];     GLuint i, j;     GLbitfield usedAttributes; -   assert(prog->Target == GL_VERTEX_PROGRAM_ARB); +   assert(origProg != linkedProg); +   assert(origProg->Target == GL_VERTEX_PROGRAM_ARB); +   assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB);     if (!shProg->Attributes)        shProg->Attributes = _mesa_new_parameter_list(); +   if (linkedProg->Attributes) { +      _mesa_free_parameter_list(linkedProg->Attributes); +   } +   linkedProg->Attributes = _mesa_new_parameter_list(); + +     /* Build a bitmask indicating which attribute indexes have been      * explicitly bound by the user with glBindAttributeLocation().      */     usedAttributes = 0x0;     for (i = 0; i < shProg->Attributes->NumParameters; i++) {        GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0]; -      usedAttributes |= attr; +      usedAttributes |= (1 << attr); +   } + +   /* initialize the generic attribute map entries to -1 */ +   for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) { +      attribMap[i] = -1;     }     /*      * Scan program for generic attribute references      */ -   for (i = 0; i < prog->NumInstructions; i++) { -      struct prog_instruction *inst = prog->Instructions + i; +   for (i = 0; i < linkedProg->NumInstructions; i++) { +      struct prog_instruction *inst = linkedProg->Instructions + i;        for (j = 0; j < 3; j++) {           if (inst->SrcReg[j].File == PROGRAM_INPUT &&               inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) { -            /* this is a generic attrib */ -            const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0; -            const char *name = prog->Attributes->Parameters[k].Name; -            /* See if this attrib name is in the program's attribute list -             * (i.e. was bound by the user). +            /* +             * OK, we've found a generic vertex attribute reference.               */ -            GLint index = _mesa_lookup_parameter_index(shProg->Attributes, -                                                          -1, name); -            GLint attr; -            if (index >= 0) { -               /* found, user must have specified a binding */ -               attr = shProg->Attributes->Parameters[index].StateIndexes[0]; -            } -            else { -               /* Not found, choose our own attribute number. -                * Start at 1 since generic attribute 0 always aliases -                * glVertex/position. +            const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0; + +            GLint attr = attribMap[k]; + +            if (attr < 0) { +               /* Need to figure out attribute mapping now. +                */ +               const char *name = origProg->Attributes->Parameters[k].Name; +               const GLint size = origProg->Attributes->Parameters[k].Size; +               const GLenum type =origProg->Attributes->Parameters[k].DataType; +               GLint index, attr; + +               /* See if there's a user-defined attribute binding for +                * this name.                  */ -               GLint size = prog->Attributes->Parameters[k].Size; -               GLenum datatype = prog->Attributes->Parameters[k].DataType; -               for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) { -                  if (((1 << attr) & usedAttributes) == 0) -                     break; +               index = _mesa_lookup_parameter_index(shProg->Attributes, +                                                    -1, name); +               if (index >= 0) { +                  /* Found a user-defined binding */ +                  attr = shProg->Attributes->Parameters[index].StateIndexes[0];                 } -               if (attr == MAX_VERTEX_ATTRIBS) { -                  /* too many!  XXX record error log */ -                  return GL_FALSE; +               else { +                  /* No user-defined binding, choose our own attribute number. +                   * Start at 1 since generic attribute 0 always aliases +                   * glVertex/position. +                   */ +                  for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) { +                     if (((1 << attr) & usedAttributes) == 0) +                        break; +                  } +                  if (attr == MAX_VERTEX_ATTRIBS) { +                     link_error(shProg, "Too many vertex attributes"); +                     return GL_FALSE; +                  } + +                  /* mark this attribute as used */ +                  usedAttributes |= (1 << attr);                 } -               _mesa_add_attribute(shProg->Attributes, name, size, datatype,attr); -	       /* set the attribute as used */ -	       usedAttributes |= 1<<attr; +               attribMap[k] = attr; + +               /* Save the final name->attrib binding so it can be queried +                * with glGetAttributeLocation(). +                */ +               _mesa_add_attribute(linkedProg->Attributes, name, +                                   size, type, attr);              } +            /* update the instruction's src reg */              inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;           }        }     } +     return GL_TRUE;  } @@ -344,36 +380,6 @@ _slang_update_inputs_outputs(struct gl_program *prog)  } -/** - * Scan a vertex program looking for instances of - * (PROGRAM_INPUT, VERT_ATTRIB_GENERIC0 + oldAttrib) and replace with - * (PROGRAM_INPUT, VERT_ATTRIB_GENERIC0 + newAttrib). - * This is used when the user calls glBindAttribLocation on an already linked - * shader program. - */ -void -_slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib, GLuint newAttrib) -{ -   GLuint i, j; - -   assert(prog->Target == GL_VERTEX_PROGRAM_ARB); - -   for (i = 0; i < prog->NumInstructions; i++) { -      struct prog_instruction *inst = prog->Instructions + i; -      for (j = 0; j < 3; j++) { -         if (inst->SrcReg[j].File == PROGRAM_INPUT) { -            if (inst->SrcReg[j].Index == VERT_ATTRIB_GENERIC0 + oldAttrib) { -               inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + newAttrib; -            } -         } -      } -   } - -   _slang_update_inputs_outputs(prog); -} - - -  /** cast wrapper */  static struct gl_vertex_program *  vertex_program(struct gl_program *prog) @@ -492,9 +498,8 @@ _slang_link(GLcontext *ctx,     /*_mesa_print_uniforms(shProg->Uniforms);*/     if (shProg->VertexProgram) { -      if (!_slang_resolve_attributes(shProg, &shProg->VertexProgram->Base)) { -         /*goto cleanup;*/ -         _mesa_problem(ctx, "_slang_resolve_attributes() failed"); +      if (!_slang_resolve_attributes(shProg, &vertProg->Base, +                                     &shProg->VertexProgram->Base)) {           return;        }     } diff --git a/src/mesa/shader/slang/slang_link.h b/src/mesa/shader/slang/slang_link.h index 8ef8a6b4b3..2b44d20787 100644 --- a/src/mesa/shader/slang/slang_link.h +++ b/src/mesa/shader/slang/slang_link.h @@ -1,8 +1,8 @@  /*   * Mesa 3-D graphics library - * Version:  6.5.3 + * Version:  7.2   * - * Copyright (C) 2007  Brian Paul   All Rights Reserved. + * Copyright (C) 2008  Brian Paul   All Rights Reserved.   *   * Permission is hereby granted, free of charge, to any person obtaining a   * copy of this software and associated documentation files (the "Software"), @@ -32,10 +32,6 @@ extern void  _slang_link(GLcontext *ctx, GLhandleARB h,              struct gl_shader_program *shProg); -extern void -_slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib, -                       GLuint newAttrib); -  #endif | 
