From: Neil Roberts <nrobe...@igalia.com>

There can now be extra sections such as the following in the
shader_test file:

[vertex shader specializations]
uint 0 3

These will get passed to glSpecializeShader when compiling the
corresponding shader.
---
 tests/shaders/shader_runner.c | 181 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 180 insertions(+), 1 deletion(-)

diff --git a/tests/shaders/shader_runner.c b/tests/shaders/shader_runner.c
index abe0df0b0..bffc444d7 100644
--- a/tests/shaders/shader_runner.c
+++ b/tests/shaders/shader_runner.c
@@ -165,6 +165,16 @@ static bool use_get_program_binary = false;
 
 static bool report_subtests = false;
 
+struct specialization_list {
+       size_t buffer_size;
+       size_t n_entries;
+       GLuint *indices;
+       union { GLuint u; GLfloat f; } *values;
+};
+
+static struct specialization_list
+specializations[SHADER_TYPES];
+
 static struct texture_binding {
        GLuint obj;
        unsigned width;
@@ -258,19 +268,25 @@ enum states {
        vertex_shader,
        vertex_shader_passthrough,
        vertex_shader_spirv,
+       vertex_shader_specializations,
        vertex_program,
        tess_ctrl_shader,
        tess_ctrl_shader_spirv,
+       tess_ctrl_shader_specializations,
        tess_eval_shader,
        tess_eval_shader_spirv,
+       tess_eval_shader_specializations,
        geometry_shader,
        geometry_shader_spirv,
+       geometry_shader_specializations,
        geometry_layout,
        fragment_shader,
        fragment_shader_spirv,
+       fragment_shader_specializations,
        fragment_program,
        compute_shader,
        compute_shader_spirv,
+       compute_shader_specializations,
        vertex_data,
        test,
 };
@@ -719,7 +735,36 @@ load_and_specialize_spirv(GLenum target,
        glShaderBinary(1, &shader, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB,
                       binary, size);
 
-       glSpecializeShaderARB(shader, "main", 0, NULL, NULL);
+       const struct specialization_list *specs;
+
+       switch (target) {
+       case GL_VERTEX_SHADER:
+               specs = specializations + 0;
+               break;
+       case GL_TESS_CONTROL_SHADER:
+               specs = specializations + 1;
+               break;
+       case GL_TESS_EVALUATION_SHADER:
+               specs = specializations + 2;
+               break;
+       case GL_GEOMETRY_SHADER:
+               specs = specializations + 3;
+               break;
+       case GL_FRAGMENT_SHADER:
+               specs = specializations + 4;
+               break;
+       case GL_COMPUTE_SHADER:
+               specs = specializations + 5;
+               break;
+       default:
+               assert(!"Should not get here.");
+       }
+
+       glSpecializeShaderARB(shader,
+                             "main",
+                             specs->n_entries,
+                             specs->indices,
+                             &specs->values[0].u);
 
        GLint ok;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
@@ -1256,6 +1301,9 @@ leave_state(enum states state, const char *line, const 
char *script_name)
                shader_string_size = line - shader_string;
                return assemble_spirv(GL_VERTEX_SHADER);
 
+       case vertex_shader_specializations:
+               break;
+
        case tess_ctrl_shader:
                if (spirv_replaces_glsl)
                        break;
@@ -1268,6 +1316,9 @@ leave_state(enum states state, const char *line, const 
char *script_name)
                shader_string_size = line - shader_string;
                return assemble_spirv(GL_TESS_CONTROL_SHADER);
 
+       case tess_ctrl_shader_specializations:
+               break;
+
        case tess_eval_shader:
                if (spirv_replaces_glsl)
                        break;
@@ -1280,6 +1331,9 @@ leave_state(enum states state, const char *line, const 
char *script_name)
                shader_string_size = line - shader_string;
                return assemble_spirv(GL_TESS_EVALUATION_SHADER);
 
+       case tess_eval_shader_specializations:
+               break;
+
        case geometry_shader:
                if (spirv_replaces_glsl)
                        break;
@@ -1292,6 +1346,9 @@ leave_state(enum states state, const char *line, const 
char *script_name)
                shader_string_size = line - shader_string;
                return assemble_spirv(GL_GEOMETRY_SHADER);
 
+       case geometry_shader_specializations:
+               break;
+
        case geometry_layout:
                break;
 
@@ -1313,6 +1370,9 @@ leave_state(enum states state, const char *line, const 
char *script_name)
                shader_string_size = line - shader_string;
                return assemble_spirv(GL_FRAGMENT_SHADER);
 
+       case fragment_shader_specializations:
+               break;
+
        case compute_shader:
                if (spirv_replaces_glsl)
                        break;
@@ -1325,6 +1385,9 @@ leave_state(enum states state, const char *line, const 
char *script_name)
                shader_string_size = line - shader_string;
                return assemble_spirv(GL_COMPUTE_SHADER);
 
+       case compute_shader_specializations:
+               break;
+
        case vertex_data:
                vertex_data_end = line;
                break;
@@ -1491,6 +1554,93 @@ cleanup:
        return result;
 }
 
+static enum piglit_result
+process_specialization(enum states state, const char *line)
+{
+       const char *end = strchrnul(line, '\n');
+       const char *next;
+       enum { TYPE_FLOAT, TYPE_UINT } type;
+
+       while (line < end && isspace(*line))
+               line++;
+
+       if (line >= end || *line == '#')
+               return PIGLIT_PASS;
+
+       if (parse_str(line, "uint", &next))
+               type = TYPE_UINT;
+       else if (parse_str(line, "float", &next))
+               type = TYPE_FLOAT;
+       else
+               goto invalid;
+
+       struct specialization_list *list;
+
+       switch (state) {
+       case vertex_shader_specializations:
+               list = specializations + 0;
+               break;
+       case tess_ctrl_shader_specializations:
+               list = specializations + 1;
+               break;
+       case tess_eval_shader_specializations:
+               list = specializations + 2;
+               break;
+       case geometry_shader_specializations:
+               list = specializations + 3;
+               break;
+       case fragment_shader_specializations:
+               list = specializations + 4;
+               break;
+       case compute_shader_specializations:
+               list = specializations + 5;
+               break;
+       default:
+               assert(!"Should not get here.");
+       }
+
+       if (list->n_entries >= list->buffer_size) {
+               if (list->buffer_size == 0)
+                       list->buffer_size = 1;
+               else
+                       list->buffer_size *= 2;
+               list->indices = realloc(list->indices,
+                                       (sizeof list->indices[0]) *
+                                       list->buffer_size);
+               list->values = realloc(list->values,
+                                      (sizeof list->values[0]) *
+                                      list->buffer_size);
+       }
+
+       if (parse_uints(next, list->indices + list->n_entries, 1, &next) != 1)
+               goto invalid;
+
+       switch (type) {
+       case TYPE_UINT:
+               if (parse_uints(next,
+                               &list->values[list->n_entries].u,
+                               1,
+                               &next) != 1)
+                       goto invalid;
+               break;
+       case TYPE_FLOAT:
+               if (parse_floats(next,
+                                &list->values[list->n_entries].f,
+                                1,
+                                &next) != 1)
+                       goto invalid;
+               break;
+       }
+
+       list->n_entries++;
+
+       return PIGLIT_PASS;
+
+ invalid:
+       fprintf(stderr, "Invalid specialization line\n");
+       return PIGLIT_FAIL;
+}
+
 static enum piglit_result
 process_test_script(const char *script_name)
 {
@@ -1530,24 +1680,34 @@ process_test_script(const char *script_name)
                        } else if (parse_str(line, "[vertex shader spirv]", 
NULL)) {
                                state = vertex_shader_spirv;
                                shader_string = NULL;
+                       } else if (parse_str(line, "[vertex shader 
specializations]", NULL)) {
+                               state = vertex_shader_specializations;
                        } else if (parse_str(line, "[tessellation control 
shader]", NULL)) {
                                state = tess_ctrl_shader;
                                shader_string = NULL;
                        } else if (parse_str(line, "[tessellation control 
shader spirv]", NULL)) {
                                state = tess_ctrl_shader_spirv;
                                shader_string = NULL;
+                       } else if (parse_str(line, "[tessellation control 
shader specializations]", NULL)) {
+                               state = tess_ctrl_shader_specializations;
                        } else if (parse_str(line, "[tessellation evaluation 
shader]", NULL)) {
                                state = tess_eval_shader;
                                shader_string = NULL;
                        } else if (parse_str(line, "[tessellation evaluation 
shader spirv]", NULL)) {
                                state = tess_eval_shader_spirv;
                                shader_string = NULL;
+                       } else if (parse_str(line, "[tessellation evaluation 
shader specializations]", NULL)) {
+                               state = tess_eval_shader_specializations;
                        } else if (parse_str(line, "[geometry shader]", NULL)) {
                                state = geometry_shader;
                                shader_string = NULL;
+                       } else if (parse_str(line, "[geometry shader 
specializations]", NULL)) {
+                               state = geometry_shader_specializations;
                        } else if (parse_str(line, "[geometry shader spirv]", 
NULL)) {
                                state = geometry_shader_spirv;
                                shader_string = NULL;
+                       } else if (parse_str(line, "[geometry shader 
specializations]", NULL)) {
+                               state = geometry_shader_specializations;
                        } else if (parse_str(line, "[geometry layout]", NULL)) {
                                state = geometry_layout;
                                shader_string = NULL;
@@ -1557,15 +1717,21 @@ process_test_script(const char *script_name)
                        } else if (parse_str(line, "[fragment program]", NULL)) 
{
                                state = fragment_program;
                                shader_string = NULL;
+                       } else if (parse_str(line, "[fragment shader 
specializations]", NULL)) {
+                               state = fragment_shader_specializations;
                        } else if (parse_str(line, "[fragment shader spirv]", 
NULL)) {
                                state = fragment_shader_spirv;
                                shader_string = NULL;
+                       } else if (parse_str(line, "[fragment shader 
specializations]", NULL)) {
+                               state = fragment_shader_specializations;
                        } else if (parse_str(line, "[compute shader]", NULL)) {
                                state = compute_shader;
                                shader_string = NULL;
                        } else if (parse_str(line, "[compute shader spirv]", 
NULL)) {
                                state = compute_shader_spirv;
                                shader_string = NULL;
+                       } else if (parse_str(line, "[compute shader 
specializations]", NULL)) {
+                               state = compute_shader_specializations;
                        } else if (parse_str(line, "[vertex data]", NULL)) {
                                state = vertex_data;
                                vertex_data_start = NULL;
@@ -1615,6 +1781,19 @@ process_test_script(const char *script_name)
                                        shader_string = (char *) line;
                                break;
 
+                       case vertex_shader_specializations:
+                       case tess_ctrl_shader_specializations:
+                       case tess_eval_shader_specializations:
+                       case geometry_shader_specializations:
+                       case fragment_shader_specializations:
+                       case compute_shader_specializations: {
+                               enum piglit_result result =
+                                       process_specialization(state, line);
+                               if (result != PIGLIT_PASS)
+                                       return result;
+                               break;
+                       }
+
                        case vertex_data:
                                if (vertex_data_start == NULL)
                                        vertex_data_start = line;
-- 
2.14.1

_______________________________________________
Piglit mailing list
Piglit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to