+ }
+
+ 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"
+ ;