]> git.cworth.org Git - apitrace/blobdiff - retrace/glstate_shaders.cpp
Use skiplist-based FastCallSet within trace::CallSet
[apitrace] / retrace / glstate_shaders.cpp
index bb0f62dd0787a009805143e7db0e1be6f5ed67f6..aeead3bb5d889afe4483c1b680127b56039224f5 100644 (file)
@@ -24,6 +24,7 @@
  **************************************************************************/
 
 
+#include <assert.h>
 #include <string.h>
 
 #include <algorithm>
@@ -128,7 +129,7 @@ dumpProgram(JSONWriter &json, GLint program)
     glGetAttachedShaders(program, attached_shaders, &count, shaders);
     std::sort(shaders, shaders + count);
     for (GLsizei i = 0; i < count; ++ i) {
-       getShaderSource(shaderMap, shaders[i]);
+        getShaderSource(shaderMap, shaders[i]);
     }
     delete [] shaders;
 
@@ -201,88 +202,223 @@ resolveUniformName(const GLchar *name,  GLint size)
     return qualifiedName;
 }
 
+
 static void
-dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name) {
+dumpUniformValues(JSONWriter &json, GLenum type, const void *values, GLint matrix_stride = 0, GLboolean is_row_major = GL_FALSE) {
     GLenum elemType;
-    GLint numElems;
-    _gl_uniform_size(type, elemType, numElems);
-    if (elemType == GL_NONE) {
-        return;
+    GLint numCols, numRows;
+    _gl_uniform_size(type, elemType, numCols, numRows);
+    if (!numCols || !numRows) {
+        json.writeNull();
     }
 
-    GLfloat fvalues[4*4];
-    GLdouble dvalues[4*4];
-    GLint ivalues[4*4];
-    GLuint uivalues[4*4];
+    size_t elemSize = _gl_type_size(elemType);
 
-    GLint i, j;
-
-    std::string qualifiedName = resolveUniformName(name, size);
+    GLint row_stride = 0;
+    GLint col_stride = 0;
+    if (is_row_major) {
+        row_stride = elemSize;
+        col_stride = matrix_stride ? matrix_stride : numRows * elemSize;
+    } else {
+        col_stride = elemSize;
+        row_stride = matrix_stride ? matrix_stride : numCols * elemSize;
+    }
 
-    for (i = 0; i < size; ++i) {
-        std::stringstream ss;
-        ss << qualifiedName;
+    if (numRows > 1) {
+        json.beginArray();
+    }
 
-        if (size > 1) {
-            ss << '[' << i << ']';
+    for (GLint row = 0; row < numRows; ++row) {
+        if (numCols > 1) {
+            json.beginArray();
         }
 
-        std::string elemName = ss.str();
-
-        json.beginMember(elemName);
+        for (GLint col = 0; col < numCols; ++col) {
+            union {
+                const GLbyte *rawvalue;
+                const GLfloat *fvalue;
+                const GLdouble *dvalue;
+                const GLint *ivalue;
+                const GLuint *uivalue;
+            } u;
 
-        GLint location = glGetUniformLocation(program, elemName.c_str());
-        if (location >= 0) {
-            if (numElems > 1) {
-                json.beginArray();
-            }
+            u.rawvalue = (const GLbyte *)values + row*row_stride + col*col_stride;
 
             switch (elemType) {
             case GL_FLOAT:
-                glGetUniformfv(program, location, fvalues);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeNumber(fvalues[j]);
-                }
+                json.writeFloat(*u.fvalue);
                 break;
             case GL_DOUBLE:
-                glGetUniformdv(program, location, dvalues);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeNumber(dvalues[j]);
-                }
+                json.writeFloat(*u.dvalue);
                 break;
             case GL_INT:
-                glGetUniformiv(program, location, ivalues);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeNumber(ivalues[j]);
-                }
+                json.writeInt(*u.ivalue);
                 break;
             case GL_UNSIGNED_INT:
-                glGetUniformuiv(program, location, uivalues);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeNumber(uivalues[j]);
-                }
+                json.writeInt(*u.uivalue);
                 break;
             case GL_BOOL:
-                glGetUniformiv(program, location, ivalues);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeBool(ivalues[j]);
-                }
+                json.writeBool(*u.uivalue);
                 break;
             default:
                 assert(0);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeNull();
-                }
+                json.writeNull();
                 break;
             }
+        }
+
+        if (numCols > 1) {
+            json.endArray();
+        }
+    }
+
+    if (numRows > 1) {
+        json.endArray();
+    }
+}
+
+
+/**
+ * Dump an uniform that belows to an uniform block.
+ */
+static void
+dumpUniformBlock(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name, GLuint index, GLuint block_index) {
+
+    GLint offset = 0;
+    GLint array_stride = 0;
+    GLint matrix_stride = 0;
+    GLint is_row_major = GL_FALSE;
+    glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_OFFSET, &offset);
+    glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
+    glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
+    glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_IS_ROW_MAJOR, &is_row_major);
+
+    GLint slot = -1;
+    glGetActiveUniformBlockiv(program, block_index, GL_UNIFORM_BLOCK_BINDING, &slot);
+    if (slot == -1) {
+        return;
+    }
+
+    if (0) {
+        GLint active_uniform_block_max_name_length = 0;
+        glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &active_uniform_block_max_name_length);
+
+        GLchar* block_name = new GLchar[active_uniform_block_max_name_length];
+
+        GLint block_data_size = 0;
+        glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_DATA_SIZE, &block_data_size);
+
+        GLsizei length = 0;
+        glGetActiveUniformBlockName(program, index, active_uniform_block_max_name_length, &length, block_name);
+
+        std::cerr
+            << "uniform `" << name << "`, size " << size << ", type " << enumToString(type) << "\n"
+            << "  block " << block_index << ", name `" << block_name << "`, size " << block_data_size << "; binding " << slot << "; \n"
+            << "  offset " << offset << ", array stride " << array_stride << ", matrix stride " << matrix_stride << ", row_major " << is_row_major << "\n"
+        ;
 
