Push parsed shaders through GLSL compiler to see what breaks. trunk
authorRyan C. Gordon <icculus@icculus.org>
Mon, 21 Apr 2008 23:35:49 -0400
branchtrunk
changeset 169 7e9d90724cf8
parent 168 0ff6f6d1e4d1
child 170 9d71c08c756e
Push parsed shaders through GLSL compiler to see what breaks. Multithreading is a real pain.
CMakeLists.txt
finderrors.c
--- a/CMakeLists.txt	Mon Apr 21 04:29:38 2008 -0400
+++ b/CMakeLists.txt	Mon Apr 21 23:35:49 2008 -0400
@@ -8,9 +8,22 @@
 # testparse uses this when I'm looking at memory usage patterns.
 #ADD_DEFINITIONS(-DMOJOSHADER_DEBUG_MALLOC=1)
 
+FIND_PACKAGE(SDL)
+IF(SDL_FOUND)
+    INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR})
+    ADD_DEFINITIONS(-DFINDERRORS_COMPILE_SHADERS=1)
+    IF(APPLE)
+        ADD_DEFINITIONS(-I/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers)
+        FIND_LIBRARY(OPENGL_LIBRARY OpenGL)
+        MARK_AS_ADVANCED(OPENGL_LIBRARY)
+        SET(EXTRA_LIBS ${OPENGL_LIBRARY})
+
+    ENDIF(APPLE)
+ENDIF(SDL_FOUND)
+
 ADD_EXECUTABLE(testparse testparse.c mojoshader.c)
 ADD_EXECUTABLE(finderrors finderrors.c mojoshader.c)
-TARGET_LINK_LIBRARIES(finderrors pthread)
+TARGET_LINK_LIBRARIES(finderrors pthread ${SDL_LIBRARY} ${EXTRA_LIBS})
 
 # End of CMakeLists.txt ...
 
--- a/finderrors.c	Mon Apr 21 04:29:38 2008 -0400
+++ b/finderrors.c	Mon Apr 21 23:35:49 2008 -0400
@@ -6,9 +6,18 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <errno.h>
+#include <unistd.h>
 
 #include "mojoshader.h"
 
+#define FINDERRORS_COMPILE_SHADERS 1
+
+#if FINDERRORS_COMPILE_SHADERS
+#include "SDL.h"
+#include <gl.h>
+#include <glext.h>
+#endif
+
 static const char *profile = NULL;
 static volatile int die_threads = 0;
 static pthread_mutex_t grab_mutex;
@@ -16,11 +25,13 @@
 
 typedef struct ShaderBytecode
 {
-    char *name;
+    void *name;
+    void *data;
     struct ShaderBytecode *next;
 } ShaderBytecode;
 
 static volatile ShaderBytecode *gbytecode = NULL;
+static volatile ShaderBytecode *gparsed = NULL;
 
 static void report(const char *fmt, ...)
 {
@@ -32,6 +43,53 @@
     va_end(ap);
 } // report
 
