[Piglit] [PATCH 1/4] shader_runner: Add basic SSO support to shader runner
Timothy Arceri
timothy.arceri at collabora.com
Fri Dec 4 02:11:03 PST 2015
This sets up the basics for using SSO with shader runner. This will
only support vertex and fragment shaders but is easily extended.
V2: delete pipeline in cleanup code rather than calling gen again,
output error message when SSO fails to link
Example shader:
[require]
GLSL >= 1.50
[vertex sso]
#version 150
#extension GL_ARB_explicit_attrib_location: require
#extension GL_ARB_separate_shader_objects: require
layout(location = 0) in vec4 piglit_vertex;
layout(location = 2) out vec3 a;
layout(location = 3) out vec3 b;
void main()
{
gl_Position = piglit_vertex;
a = vec3(0, 0, 1);
b = vec3(1, 0, 0);
}
[fragment sso]
#version 150
#extension GL_ARB_explicit_attrib_location: require
#extension GL_ARB_separate_shader_objects: require
layout(location = 0) out vec4 out_color;
layout(location = 2) in vec3 b; /* should get vec3(0, 0, 1) */
layout(location = 3) in vec3 a; /* should get vec3(1, 0, 0) */
void main()
{
out_color = vec4(cross(b, a), 1);
}
[test]
draw rect -1 -1 2 2
probe all rgb 0 1 0
---
tests/shaders/shader_runner.c | 85 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)
diff --git a/tests/shaders/shader_runner.c b/tests/shaders/shader_runner.c
index eeb1aac..6ec8f5c 100644
--- a/tests/shaders/shader_runner.c
+++ b/tests/shaders/shader_runner.c
@@ -123,10 +123,12 @@ GLint shader_string_size;
const char *vertex_data_start = NULL;
const char *vertex_data_end = NULL;
GLuint prog;
+GLuint pipeline;
size_t num_vbo_rows = 0;
bool vbo_present = false;
bool link_ok = false;
bool prog_in_use = false;
+bool sso_in_use = false;
GLchar *prog_err_info = NULL;
GLuint vao = 0;
GLuint fbo = 0;
@@ -137,12 +139,14 @@ enum states {
requirements,
vertex_shader,
vertex_shader_passthrough,
+ vertex_sso,
vertex_program,
tess_ctrl_shader,
tess_eval_shader,
geometry_shader,
geometry_layout,
fragment_shader,
+ fragment_sso,
fragment_program,
compute_shader,
vertex_data,
@@ -480,6 +484,55 @@ compile_and_bind_program(GLenum target, const char *start, int len)
prog_in_use = true;
}
+void
+create_sso(GLenum target, const char *start, int len)
+{
+ GLuint prog;
+ GLint ok;
+ char *source;
+
+ piglit_require_extension("GL_ARB_separate_shader_objects");
+
+ source = malloc(len + 1);
+ memcpy(source, start, len);
+ source[len] = 0;
+ prog = glCreateShaderProgramv(target, 1,
+ (const GLchar *const *) &source);
+
+ glGetProgramiv(prog, GL_LINK_STATUS, &ok);
+ if (ok) {
+ link_ok = true;
+ } else {
+ GLint size;
+
+ glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
+ prog_err_info = malloc(size);
+
+ glGetProgramInfoLog(prog, size, NULL, prog_err_info);
+
+ fprintf(stderr, "glCreateShaderProgramv(%s) failed: %s\n",
+ target_to_short_name(target),
+ prog_err_info);
+
+ free(prog_err_info);
+ piglit_report_result(PIGLIT_FAIL);
+
+ return;
+ }
+
+ switch (target) {
+ case GL_VERTEX_SHADER:
+ glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, prog);
+ break;
+ case GL_FRAGMENT_SHADER:
+ glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, prog);
+ break;
+ }
+
+ sso_in_use = true;
+ prog_in_use = true;
+}
+
/**
* Compare two values given a specified comparison operator
*/
@@ -846,6 +899,13 @@ leave_state(enum states state, const char *line)
compile_glsl(GL_VERTEX_SHADER);
break;
+ case vertex_sso:
+ shader_string_size = line - shader_string;
+ create_sso(GL_VERTEX_SHADER,
+ shader_string,
+ line - shader_string);
+ break;
+
case vertex_program:
compile_and_bind_program(GL_VERTEX_PROGRAM_ARB,
shader_string,
@@ -875,6 +935,12 @@ leave_state(enum states state, const char *line)
compile_glsl(GL_FRAGMENT_SHADER);
break;
+ case fragment_sso:
+ create_sso(GL_FRAGMENT_SHADER,
+ shader_string,
+ line - shader_string);
+ break;
+
case fragment_program:
compile_and_bind_program(GL_FRAGMENT_PROGRAM_ARB,
shader_string,
@@ -1043,6 +1109,9 @@ process_test_script(const char *script_name)
} else if (string_match("[vertex program]", line)) {
state = vertex_program;
shader_string = NULL;
+ } else if (string_match("[vertex sso]", line)) {
+ state = vertex_sso;
+ shader_string = NULL;
} else if (string_match("[vertex shader passthrough]", line)) {
state = vertex_shader_passthrough;
shader_string =
@@ -1063,6 +1132,9 @@ process_test_script(const char *script_name)
} else if (string_match("[fragment shader]", line)) {
state = fragment_shader;
shader_string = NULL;
+ } else if (string_match("[fragment sso]", line)) {
+ state = fragment_sso;
+ shader_string = NULL;
} else if (string_match("[fragment program]", line)) {
state = fragment_program;
shader_string = NULL;
@@ -1098,11 +1170,13 @@ process_test_script(const char *script_name)
break;
case vertex_shader:
+ case vertex_sso:
case vertex_program:
case tess_ctrl_shader:
case tess_eval_shader:
case geometry_shader:
case fragment_shader:
+ case fragment_sso:
case fragment_program:
case compute_shader:
if (shader_string == NULL)
@@ -3094,8 +3168,10 @@ piglit_display(void)
glDeleteProgram(prog);
glUseProgram(0);
} else {
- glDeleteProgramsARB(1, &prog);
+ if (!sso_in_use)
+ glDeleteProgramsARB(1, &prog);
}
+ glDeleteProgramPipelines(1, &pipeline);
}
return pass ? PIGLIT_PASS : PIGLIT_FAIL;
@@ -3138,6 +3214,9 @@ piglit_init(int argc, char **argv)
glGetIntegerv(GL_MAX_VARYING_COMPONENTS,
&gl_max_varying_components);
glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max_clip_planes);
+
+ if (piglit_is_extension_supported("GL_ARB_separate_shader_objects"))
+ glGenProgramPipelines(1, &pipeline);
#else
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
&gl_max_fragment_uniform_components);
@@ -3157,6 +3236,10 @@ piglit_init(int argc, char **argv)
process_test_script(argv[1]);
link_and_use_shaders();
+
+ if (sso_in_use)
+ glBindProgramPipeline(pipeline);
+
if (link_ok && vertex_data_start != NULL) {
program_must_be_in_use();
bind_vao_if_supported();
--
2.4.3
More information about the Piglit
mailing list