-            if (numElems > 1) {
-                json.endArray();
+        delete block_name;
+    }
+
+    GLint ubo = 0;
+    glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, slot, &ubo);
+
+    GLint previous_ubo = 0;
+    glGetIntegerv(GL_UNIFORM_BUFFER_BINDING, &previous_ubo);
+
+    glBindBuffer(GL_UNIFORM_BUFFER, ubo);
+
+    const GLbyte *raw_data = (const GLbyte *)glMapBuffer(GL_UNIFORM_BUFFER, GL_READ_ONLY);
+    if (raw_data) {
+        std::string qualifiedName = resolveUniformName(name, size);
+
+        for (GLint i = 0; i < size; ++i) {
+            std::stringstream ss;
+            ss << qualifiedName;
+
+            if (size > 1) {
+                ss << '[' << i << ']';
             }
-        } else {
-            json.writeNull();
+
+            std::string elemName = ss.str();
+
+            json.beginMember(elemName);
+
+            const GLbyte *row = raw_data + offset + array_stride*i;
+
+            dumpUniformValues(json, type, row, matrix_stride, is_row_major);
+
+            json.endMember();
         }
 
+        glUnmapBuffer(GL_UNIFORM_BUFFER);
+    }
+
+    glBindBuffer(GL_UNIFORM_BUFFER, previous_ubo);
+}
+
+
+static void
+dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name) {
+    GLenum elemType;
+    GLint numCols, numRows;
+    _gl_uniform_size(type, elemType, numCols, numRows);
+    if (elemType == GL_NONE) {
+        return;
+    }
+
+    union {
+        GLfloat fvalues[4*4];
+        GLdouble dvalues[4*4];
+        GLint ivalues[4*4];
+        GLuint uivalues[4*4];
+    } u;
+
+    GLint i;
+
+    std::string qualifiedName = resolveUniformName(name, size);
+
+    for (i = 0; i < size; ++i) {
+        std::stringstream ss;
+        ss << qualifiedName;
+
+        if (size > 1) {
+            ss << '[' << i << ']';
+        }
+
+        std::string elemName = ss.str();
+
+        GLint location = glGetUniformLocation(program, elemName.c_str());
+        assert(location != -1);
+        if (location == -1) {
+            continue;
+        }
+
+        json.beginMember(elemName);
+
+        switch (elemType) {
+        case GL_FLOAT:
+            glGetUniformfv(program, location, u.fvalues);
+            break;
+        case GL_DOUBLE:
+            glGetUniformdv(program, location, u.dvalues);
+            break;
+        case GL_INT:
+            glGetUniformiv(program, location, u.ivalues);
+            break;
+        case GL_UNSIGNED_INT:
+            glGetUniformuiv(program, location, u.uivalues);
+            break;
+        case GL_BOOL:
+            glGetUniformiv(program, location, u.ivalues);
+            break;
+        default:
+            assert(0);
+            break;
+        }
+
+        dumpUniformValues(json, type, &u);
+
         json.endMember();
     }
 }
