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

Reply via email to