[Piglit] [PATCH] shader_runner: add ARB_shader_subroutine support (v2)

Dave Airlie airlied at gmail.com
Mon Apr 6 22:44:46 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)
Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 tests/shaders/shader_runner.c                      | 138 +++++++++++++++++++++
 .../execution/simple-subroutine.shader_test        |  42 +++++++
 .../execution/two-subroutines.shader_test          |  59 +++++++++
 3 files changed, 239 insertions(+)
 create mode 100644 tests/spec/arb_shader_subroutine/execution/simple-subroutine.shader_test
 create mode 100644 tests/spec/arb_shader_subroutine/execution/two-subroutines.shader_test

diff --git a/tests/shaders/shader_runner.c b/tests/shaders/shader_runner.c
index 20eb26c..d8a91cb 100644
--- a/tests/shaders/shader_runner.c
+++ b/tests/shaders/shader_runner.c
@@ -113,6 +113,14 @@ GLenum geometry_layout_output_type = GL_TRIANGLE_STRIP;
 GLint geometry_layout_vertices_out = 0;
 GLuint atomics_bo = 0;
 
+struct subroutine_uniform {
+	GLuint uniform_location;
+	GLuint uniform_index;
+};
+
+#define SHADER_TYPES 6
+static struct subroutine_uniform subuniforms[SHADER_TYPES][64];
+static int num_subuniforms[SHADER_TYPES];
 char *shader_string;
 GLint shader_string_size;
 const char *vertex_data_start = NULL;
@@ -1642,6 +1650,131 @@ 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
+program_subroutine_uniforms(void)
+{
+ 	int i, sidx;
+	GLuint uniformidx[64];
+	int stype;
+	for (sidx = 0; sidx < 4; sidx++) {
+
+		if (num_subuniforms[sidx] == 0)
+			continue;
+		stype = lookup_shader_type(sidx);
+		if (!stype)
+			continue;
+
+		for (i = 0; i < num_subuniforms[sidx]; i++)
+			uniformidx[i] = subuniforms[sidx][i].uniform_index;
+
+		glUniformSubroutinesuiv(stype, num_subuniforms[sidx], uniformidx);
+	}
+}
+
+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, i;
+
+	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);
+
+	loc = glGetSubroutineUniformLocation(prog, ptype, name);
+	if (loc < 0) {
+		printf("cannot get location of 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);
+	}
+
+	for (i = 0; i < num_subuniforms[sidx]; i++) {
+		if (subuniforms[sidx][i].uniform_location == loc) {
+			subuniforms[sidx][i].uniform_index = idx;
+			break;
+		}
+	}
+	if (i == num_subuniforms[sidx]) {
+		num_subuniforms[sidx]++;
+		subuniforms[sidx][i].uniform_location = loc;
+		subuniforms[sidx][i].uniform_index = idx;
+	}
+
+	return;
+}
+
 /**
  * Query a uniform using glGetActiveUniformsiv
  *
@@ -2300,11 +2433,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", 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)) {
@@ -2614,6 +2749,9 @@ 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();
+			set_subroutine_uniform(line + 10);
 		} else if (string_match("parameter ", line)) {
 			set_parameter(line + strlen("parameter "));
 		} else if (string_match("patch parameter ", line)) {
diff --git a/tests/spec/arb_shader_subroutine/execution/simple-subroutine.shader_test b/tests/spec/arb_shader_subroutine/execution/simple-subroutine.shader_test
new file mode 100644
index 0000000..ae5925f
--- /dev/null
+++ b/tests/spec/arb_shader_subroutine/execution/simple-subroutine.shader_test
@@ -0,0 +1,42 @@
+[require]
+GLSL >= 1.50
+GL_ARB_shader_subroutine
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 150
+#extension GL_ARB_shader_subroutine: enable
+
+out vec4 color;
+
+subroutine vec4 getcolor();
+subroutine uniform getcolor GetColor;
+
+subroutine(getcolor)
+vec4 color_red()
+{
+	return vec4(1.0, 0.0, 0.0, 1.0);
+}
+
+subroutine(getcolor)
+vec4 color_green()
+{
+	return vec4(0.0, 1.0, 0.0, 1.0);
+}
+
+void main()
+{
+	color = GetColor();
+}
+
+
+[test]
+clear color 0.0 0.0 1.0 0.0
+clear
+subuniform GL_FRAGMENT_SHADER GetColor color_red
+draw rect -1 -1 2 2
+probe all rgba 1.0 0.0 0.0 1.0
+subuniform GL_FRAGMENT_SHADER GetColor color_green
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/arb_shader_subroutine/execution/two-subroutines.shader_test b/tests/spec/arb_shader_subroutine/execution/two-subroutines.shader_test
new file mode 100644
index 0000000..a38b695
--- /dev/null
+++ b/tests/spec/arb_shader_subroutine/execution/two-subroutines.shader_test
@@ -0,0 +1,59 @@
+[require]
+GLSL >= 1.50
+GL_ARB_shader_subroutine
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 150
+#extension GL_ARB_shader_subroutine: enable
+
+out vec4 color;
+
+subroutine float getchan1();
+subroutine uniform getchan1 GetChan1;
+
+subroutine float getchan2();
+subroutine uniform getchan2 GetChan2;
+
+subroutine(getchan1)
+float chan1_full()
+{
+	return 1.0;
+}
+
+subroutine(getchan1)
+float chan1_empty()
+{
+	return 0.0;
+}
+
+subroutine(getchan2)
+float chan2_full()
+{
+	return 1.0;
+}
+
+subroutine(getchan2)
+float chan2_empty()
+{
+	return 0.0;
+}
+
+void main()
+{
+	color = vec4(GetChan1(), GetChan2(), 0.0, 1.0);
+}
+
+
+[test]
+clear color 0.0 0.0 1.0 0.0
+clear
+subuniform GL_FRAGMENT_SHADER GetChan1 chan1_full
+subuniform GL_FRAGMENT_SHADER GetChan2 chan2_empty
+draw rect -1 -1 2 2
+probe all rgba 1.0 0.0 0.0 1.0
+subuniform GL_FRAGMENT_SHADER GetChan1 chan1_empty
+subuniform GL_FRAGMENT_SHADER GetChan2 chan2_full
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
-- 
1.8.3.1



More information about the Piglit mailing list