+/**
+ * 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 << ']';