[Piglit] [PATCH 05/25] shader_runner/spirv: Add support for SPIR-V specializations
Alejandro PiƱeiro
apinheiro at igalia.com
Tue Apr 17 14:37:11 UTC 2018
From: Neil Roberts <nroberts at 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 f7c6ede60..d943cff06 100644
--- a/tests/shaders/shader_runner.c
+++ b/tests/shaders/shader_runner.c
@@ -159,6 +159,16 @@ static GLint read_width, read_height;
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;
@@ -252,19 +262,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,
};
@@ -617,7 +633,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);
@@ -1145,6 +1190,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;
@@ -1157,6 +1205,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;
@@ -1169,6 +1220,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;
@@ -1181,6 +1235,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;
@@ -1202,6 +1259,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;
@@ -1214,6 +1274,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;
@@ -1378,6 +1441,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)
{
@@ -1417,24 +1567,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;
@@ -1444,15 +1604,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;
@@ -1502,6 +1668,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
More information about the Piglit
mailing list