@@ -290,16 +426,20 @@ dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLch
 
 static void
 dumpUniformARB(JSONWriter &json, GLhandleARB programObj, GLint size, GLenum type, const GLchar *name) {
-
     GLenum elemType;
-    GLint numElems;
-    _gl_uniform_size(type, elemType, numElems);
+    GLint numCols, numRows;
+    _gl_uniform_size(type, elemType, numCols, numRows);
+    GLint numElems = numCols * numRows;
     if (elemType == GL_NONE) {
         return;
     }
 
     GLfloat fvalues[4*4];
-    GLint ivalues[4*4];
+    union {
+        GLdouble dvalues[4*4];
+        GLfloat fvalues[4*4];
+        GLint ivalues[4*4];
+    } u;
 
     GLint i, j;
 
@@ -318,49 +458,36 @@ dumpUniformARB(JSONWriter &json, GLhandleARB programObj, GLint size, GLenum type
         json.beginMember(elemName);
 
         GLint location = glGetUniformLocationARB(programObj, elemName.c_str());
-        if (location >= 0) {
-            if (numElems > 1) {
-                json.beginArray();
-            }
-
-            switch (elemType) {
-            case GL_DOUBLE:
-                // glGetUniformdvARB does not exists
-            case GL_FLOAT:
-                glGetUniformfvARB(programObj, location, fvalues);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeNumber(fvalues[j]);
-                }
-                break;
-            case GL_UNSIGNED_INT:
-                // glGetUniformuivARB does not exists
-            case GL_INT:
-                glGetUniformivARB(programObj, location, ivalues);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeNumber(ivalues[j]);
-                }
-                break;
-            case GL_BOOL:
-                glGetUniformivARB(programObj, location, ivalues);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeBool(ivalues[j]);
-                }
-                break;
-            default:
-                assert(0);
-                for (j = 0; j < numElems; ++j) {
-                    json.writeNull();
-                }
-                break;
-            }
+        if (location == -1) {
+            continue;
+        }
 
-            if (numElems > 1) {
-                json.endArray();
+        switch (elemType) {
+        case GL_DOUBLE:
+            // glGetUniformdvARB does not exists
+            glGetUniformfvARB(programObj, location, fvalues);
+            for (j = 0; j < numElems; ++j) {
+                u.dvalues[j] = fvalues[j];
             }
-        } else {
-            json.writeNull();
+            break;
+        case GL_FLOAT:
+            glGetUniformfvARB(programObj, location, fvalues);
+            break;
+        case GL_UNSIGNED_INT:
+            // glGetUniformuivARB does not exists
+        case GL_INT:
+            glGetUniformivARB(programObj, location, u.ivalues);
+            break;
+        case GL_BOOL:
+            glGetUniformivARB(programObj, location, u.ivalues);
+            break;
+        default:
+            assert(0);
+            break;
         }
 
+        dumpUniformValues(json, type, &u);
+
         json.endMember();
     }
 }
@@ -382,15 +509,30 @@ dumpProgramUniforms(JSONWriter &json, GLint program)
         return;
     }
 
-    for (GLint index = 0; index < active_uniforms; ++index) {
+    for (GLuint index = 0; (GLint)index < active_uniforms; ++index) {
         GLsizei length = 0;
         GLint size = 0;
         GLenum type = GL_NONE;
         glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name);
 
-        if (!isBuiltinUniform(name)) {
+        if (isBuiltinUniform(name)) {
+            continue;
+        }
+
+        GLint location = glGetUniformLocation(program, name);
+        if (location != -1) {
             dumpUniform(json, program, size, type, name);
+            continue;
+        }
+
+        GLint block_index = -1;
+        glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_BLOCK_INDEX, &block_index);
+        if (block_index != -1) {
+            dumpUniformBlock(json, program, size, type, name, index, block_index);
+            continue;
         }
+
+        assert(0);
     }
 
     delete [] name;
