[Piglit] [PATCH 1/5] shader_runner: Allow uniform setup through a uniform block.

Eric Anholt eric at anholt.net
Thu Jul 26 16:23:44 PDT 2012


---
 tests/shaders/shader_runner.c |  147 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 147 insertions(+)

diff --git a/tests/shaders/shader_runner.c b/tests/shaders/shader_runner.c
index 694f2d2..aa60a62 100644
--- a/tests/shaders/shader_runner.c
+++ b/tests/shaders/shader_runner.c
@@ -60,6 +60,8 @@ GLuint geometry_shaders[256];
 unsigned num_geometry_shaders = 0;
 GLuint fragment_shaders[256];
 unsigned num_fragment_shaders = 0;
+int num_uniform_blocks;
+GLuint *uniform_block_bos;
 
 /**
  * List of strings loaded from files
@@ -742,6 +744,117 @@ check_unsigned_support()
 		piglit_report_result(PIGLIT_SKIP);
 }
 
+/**
+ * Handles uploads of UBO uniforms by mapping the buffer and storing
+ * the data.  If the uniform is not in a uniform block, returns false.
+ */
+bool
+set_ubo_uniform(const char *name, const char *type, const char *line)
+{
+	GLuint uniform_index;
+	GLint block_index;
+	GLint offset;
+	char *data;
+	float f[16];
+	int ints[16];
+	unsigned uints[16];
+	int name_len = strlen(name);
+
+	if (!num_uniform_blocks)
+		return false;
+
+	glGetUniformIndices(prog, 1, &name, &uniform_index);
+	if (uniform_index == GL_INVALID_INDEX) {
+		printf("cannot get index of uniform \"%s\"\n", name);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	glGetActiveUniformsiv(prog, 1, &uniform_index,
+			      GL_UNIFORM_BLOCK_INDEX, &block_index);
+
+	if (block_index == -1)
+		return false;
+
+	glGetActiveUniformsiv(prog, 1, &uniform_index,
+			      GL_UNIFORM_OFFSET, &offset);
+
+	if (name[name_len - 1] == ']') {
+		GLint stride;
+		int i;
+
+		for (i = name_len - 1; (i > 0) && isdigit(name[i-1]); --i)
+			/* empty */;
+
+		glGetActiveUniformsiv(prog, 1, &uniform_index,
+				      GL_UNIFORM_ARRAY_STRIDE, &stride);
+		offset += stride * strtol(&name[i], NULL, 0);
+	}
+
+	glBindBuffer(GL_UNIFORM_BUFFER,
+		     uniform_block_bos[block_index]);
+	data = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
+	data += offset;
+
+	if (string_match("float", type)) {
+		get_floats(line, f, 1);
+		memcpy(data, f, sizeof(float));
+	} else if (string_match("int", type)) {
+		get_ints(line, ints, 1);
+		memcpy(data, ints, sizeof(int));
+	} else if (string_match("uint", type)) {
+		get_uints(line, uints, 1);
+		memcpy(data, uints, sizeof(int));
+	} else if (string_match("vec", type)) {
+		int elements = type[3] - '0';
+		get_floats(line, f, elements);
+		memcpy(data, f, elements * sizeof(float));
+	} else if (string_match("ivec", type)) {
+		int elements = type[4] - '0';
+		get_ints(line, ints, elements);
+		memcpy(data, ints, elements * sizeof(int));
+	} else if (string_match("uvec", type)) {
+		int elements = type[4] - '0';
+		get_uints(line, uints, elements);
+		memcpy(data, uints, elements * sizeof(unsigned));
+	} else if (string_match("mat", type)) {
+		GLint matrix_stride, row_major;
+		int cols = type[3] - '0';
+		int rows = type[4] == 'x' ? type[5] - '0' : cols;
+		int r, c;
+		float *matrixdata = (float *)data;
+
+		assert(cols >= 2 && cols <= 4);
+		assert(rows >= 2 && rows <= 4);
+
+		get_floats(line, f, rows * cols);
+
+		glGetActiveUniformsiv(prog, 1, &uniform_index,
+				      GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
+		glGetActiveUniformsiv(prog, 1, &uniform_index,
+				      GL_UNIFORM_IS_ROW_MAJOR, &row_major);
+
+		matrix_stride /= sizeof(float);
+
+		for (c = 0; c < cols; c++) {
+			for (r = 0; r < rows; r++) {
+				if (row_major) {
+					matrixdata[matrix_stride * c + r] =
+						f[r * rows + c];
+				} else {
+					matrixdata[matrix_stride * r + c] =
+						f[r * rows + c];
+				}
+			}
+		}
+	} else {
+		printf("unknown uniform type \"%s\" for \"%s\"", type, name);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	glUnmapBuffer(GL_UNIFORM_BUFFER);
+
+	return true;
+}
 
 void
 set_uniform(const char *line)
@@ -760,6 +873,10 @@ set_uniform(const char *line)
 	line = eat_text(type);
 
 	line = strcpy_to_space(name, eat_whitespace(line));
+
+	if (set_ubo_uniform(name, type, line))
+		return;
+
 	loc = piglit_GetUniformLocation(prog, name);
 	if (loc < 0) {
 		printf("cannot get location of uniform \"%s\"\n",
@@ -1125,6 +1242,35 @@ handle_texparameter(const char *line)
 	piglit_report_result(PIGLIT_FAIL);
 }
 
+static void
+setup_ubos()
+{
+	int i;
+
+	if (!piglit_is_extension_supported("GL_ARB_uniform_buffer_object") &&
+	    piglit_get_gl_version() < 31) {
+		return;
+	}
+
+	glGetProgramiv(prog, GL_ACTIVE_UNIFORM_BLOCKS, &num_uniform_blocks);
+	if (num_uniform_blocks == 0)
+		return;
+
+	uniform_block_bos = calloc(num_uniform_blocks, sizeof(GLuint));
+	glGenBuffers(num_uniform_blocks, uniform_block_bos);
+
+	for (i = 0; i < num_uniform_blocks; i++) {
+		GLint size;
+
+		glGetActiveUniformBlockiv(prog, i, GL_UNIFORM_BLOCK_DATA_SIZE,
+					  &size);
+
+		glBindBuffer(GL_UNIFORM_BUFFER, uniform_block_bos[i]);
+		glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
+		glBindBufferBase(GL_UNIFORM_BUFFER, i, uniform_block_bos[i]);
+	}
+}
+
 enum piglit_result
 piglit_display(void)
 {
@@ -1443,4 +1589,5 @@ piglit_init(int argc, char **argv)
 	if (vertex_data_start != NULL)
 		num_vbo_rows = setup_vbo_from_text(prog, vertex_data_start,
 						   vertex_data_end);
+	setup_ubos();
 }
-- 
1.7.10.4



More information about the Piglit mailing list