[Piglit] [PATCH 1/2] shader_runner: add ARB_shader_subroutine support (v3)

Dave Airlie airlied at gmail.com
Thu Apr 23 17:36:54 PDT 2015


From: Dave Airlie <airlied at redhat.com>

This adds basic support for executing shader subroutine tests.

it comes with two intro tests, and probably a lot of bugs.

tested against NVIDIA, for some reason -auto fails here.

v2: add support for other shader types (Ilia)
v2.1: fix printf
v3: rework code to query num subroutine locations,
and calloc them, also check for the extension.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 tests/shaders/shader_runner.c | 156 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 156 insertions(+)

diff --git a/tests/shaders/shader_runner.c b/tests/shaders/shader_runner.c
index 0a28eeb..b64b213 100644
--- a/tests/shaders/shader_runner.c
+++ b/tests/shaders/shader_runner.c
@@ -113,6 +113,9 @@ GLenum geometry_layout_output_type = GL_TRIANGLE_STRIP;
 GLint geometry_layout_vertices_out = 0;
 GLuint atomics_bo = 0;
 
+#define SHADER_TYPES 6
+static GLuint *subuniform_locations[SHADER_TYPES];
+static int num_subuniform_locations[SHADER_TYPES];
 char *shader_string;
 GLint shader_string_size;
 const char *vertex_data_start = NULL;
@@ -1241,6 +1244,17 @@ check_double_support(void)
 }
 
 /**
+ * Check that the GL implementation supports shader subroutines
+ * If not, terminate the test with a SKIP.
+ */
+void
+check_shader_subroutine_support(void)
+{
+	if (gl_version.num < 40 && !piglit_is_extension_supported("GL_ARB_shader_subroutine"))
+		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.
  */
@@ -1642,6 +1656,140 @@ set_uniform(const char *line, int ubo_array_index)
 	return;
 }
 
