This sets up the basics for using SSO with shader runner. This will only support vertex and fragment shaders but is easily extended.
Example shader: [require] GLSL >= 1.50 [vertex sso] 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] 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 | 78 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/tests/shaders/shader_runner.c b/tests/shaders/shader_runner.c index eeb1aac..6010ae2 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,48 @@ 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); + + 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 +892,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 +928,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 +1102,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 +1125,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 +1163,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 +3161,10 @@ piglit_display(void) glDeleteProgram(prog); glUseProgram(0); } else { - glDeleteProgramsARB(1, &prog); + if (!sso_in_use) + glDeleteProgramsARB(1, &prog); } + glGenProgramPipelines(1, &pipeline); } return pass ? PIGLIT_PASS : PIGLIT_FAIL; @@ -3138,6 +3207,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 +3229,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 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/piglit