From 0f0e6daf84ef2da21a94ff2b9b0185eb2b4500a1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Thu, 10 May 2012 13:18:38 +0100 Subject: [PATCH] Support dumping uniform buffer objects (issue #75). Based on Gregory Hainaut's prototype. --- helpers/glsize.hpp | 98 ++++++----- retrace/glstate_shaders.cpp | 343 +++++++++++++++++++++++++----------- 2 files changed, 300 insertions(+), 141 deletions(-) diff --git a/helpers/glsize.hpp b/helpers/glsize.hpp index 916d979..7efa12e 100644 --- a/helpers/glsize.hpp +++ b/helpers/glsize.hpp @@ -71,159 +71,175 @@ _gl_type_size(GLenum type) } static inline void -_gl_uniform_size(GLenum type, GLenum &elemType, GLint &numElems) { +_gl_uniform_size(GLenum type, GLenum &elemType, GLint &numCols, GLint &numRows) { + numCols = 1; + numRows = 1; + switch (type) { case GL_FLOAT: elemType = GL_FLOAT; - numElems = 1; break; case GL_FLOAT_VEC2: elemType = GL_FLOAT; - numElems = 2; + numCols = 2; break; case GL_FLOAT_VEC3: elemType = GL_FLOAT; - numElems = 3; + numCols = 3; break; case GL_FLOAT_VEC4: elemType = GL_FLOAT; - numElems = 4; + numCols = 4; break; case GL_DOUBLE: elemType = GL_DOUBLE; - numElems = 1; break; case GL_DOUBLE_VEC2: elemType = GL_DOUBLE; - numElems = 2; + numCols = 2; break; case GL_DOUBLE_VEC3: elemType = GL_DOUBLE; - numElems = 3; + numCols = 3; break; case GL_DOUBLE_VEC4: elemType = GL_DOUBLE; - numElems = 4; + numCols = 4; break; case GL_INT: elemType = GL_INT; - numElems = 1; break; case GL_INT_VEC2: elemType = GL_INT; - numElems = 2; + numCols = 2; break; case GL_INT_VEC3: elemType = GL_INT; - numElems = 3; + numCols = 3; break; case GL_INT_VEC4: elemType = GL_INT; - numElems = 4; + numCols = 4; break; case GL_UNSIGNED_INT: elemType = GL_UNSIGNED_INT; - numElems = 1; break; case GL_UNSIGNED_INT_VEC2: elemType = GL_UNSIGNED_INT; - numElems = 2; + numCols = 2; break; case GL_UNSIGNED_INT_VEC3: elemType = GL_UNSIGNED_INT; - numElems = 3; + numCols = 3; break; case GL_UNSIGNED_INT_VEC4: elemType = GL_UNSIGNED_INT; - numElems = 4; + numCols = 4; break; case GL_BOOL: elemType = GL_BOOL; - numElems = 1; break; case GL_BOOL_VEC2: elemType = GL_BOOL; - numElems = 2; + numCols = 2; break; case GL_BOOL_VEC3: elemType = GL_BOOL; - numElems = 3; + numCols = 3; break; case GL_BOOL_VEC4: elemType = GL_BOOL; - numElems = 4; + numCols = 4; break; case GL_FLOAT_MAT2: elemType = GL_FLOAT; - numElems = 2*2; + numCols = 2; + numRows = 2; break; case GL_FLOAT_MAT3: elemType = GL_FLOAT; - numElems = 3*3; + numCols = 3; + numRows = 3; break; case GL_FLOAT_MAT4: elemType = GL_FLOAT; - numElems = 4*4; + numCols = 4; + numRows = 4; break; case GL_FLOAT_MAT2x3: elemType = GL_FLOAT; - numElems = 2*3; + numCols = 2; + numRows = 3; break; case GL_FLOAT_MAT2x4: elemType = GL_FLOAT; - numElems = 2*4; + numCols = 2; + numRows = 4; break; case GL_FLOAT_MAT3x2: elemType = GL_FLOAT; - numElems = 3*2; + numCols = 3; + numRows = 2; break; case GL_FLOAT_MAT3x4: elemType = GL_FLOAT; - numElems = 3*4; + numCols = 3; + numRows = 4; break; case GL_FLOAT_MAT4x2: elemType = GL_FLOAT; - numElems = 4*2; + numCols = 4; + numRows = 2; break; case GL_FLOAT_MAT4x3: elemType = GL_FLOAT; - numElems = 4*3; + numCols = 4; + numRows = 3; break; case GL_DOUBLE_MAT2: elemType = GL_DOUBLE; - numElems = 2*2; + numCols = 2; + numRows = 2; break; case GL_DOUBLE_MAT3: elemType = GL_DOUBLE; - numElems = 3*3; + numCols = 3; + numRows = 3; break; case GL_DOUBLE_MAT4: elemType = GL_DOUBLE; - numElems = 4*4; + numCols = 4; + numRows = 4; break; case GL_DOUBLE_MAT2x3: elemType = GL_DOUBLE; - numElems = 2*3; + numCols = 2; + numRows = 3; break; case GL_DOUBLE_MAT2x4: elemType = GL_DOUBLE; - numElems = 2*4; + numCols = 2; + numRows = 4; break; case GL_DOUBLE_MAT3x2: elemType = GL_DOUBLE; - numElems = 3*2; + numCols = 3; + numRows = 2; break; case GL_DOUBLE_MAT3x4: elemType = GL_DOUBLE; - numElems = 3*4; + numCols = 3; + numRows = 4; break; case GL_DOUBLE_MAT4x2: elemType = GL_DOUBLE; - numElems = 4*2; + numCols = 4; + numRows = 2; break; case GL_DOUBLE_MAT4x3: elemType = GL_DOUBLE; - numElems = 4*3; + numCols = 4; + numRows = 3; break; case GL_SAMPLER_1D: case GL_SAMPLER_2D: @@ -266,12 +282,12 @@ _gl_uniform_size(GLenum type, GLenum &elemType, GLint &numElems) { case GL_UNSIGNED_INT_SAMPLER_BUFFER: case GL_UNSIGNED_INT_SAMPLER_2D_RECT: elemType = GL_INT; - numElems = 1; break; default: os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type); elemType = GL_NONE; - numElems = 0; + numCols = 0; + numRows = 0; return; } } diff --git a/retrace/glstate_shaders.cpp b/retrace/glstate_shaders.cpp index bb0f62d..392dc2b 100644 --- a/retrace/glstate_shaders.cpp +++ b/retrace/glstate_shaders.cpp @@ -201,88 +201,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]; - - GLint i, j; + size_t elemSize = _gl_type_size(elemType); - 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.writeNumber(*u.fvalue); break; case GL_DOUBLE: - glGetUniformdv(program, location, dvalues); - for (j = 0; j < numElems; ++j) { - json.writeNumber(dvalues[j]); - } + json.writeNumber(*u.dvalue); break; case GL_INT: - glGetUniformiv(program, location, ivalues); - for (j = 0; j < numElems; ++j) { - json.writeNumber(ivalues[j]); - } + json.writeNumber(*u.ivalue); break; case GL_UNSIGNED_INT: - glGetUniformuiv(program, location, uivalues); - for (j = 0; j < numElems; ++j) { - json.writeNumber(uivalues[j]); - } + json.writeNumber(*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(); + } +} + - if (numElems > 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" + ; + + 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_BINDING); + } + + 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 +425,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 +457,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 +508,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 +560,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; -- 2.43.0