@@ -419,9 +561,11 @@ dumpProgramObjUniforms(JSONWriter &json, GLhandleARB programObj)
         GLenum type = GL_NONE;
         glGetActiveUniformARB(programObj, index, active_uniform_max_length, &length, &size, &type, name);
 
-        if (!isBuiltinUniform(name)) {
-            dumpUniformARB(json, programObj, size, type, name);
-        }
+    if (isBuiltinUniform(name)) {
+        continue;
+    }
+
+        dumpUniformARB(json, programObj, size, type, name);
     }
 
     delete [] name;
@@ -482,10 +626,10 @@ dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix)
 
         json.beginMember(name);
         json.beginArray();
-        json.writeNumber(params[0]);
-        json.writeNumber(params[1]);
-        json.writeNumber(params[2]);
-        json.writeNumber(params[3]);
+        json.writeFloat(params[0]);
+        json.writeFloat(params[1]);
+        json.writeFloat(params[2]);
+        json.writeFloat(params[3]);
         json.endArray();
         json.endMember();
     }
@@ -505,30 +649,66 @@ dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix)
 
         json.beginMember(name);
         json.beginArray();
-        json.writeNumber(params[0]);
-        json.writeNumber(params[1]);
-        json.writeNumber(params[2]);
-        json.writeNumber(params[3]);
+        json.writeFloat(params[0]);
+        json.writeFloat(params[1]);
+        json.writeFloat(params[2]);
+        json.writeFloat(params[3]);
         json.endArray();
         json.endMember();
     }
 }
 
+static void
+dumpProgramUniformsStage(JSONWriter &json, GLint program, const char *stage)
+{
+    if (program) {
+        json.beginMember(stage);
+        json.beginObject();
+        dumpProgramUniforms(json, program);
+        json.endObject();
+        json.endMember();
+    }
+}
 
 void
 dumpShadersUniforms(JSONWriter &json, Context &context)
 {
-    GLint program = 0;
-    glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+    GLint pipeline = 0;
+    GLint vertex_program = 0;
+    GLint fragment_program = 0;
+    GLint geometry_program = 0;
+    GLint tess_control_program = 0;
+    GLint tess_evaluation_program = 0;
+
+    if (!context.ES) {
+        glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING, &pipeline);
+        if (pipeline) {
+            glGetProgramPipelineiv(pipeline, GL_VERTEX_SHADER, &vertex_program);
+            glGetProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, &fragment_program);
+            glGetProgramPipelineiv(pipeline, GL_GEOMETRY_SHADER, &geometry_program);
+            glGetProgramPipelineiv(pipeline, GL_TESS_CONTROL_SHADER, &tess_control_program);
+            glGetProgramPipelineiv(pipeline, GL_TESS_EVALUATION_SHADER, &tess_evaluation_program);
+        }
+    }
 
+    GLint program = 0;
     GLhandleARB programObj = 0;
-    if (!context.ES && !program) {
-        programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
+    if (!pipeline) {
+        glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+        if (!context.ES && !program) {
+            programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
+        }
     }
 
     json.beginMember("shaders");
     json.beginObject();
-    if (program) {
+    if (pipeline) {
+        dumpProgram(json, vertex_program);
+        dumpProgram(json, fragment_program);
+        dumpProgram(json, geometry_program);
+        dumpProgram(json, tess_control_program);
+        dumpProgram(json, tess_evaluation_program);
+    } else if (program) {
         dumpProgram(json, program);
     } else if (programObj) {
         dumpProgramObj(json, programObj);
@@ -541,7 +721,13 @@ dumpShadersUniforms(JSONWriter &json, Context &context)
 
     json.beginMember("uniforms");
     json.beginObject();
-    if (program) {
+    if (pipeline) {
+        dumpProgramUniformsStage(json, vertex_program, "GL_VERTEX_SHADER");
+        dumpProgramUniformsStage(json, fragment_program, "GL_FRAGMENT_SHADER");
+        dumpProgramUniformsStage(json, geometry_program, "GL_GEOMETRY_SHADER");
+        dumpProgramUniformsStage(json, tess_control_program, "GL_TESS_CONTROL_SHADER");
+        dumpProgramUniformsStage(json, tess_evaluation_program, "GL_TESS_EVALUATION_SHADER");
+    } else if (program) {
         dumpProgramUniforms(json, program);
     } else if (programObj) {
         dumpProgramObjUniforms(json, programObj);