+
+static int compile_shader(const char *fname, const MOJOSHADER_parseData *pd)
+{
+    int retval = 1;
+
+    #if FINDERRORS_COMPILE_SHADERS
+    const GLenum shader_type = (pd->shader_type == MOJOSHADER_TYPE_PIXEL) ? GL_FRAGMENT_SHADER_ARB : GL_VERTEX_SHADER_ARB;
+    GLint shaderlen = (GLint) pd->output_len;
+    GLhandleARB program = glCreateProgramObjectARB();
+    GLhandleARB shader = glCreateShaderObjectARB(shader_type);
+    GLint ok = 0;
+    GLcharARB err[1024];
+    GLsizei len = 0;
+
+    retval = 0;
+
+    glShaderSourceARB(shader, 1, (const GLcharARB **) &pd->output, &shaderlen);
+    glCompileShaderARB(shader);
+    glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &ok);
+    if (!ok)
+    {
+        glGetInfoLogARB(shader, sizeof (err), &len, err);
+        printf("FAIL: %s glsl compile: %s\n", fname, err);
+    } // if
+    else
+    {
+        glAttachObjectARB(program, shader);
+        glLinkProgramARB(program);
+        glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &ok);
+        if (!ok)
+        {
+            glGetInfoLogARB(program, sizeof (err), &len, err);
+            printf("FAIL: %s glsl link: %s\n", fname, err);
+        } // if
+        else
+        {
+            retval = 1;
+        } // else
+    } // else
+    glDeleteObjectARB(shader);
+    glDeleteObjectARB(program);
+    #endif
+
+    return retval;
+} // compile_shader
+
+
 static void *worker(void *unused)
 {
     unsigned char buf[1024 * 256];
@@ -51,7 +109,7 @@
         if (my_bytecode == NULL)
             break;
 
-        const char *fname = my_bytecode->name;
+        const char *fname = (const char *) my_bytecode->name;
         FILE *io = fopen(fname, "rb");
         if (io == NULL)
             report("FAIL: %s fopen() failed.\n", fname);
@@ -62,19 +120,13 @@
             if (rc == -1)
                 report("FAIL: %s %s\n", fname, strerror(errno));
             else
-            {
-                const MOJOSHADER_parseData *pd;
-                pd = MOJOSHADER_parse(profile, buf, rc, 0, 0, 0);
-                if (pd->error != NULL)
-                    report("FAIL: %s %s\n", fname, pd->error);
-                else
-                    report("PASS: %s\n", fname);
-                MOJOSHADER_freeParseData(pd);
-            } // else
+                my_bytecode->data = (void *) MOJOSHADER_parse(profile, buf, rc, 0, 0, 0);
+
+            pthread_mutex_lock(&grab_mutex);
+            my_bytecode->next = (ShaderBytecode *) gparsed;
+            gparsed = my_bytecode;
+            pthread_mutex_unlock(&grab_mutex);
         } // else
-
-        free(my_bytecode->name);
-        free(my_bytecode);
     } // while
 
     return NULL;
@@ -97,8 +149,9 @@
 
             total++;
             bytecode = (ShaderBytecode *) malloc(sizeof (ShaderBytecode));
-            bytecode->name = (char *) malloc(strlen(dent->d_name) + dirlen);
-            sprintf(bytecode->name, "%s/%s", dname, dent->d_name);
+            bytecode->data = NULL;
+            bytecode->name = malloc(strlen(dent->d_name) + dirlen);
+            sprintf((char *) bytecode->name, "%s/%s", dname, dent->d_name);
             bytecode->next = (ShaderBytecode *) gbytecode;
             gbytecode = bytecode;
         } // while
@@ -124,6 +177,11 @@
         pthread_t workers[MAX_WORKERS];
         int total = 0;
 
+        #if FINDERRORS_COMPILE_SHADERS
+        SDL_Init(SDL_INIT_VIDEO);
+        SDL_SetVideoMode(640, 480, 0, SDL_OPENGL);
+        #endif
+
         pthread_mutex_init(&grab_mutex, NULL);
         pthread_mutex_init(&report_mutex, NULL);
 
@@ -138,11 +196,56 @@
         for (i = 0; i < MAX_WORKERS; i++)
             pthread_create(&workers[i], NULL, worker, NULL);
 
+        while (1)
+        {
+            ShaderBytecode *my_bytecode = NULL;
+            pthread_mutex_lock(&grab_mutex);
+            if (gparsed != NULL)
+            {
+                my_bytecode = (ShaderBytecode *) gparsed;
+                gparsed = gparsed->next;
+            } // if
+            pthread_mutex_unlock(&grab_mutex);
+
+            if (my_bytecode == NULL)
+            {
+                if (gbytecode == NULL)
+                    break;
+                else
+                {
+                    usleep(10000);
+                    continue;
+                } // else
+            } // if
+
+            const MOJOSHADER_parseData *pd = (const MOJOSHADER_parseData *)
+                                                my_bytecode->data;
+            const char *fname = my_bytecode->name;
+            if (pd != NULL)
+            {
+                if (pd->error != NULL)
+                    report("FAIL: %s %s\n", fname, pd->error);
+                else
+                {
+                    if (compile_shader(fname, pd))
+                        report("PASS: %s\n", fname);
+                } // else
+                MOJOSHADER_freeParseData(pd);
+            } // if
+
+            free(my_bytecode->name);
+            free(my_bytecode);
+        } // while
+
         for (i = 0; i < MAX_WORKERS; i++)
             pthread_join(workers[i], NULL);
 
         pthread_mutex_destroy(&report_mutex);
         pthread_mutex_destroy(&grab_mutex);
+
+        #if FINDERRORS_COMPILE_SHADERS
+        SDL_Quit();
+        #endif
     } // else
 
     return 0;