OpenSubdiv: More graceful handling of shader compile/linking errors
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 9 Sep 2015 12:27:08 +0000 (17:27 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 9 Sep 2015 12:27:08 +0000 (17:27 +0500)
intern/opensubdiv/opensubdiv_capi.h
intern/opensubdiv/opensubdiv_gpu_capi.cc

index 0103952ec0c0ba1499f2b690eb8b437dd9bf6c16..ef6db92b1e8fe6a6378dd9c1a017a10b5722b223 100644 (file)
@@ -85,7 +85,7 @@ const struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_getGLMeshTopologyRefine
         OpenSubdiv_GLMesh *gl_mesh);
 
 /* ** Initialize/Deinitialize global OpenGL drawing buffers/GLSL programs ** */
-void openSubdiv_osdGLDisplayInit(void);
+bool openSubdiv_osdGLDisplayInit(void);
 void openSubdiv_osdGLDisplayDeinit(void);
 
 /* ** Evaluator API ** */
index f80ecce00a8c4e7fc69d78700adf7bca171ab6bf..31996a1bab81708a0ebfecf6540a229f406d7846 100644 (file)
@@ -214,7 +214,7 @@ GLuint compileShader(GLenum shaderType,
                fprintf(stderr, "Section: %s\n", sdefine);
                fprintf(stderr, "Defines: %s\n", define);
                fprintf(stderr, "Source: %s\n", sources[2]);
-               exit(1);
+               return 0;
        }
 
        return shader;
@@ -225,12 +225,21 @@ GLuint linkProgram(const char *define)
        GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
                                            "VERTEX_SHADER",
                                            define);
+       if (vertexShader == 0) {
+               return 0;
+       }
        GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
                                              "GEOMETRY_SHADER",
                                              define);
+       if (geometryShader == 0) {
+               return 0;
+       }
        GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
                                              "FRAGMENT_SHADER",
                                              define);
+       if (fragmentShader == 0) {
+               return 0;
+       }
 
        GLuint program = glCreateProgram();
 
@@ -279,7 +288,8 @@ GLuint linkProgram(const char *define)
                glGetProgramInfoLog(program, sizeof(emsg), 0, emsg);
                fprintf(stderr, "Error linking GLSL program : %s\n", emsg);
                fprintf(stderr, "Defines: %s\n", define);
-               exit(1);
+               glDeleteProgram(program);
+               return 0;
        }
 
        glUniformBlockBinding(program,
@@ -363,9 +373,10 @@ void bindProgram(GLMeshInterface * /*mesh*/,
 
 }  /* namespace */
 
-void openSubdiv_osdGLDisplayInit(void)
+bool openSubdiv_osdGLDisplayInit(void)
 {
        static bool need_init = true;
+       static bool init_success = false;
        if (need_init) {
                g_flat_fill_solid_program = linkProgram("#define FLAT_SHADING\n");
                g_flat_fill_texture2d_program = linkProgram("#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
@@ -379,7 +390,13 @@ void openSubdiv_osdGLDisplayInit(void)
                             sizeof(g_lighting_data), NULL, GL_STATIC_DRAW);
 
                need_init = false;
+               init_success = g_flat_fill_solid_program != 0 &&
+                              g_flat_fill_texture2d_program != 0 &&
+                              g_smooth_fill_solid_program != 0 &&
+                              g_smooth_fill_texture2d_program != 0 &&
+                              g_wireframe_program;
        }
+       return init_success;
 }
 
 void openSubdiv_osdGLDisplayDeinit(void)
@@ -635,7 +652,9 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
                (GLMeshInterface *)(gl_mesh->descriptor);
 
        /* Make sure all global invariants are initialized. */
-       openSubdiv_osdGLDisplayInit();
+       if (!openSubdiv_osdGLDisplayInit()) {
+               return;
+       }
 
        /* Setup GLSL/OpenGL to draw patches in current context. */
        GLuint program = preapre_patchDraw(mesh, fill_quads != 0);