+static GLenum lookup_shader_type(GLuint idx)
+{
+	switch (idx) {
+	case 0:
+		return GL_VERTEX_SHADER;
+	case 1:
+		return GL_FRAGMENT_SHADER;
+	case 2:
+		return GL_GEOMETRY_SHADER;
+	case 3:
+		return GL_TESS_CONTROL_SHADER;
+	case 4:
+		return GL_TESS_EVALUATION_SHADER;
+	case 5:
+		return GL_COMPUTE_SHADER;
+	default:
+		return 0;
+	}
+}
+
+static GLenum get_shader_from_string(const char *name, int *idx)
+{
+	if (string_match("GL_VERTEX_SHADER", name)) {
+		*idx = 0;
+		return GL_VERTEX_SHADER;
+	}
+	if (string_match("GL_FRAGMENT_SHADER", name)) {
+		*idx = 1;
+		return GL_FRAGMENT_SHADER;
+	}
+	if (string_match("GL_GEOMETRY_SHADER", name)) {
+		*idx = 2;
+		return GL_GEOMETRY_SHADER;
+	}
+	if (string_match("GL_TESS_CONTROL_SHADER", name)) {
+		*idx = 3;
+		return GL_TESS_CONTROL_SHADER;
+	}
+	if (string_match("GL_TESS_EVALUATION_SHADER", name)) {
+		*idx = 4;
+		return GL_TESS_EVALUATION_SHADER;
+	}
+	if (string_match("GL_COMPUTE_SHADER", name)) {
+		*idx = 5;
+		return GL_COMPUTE_SHADER;
+	}
+	return 0;
+}
+
+void
+free_subroutine_uniforms(void)
+{
+	int sidx;
+	for (sidx = 0; sidx < 4; sidx++)
+	    free(subuniform_locations[sidx]);
+}
+
+void
+program_subroutine_uniforms(void)
+{
+ 	int sidx;
+	int stype;
+
+	for (sidx = 0; sidx < 4; sidx++) {
+
+		if (num_subuniform_locations[sidx] == 0)
+			continue;
+
+		stype = lookup_shader_type(sidx);
+		if (!stype)
+			continue;
+
+		glUniformSubroutinesuiv(stype, num_subuniform_locations[sidx], subuniform_locations[sidx]);
+	}
+}
+
+void
+set_subroutine_uniform(const char *line)
+{
+	GLuint prog;
+	char name[512];
+	char subname[512];
+	const char *type;
+	GLint loc;
+	GLuint idx;
+	GLenum ptype = 0;
+	int sidx = 0;
+
+	type = eat_whitespace(line);
+	line = eat_text(type);
+
+	line = strcpy_to_space(name, eat_whitespace(line));
+	line = strcpy_to_space(subname, eat_whitespace(line));
+
+	ptype = get_shader_from_string(type, &sidx);
+	if (ptype == 0) {
+		printf("illegal type in subroutine uniform\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
+
+	if (num_subuniform_locations[sidx] == 0) {
+		glGetProgramStageiv(prog, ptype, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
+				    &num_subuniform_locations[sidx]);
+
+		if (num_subuniform_locations[sidx] == 0) {
+			printf("illegal subroutine uniform specified\n");
+			piglit_report_result(PIGLIT_FAIL);
+		}
+
+		subuniform_locations[sidx] = calloc(num_subuniform_locations[sidx], sizeof(GLuint));
+		if (!subuniform_locations[sidx])
+			piglit_report_result(PIGLIT_FAIL);
+	}
+
+	loc = glGetSubroutineUniformLocation(prog, ptype, name);
+	if (loc < 0) {
+		printf("cannot get location of subroutine uniform \"%s\"\n",
+		       name);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	idx = glGetSubroutineIndex(prog, ptype, subname);
+	if (idx == GL_INVALID_INDEX) {
+		printf("cannot get index of subroutine uniform \"%s\"\n",
+		       subname);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	subuniform_locations[sidx][loc] = idx;
+	return;
+}
+
 /**
  * Query a uniform using glGetActiveUniformsiv
  *
@@ -2300,11 +2448,13 @@ piglit_display(void)
 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
 		} else if (string_match("draw rect tex", line)) {
 			program_must_be_in_use();
+			program_subroutine_uniforms();
 			get_floats(line + 13, c, 8);
 			piglit_draw_rect_tex(c[0], c[1], c[2], c[3],
 					     c[4], c[5], c[6], c[7]);
 		} else if (string_match("draw rect ortho", line)) {
 			program_must_be_in_use();
+			program_subroutine_uniforms();
 			get_floats(line + 15, c, 4);
 
 			piglit_draw_rect(-1.0 + 2.0 * (c[0] / piglit_width),
@@ -2313,6 +2463,7 @@ piglit_display(void)
 					 2.0 * (c[3] / piglit_height));
 		} else if (string_match("draw rect", line)) {
 			program_must_be_in_use();
+			program_subroutine_uniforms();
 			get_floats(line + 9, c, 4);
 			piglit_draw_rect(c[0], c[1], c[2], c[3]);
 		} else if (string_match("draw instanced rect", line)) {
@@ -2630,6 +2781,10 @@ piglit_display(void)
 		} else if (string_match("uniform", line)) {
 			program_must_be_in_use();
 			set_uniform(line + 7, ubo_array_index);
+		} else if (string_match("subuniform", line)) {
+			program_must_be_in_use();
+			check_shader_subroutine_support();
+			set_subroutine_uniform(line + 10);
 		} else if (string_match("parameter ", line)) {
 			set_parameter(line + strlen("parameter "));
 		} else if (string_match("patch parameter ", line)) {
@@ -2666,6 +2821,7 @@ piglit_display(void)
 	piglit_present_results();
 
 	if (piglit_automatic) {
+	        free_subroutine_uniforms();
 		/* Free our resources, useful for valgrinding. */
 		glDeleteProgram(prog);
 		glUseProgram(0);
-- 
2.1.0



More information about the Piglit mailing list