Henri Verbeet : wined3d: Dump the GLSL shader source on link failure.

Alexandre Julliard julliard at winehq.org
Fri Jan 29 10:56:32 CST 2010


Module: wine
Branch: master
Commit: 9f21f2c2f20c7ce770030eb99eba86e115739adc
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9f21f2c2f20c7ce770030eb99eba86e115739adc

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Thu Jan 28 23:40:27 2010 +0100

wined3d: Dump the GLSL shader source on link failure.

Mostly to help Mesa developers diagnose bug reports involving GLSL compile
failures, but it's convenient in general to have the source all in one place.

---

 dlls/wined3d/glsl_shader.c |   93 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 1179f51..dc1dc28 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -156,6 +156,20 @@ struct glsl_vshader_private
     UINT                            num_gl_shaders, shader_array_size;
 };
 
+static const char *debug_gl_shader_type(GLenum type)
+{
+    switch (type)
+    {
+#define WINED3D_TO_STR(u) case u: return #u
+        WINED3D_TO_STR(GL_VERTEX_SHADER_ARB);
+        WINED3D_TO_STR(GL_GEOMETRY_SHADER_ARB);
+        WINED3D_TO_STR(GL_FRAGMENT_SHADER_ARB);
+#undef WINED3D_TO_STR
+        default:
+            return wine_dbg_sprintf("UNKNOWN(%#x)", type);
+    }
+}
+
 /* Extract a line from the info log.
  * Note that this modifies the source string. */
 static char *get_info_log_line(char **ptr)
@@ -238,6 +252,81 @@ static void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLhandleA
     }
 }
 
+/* GL locking is done by the caller. */
+static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_info, GLhandleARB program)
+{
+    GLint i, object_count, source_size;
+    GLhandleARB *objects;
+    char *source = NULL;
+
+    GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_ATTACHED_OBJECTS_ARB, &object_count));
+    objects = HeapAlloc(GetProcessHeap(), 0, object_count * sizeof(*objects));
+    if (!objects)
+    {
+        ERR("Failed to allocate object array memory.\n");
+        return;
+    }
+
+    GL_EXTCALL(glGetAttachedObjectsARB(program, object_count, NULL, objects));
+    for (i = 0; i < object_count; ++i)
+    {
+        char *ptr, *line;
+        GLint tmp;
+
+        GL_EXTCALL(glGetObjectParameterivARB(objects[i], GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &tmp));
+
+        if (!source || source_size < tmp)
+        {
+            HeapFree(GetProcessHeap(), 0, source);
+
+            source = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, tmp);
+            if (!source)
+            {
+                ERR("Failed to allocate %d bytes for shader source.\n", tmp);
+                HeapFree(GetProcessHeap(), 0, objects);
+                return;
+            }
+            source_size = tmp;
+        }
+
+        FIXME("Object %u:\n", objects[i]);
+        GL_EXTCALL(glGetObjectParameterivARB(objects[i], GL_OBJECT_SUBTYPE_ARB, &tmp));
+        FIXME("    GL_OBJECT_SUBTYPE_ARB: %s.\n", debug_gl_shader_type(tmp));
+        GL_EXTCALL(glGetObjectParameterivARB(objects[i], GL_OBJECT_COMPILE_STATUS_ARB, &tmp));
+        FIXME("    GL_OBJECT_COMPILE_STATUS_ARB: %d.\n", tmp);
+        FIXME("\n");
+
+        ptr = source;
+        GL_EXTCALL(glGetShaderSourceARB(objects[i], source_size, NULL, source));
+        while ((line = get_info_log_line(&ptr))) FIXME("    %s\n", line);
+        FIXME("\n");
+    }
+
+    HeapFree(GetProcessHeap(), 0, source);
+    HeapFree(GetProcessHeap(), 0, objects);
+}
+
+/* GL locking is done by the caller. */
+static void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLhandleARB program)
+{
+    GLint tmp;
+
+    if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) return;
+
+    GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_TYPE_ARB, &tmp));
+    if (tmp == GL_PROGRAM_OBJECT_ARB)
+    {
+        GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &tmp));
+        if (!tmp)
+        {
+            FIXME("Program %u link status invalid.\n", program);
+            shader_glsl_dump_program_source(gl_info, program);
+        }
+    }
+
+    print_glsl_info_log(gl_info, program);
+}
+
 /**
  * Loads (pixel shader) samplers
  */
@@ -4240,7 +4329,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context,
     /* Link the program */
     TRACE("Linking GLSL shader program %u\n", programId);
     GL_EXTCALL(glLinkProgramARB(programId));
-    print_glsl_info_log(gl_info, programId);
+    shader_glsl_validate_link(gl_info, programId);
 
     entry->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0,
             sizeof(GLhandleARB) * gl_info->limits.glsl_vs_float_constants);
@@ -4396,7 +4485,7 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info,
     GL_EXTCALL(glAttachObjectARB(program_id, pshader_id));
     GL_EXTCALL(glLinkProgramARB(program_id));
 
-    print_glsl_info_log(gl_info, program_id);
+    shader_glsl_validate_link(gl_info, program_id);
 
     /* Once linked we can mark the shaders for deletion. They will be deleted once the program
      * is destroyed




More information about the wine-cvs mailing list