Cache attribute locations for GLSL programs at link time. trunk
authorRyan C. Gordon <icculus@icculus.org>
Sun, 27 Apr 2008 03:47:15 -0400
branchtrunk
changeset 213 73935330a973
parent 212 76eeb43e054c
child 214 a4346bb8608b
Cache attribute locations for GLSL programs at link time.
mojoshader_opengl.c
--- a/mojoshader_opengl.c	Sun Apr 27 03:08:06 2008 -0400
+++ b/mojoshader_opengl.c	Sun Apr 27 03:47:15 2008 -0400
@@ -93,6 +93,12 @@
     GLint location;
 } UniformMap;
 
+typedef struct
+{
+    MOJOSHADER_attribute *attribute;
+    GLint location;
+} AttributeMap;
+
 struct MOJOSHADER_glProgram
 {
     const MOJOSHADER_glShader *vertex;
@@ -100,6 +106,8 @@
     GLhandleARB handle;
     uint32 uniform_count;
     UniformMap uniforms;
+    uint32 attribute_count;
+    AttributeMap attributes;
     uint32 refcount;
 };
 
@@ -248,6 +256,7 @@
             pglDeleteObjectARB(program->handle);
             shader_unref(program->vertex);
             shader_unref(program->fragment);
+            Free(program->attributes);
             Free(program->uniforms);
             Free(program);
         } // else
@@ -278,6 +287,26 @@
 } // lookup_uniforms
 
 
+static void lookup_attributes(MOJOSHADER_glProgram *program)
+{
+    int i;
+    const MOJOSHADER_parseData *pd = program->vertex->parseData;
+    const MOJOSHADER_attributes *a = pd->attributes;
+
+    for (i = 0; i < pd->attribute_count; i++)
+    {
+        const GLint loc = pglGetAttribLocationARB(program->handle, a->name);
+        if (loc != -1)  // maybe the Attribute was optimized out?
+        {
+            AttributeMap *map = &program->attributes[program->attribute_count];
+            map->attribute = &a[i];
+            map->location = loc;
+            program->attribute_count++;
+        } // if
+    } // for
+} // lookup_attributes
+
+
 MOJOSHADER_glProgram *MOJOSHADER_glLinkProgram(MOJOSHADER_glShader *vshader,
                                                MOJOSHADER_glShader *pshader)
 {
@@ -323,6 +352,12 @@
 
     if (vshader != NULL)
     {
+        retval->attributes = (AttributeMap *) Malloc(sizeof (AttributeMap) *
+                                        vshader->parseData->attribute_count);
+        if (retval->attributes == NULL)
+            goto link_program_fail;
+
+        lookup_attributes(retval);
         lookup_uniforms(retval, vshader);
         vshader->refcount++;
     } // if
@@ -338,8 +373,8 @@
 link_program_fail:
     if (retval != NULL)
     {
-        if (retval->uniforms != NULL)
-            Free(retval->uniforms);
+        Free(retval->uniforms);
+        Free(retval->attributes);
         Free(retval);
     } // if