--- tests/all.tests | 7 + tests/spec/glsl-1.10/execution/CMakeLists.txt | 1 + .../execution/varying-packing/CMakeLists.gl.txt | 14 + .../execution/varying-packing/CMakeLists.txt | 1 + .../glsl-1.10/execution/varying-packing/simple.c | 413 +++++++++++++++++++++ 5 files changed, 436 insertions(+) create mode 100644 tests/spec/glsl-1.10/execution/varying-packing/CMakeLists.gl.txt create mode 100644 tests/spec/glsl-1.10/execution/varying-packing/CMakeLists.txt create mode 100644 tests/spec/glsl-1.10/execution/varying-packing/simple.c
diff --git a/tests/all.tests b/tests/all.tests index a471203..c823bcf 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -705,6 +705,13 @@ add_shader_test_dir(spec['glsl-1.10']['execution'], for mode in ['fixed', 'pos_clipvert', 'clipvert_pos']: cmdline = 'clip-plane-transformation ' + mode spec['glsl-1.10']['execution']['clipping'][cmdline] = concurrent_test(cmdline) +for type in ['int', 'uint', 'float', 'vec2', 'vec3', 'vec4', 'ivec2', 'ivec3', + 'ivec4', 'uvec2', 'uvec3', 'uvec4', 'mat2', 'mat3', 'mat4', + 'mat2x3', 'mat2x4', 'mat3x2', 'mat3x4', 'mat4x2', 'mat4x3']: + for arrayspec in ['array', 'separate']: + cmdline = 'simple {0} {1}'.format(type, arrayspec) + spec['glsl-1.10']['execution']['varying-packing'][cmdline] = \ + concurrent_test('varying-packing-' + cmdline) spec['glsl-1.10']['api'] = Group() add_concurrent_test(spec['glsl-1.10']['api'], 'getactiveattrib 110'); diff --git a/tests/spec/glsl-1.10/execution/CMakeLists.txt b/tests/spec/glsl-1.10/execution/CMakeLists.txt index a768d27..18243fe 100644 --- a/tests/spec/glsl-1.10/execution/CMakeLists.txt +++ b/tests/spec/glsl-1.10/execution/CMakeLists.txt @@ -1,2 +1,3 @@ piglit_include_target_api() add_subdirectory (clipping) +add_subdirectory (varying-packing) diff --git a/tests/spec/glsl-1.10/execution/varying-packing/CMakeLists.gl.txt b/tests/spec/glsl-1.10/execution/varying-packing/CMakeLists.gl.txt new file mode 100644 index 0000000..692b5e7 --- /dev/null +++ b/tests/spec/glsl-1.10/execution/varying-packing/CMakeLists.gl.txt @@ -0,0 +1,14 @@ + +include_directories( + ${GLEXT_INCLUDE_DIR} + ${OPENGL_INCLUDE_PATH} + ${piglit_SOURCE_DIR}/tests/mesa/util +) + +link_libraries ( + piglitutil_${piglit_target_api} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +piglit_add_executable (varying-packing-simple simple.c) diff --git a/tests/spec/glsl-1.10/execution/varying-packing/CMakeLists.txt b/tests/spec/glsl-1.10/execution/varying-packing/CMakeLists.txt new file mode 100644 index 0000000..144a306 --- /dev/null +++ b/tests/spec/glsl-1.10/execution/varying-packing/CMakeLists.txt @@ -0,0 +1 @@ +piglit_include_target_api() diff --git a/tests/spec/glsl-1.10/execution/varying-packing/simple.c b/tests/spec/glsl-1.10/execution/varying-packing/simple.c new file mode 100644 index 0000000..5d36ccb --- /dev/null +++ b/tests/spec/glsl-1.10/execution/varying-packing/simple.c @@ -0,0 +1,413 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * \file simple.c + * + * This file checks that simple cases of varying packing work + * correctly. Specifically, it tests that for each basic type allowed + * in varyings, it is possible to create a shader with the maximum + * possible number of that type of varying (determined by the + * implementation's reported value of GL_MAX_VARYING_FLOATS). If the + * size of the basic type being tested does not evenly divide + * GL_MAX_VARYING_FLOATS, the remaining varyings are taken up by + * individual floats. + * + * The test may be run in two modes: "array" mode, in which the test + * uses a single varying whose type is an array (e.g. mat3[7]), and + * "separate" mode, in which the test uses separate individual + * varyings of the given type. + * + * The test operates by first querying the implementation's value of + * GL_MAX_VARYING_FLOATS, then creating a vertex and fragment shader + * that use up all possible varying components. The vertex shader + * fills the varying components with consecutive integer values (where + * the starting value is determined by a uniform), and the fragment + * shader checks that all of the varying components were received + * correctly. The shaders are compiled and run, to ensure that the + * implementation not only claims to be able to pack the varyings, but + * actually packs them correctly too. + * + * For example, on an implementation where GL_MAX_VARYING_FLOATS is + * 64, when testing the mat3 type in "array" mode, the vertex shader + * looks like this: + * + * #version 110 + * uniform int i; + * varying mat3 var0[7]; + * varying float var1; + * + * void main() + * { + * gl_Position = gl_Vertex; + * var0[0][0][0] = float(i + 0); + * var0[0][0][1] = float(i + 1); + * var0[0][0][2] = float(i + 2); + * var0[0][1][0] = float(i + 3); + * ... + * var0[6][2][1] = float(i + 61); + * var0[6][2][2] = float(i + 62); + * var1 = float(i + 63); + * } + * + * And the fragment shader looks like this: + * + * #version 110 + * uniform int i; + * varying mat3 var0[7]; + * varying float var1; + * + * void main() + * { + * bool failed = false; + * if (var0[0][0][0] != float(i + 0)) + * failed = true; + * if (var0[0][0][1] != float(i + 1)) + * failed = true; + * ... + * if (var0[6][2][2] != float(i + 62)) + * failed = true; + * if (var1 != float(i + 63)) + * failed = true; + * if (failed) + * gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + * else + * gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); + * } + */ +#include "piglit-util-gl-common.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 10; + + config.window_width = 100; + config.window_height = 100; + config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE; + +PIGLIT_GL_TEST_CONFIG_END + +static GLuint prog; +static GLint i_location; + +enum base_type +{ + BASE_TYPE_FLOAT, + BASE_TYPE_UINT, + BASE_TYPE_INT, +}; + +static const char * +get_base_type_name(enum base_type t) +{ + switch (t) { + case BASE_TYPE_FLOAT: return "float"; + case BASE_TYPE_UINT: return "uint"; + case BASE_TYPE_INT: return "int"; + default: return "???"; + } +} + +struct type_desc +{ + const char *name; + enum base_type base; + unsigned num_cols; + unsigned num_rows; + unsigned glsl_version_required; +}; + +struct type_desc int_type = { "int", BASE_TYPE_INT, 1, 1, 130 }; +struct type_desc uint_type = { "uint", BASE_TYPE_UINT, 1, 1, 130 }; +struct type_desc float_type = { "float", BASE_TYPE_FLOAT, 1, 1, 110 }; +struct type_desc vec2_type = { "vec2", BASE_TYPE_FLOAT, 1, 2, 110 }; +struct type_desc vec3_type = { "vec3", BASE_TYPE_FLOAT, 1, 3, 110 }; +struct type_desc vec4_type = { "vec4", BASE_TYPE_FLOAT, 1, 4, 110 }; +struct type_desc ivec2_type = { "ivec2", BASE_TYPE_INT, 1, 2, 130 }; +struct type_desc ivec3_type = { "ivec3", BASE_TYPE_INT, 1, 3, 130 }; +struct type_desc ivec4_type = { "ivec4", BASE_TYPE_INT, 1, 4, 130 }; +struct type_desc uvec2_type = { "uvec2", BASE_TYPE_UINT, 1, 2, 130 }; +struct type_desc uvec3_type = { "uvec3", BASE_TYPE_UINT, 1, 3, 130 }; +struct type_desc uvec4_type = { "uvec4", BASE_TYPE_UINT, 1, 4, 130 }; +struct type_desc mat2_type = { "mat2", BASE_TYPE_FLOAT, 2, 2, 110 }; +struct type_desc mat3_type = { "mat3", BASE_TYPE_FLOAT, 3, 3, 110 }; +struct type_desc mat4_type = { "mat4", BASE_TYPE_FLOAT, 4, 4, 110 }; +struct type_desc mat2x3_type = { "mat2x3", BASE_TYPE_FLOAT, 2, 3, 120 }; +struct type_desc mat2x4_type = { "mat2x4", BASE_TYPE_FLOAT, 2, 4, 120 }; +struct type_desc mat3x2_type = { "mat3x2", BASE_TYPE_FLOAT, 3, 2, 120 }; +struct type_desc mat3x4_type = { "mat3x4", BASE_TYPE_FLOAT, 3, 4, 120 }; +struct type_desc mat4x2_type = { "mat4x2", BASE_TYPE_FLOAT, 4, 2, 120 }; +struct type_desc mat4x3_type = { "mat4x3", BASE_TYPE_FLOAT, 4, 3, 120 }; + +const struct type_desc *all_types[] = { + &int_type, + &uint_type, + &float_type, + &vec2_type, + &vec3_type, + &vec4_type, + &ivec2_type, + &ivec3_type, + &ivec4_type, + &uvec2_type, + &uvec3_type, + &uvec4_type, + &mat2_type, + &mat3_type, + &mat4_type, + &mat2x3_type, + &mat2x4_type, + &mat3x2_type, + &mat3x4_type, + &mat4x2_type, + &mat4x3_type, + NULL, +}; + +/** + * Type used to communicate to get_shader() the set of varyings to + * test. + */ +struct varying_desc +{ + const struct type_desc *type; + unsigned array_elems; +}; + +/** + * Generate a vertex or fragment shader to test the given set of + * varyings. + */ +static GLint +get_shader(bool is_vs, unsigned glsl_version, int num_varyings, + struct varying_desc *varyings) +{ + GLuint shader; + char *full_text = malloc(1000 * 100 + num_varyings); + char *text = full_text; + unsigned i, j, k, l; + const char *varying_keyword; + unsigned offset = 0; + GLenum shader_type = is_vs ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER; + + if (glsl_version >= 130) { + if (is_vs) + varying_keyword = "out"; + else + varying_keyword = "in"; + } else { + varying_keyword = "varying"; + } + + text += sprintf(text, "#version %u\n", glsl_version); + text += sprintf(text, "uniform int i;\n"); + for (i = 0; i < num_varyings; ++i) { + const char *opt_flat_keyword = ""; + if (varyings[i].type->base != BASE_TYPE_FLOAT) + opt_flat_keyword = "flat "; + if (varyings[i].array_elems != 0) { + text += sprintf(text, "%s%s %s var%u[%u];\n", + opt_flat_keyword, varying_keyword, + varyings[i].type->name, i, + varyings[i].array_elems); + } else { + text += sprintf(text, "%s%s %s var%u;\n", + opt_flat_keyword, varying_keyword, + varyings[i].type->name, i); + } + } + text += sprintf(text, + "\n" + "void main()\n" + "{\n"); + if (is_vs) + text += sprintf(text, " gl_Position = gl_Vertex;\n"); + else + text += sprintf(text, " bool failed = false;\n"); + for (i = 0; i < num_varyings; ++i) { + unsigned array_loop_bound = varyings[i].array_elems; + const char *base_type_name + = get_base_type_name(varyings[i].type->base); + if (array_loop_bound == 0) + array_loop_bound = 1; + for (j = 0; j < array_loop_bound; ++j) { + for (k = 0; k < varyings[i].type->num_cols; ++k) { + for (l = 0; l < varyings[i].type->num_rows; ++l) { + text += sprintf(text, " "); + if (!is_vs) + text += sprintf(text, "if ("); + text += sprintf(text, "var%u", i); + if (varyings[i].array_elems) + text += sprintf(text, "[%u]", j); + if (varyings[i].type->num_cols > 1) + text += sprintf(text, "[%u]", k); + if (varyings[i].type->num_rows > 1) + text += sprintf(text, "[%u]", l); + if (is_vs) + text += sprintf(text, " = "); + else + text += sprintf(text, " != "); + text += sprintf(text, "%s(i + %u)", + base_type_name, + offset++); + if (is_vs) { + text += sprintf(text, ";\n"); + } else { + text += sprintf(text, + ")\n" + " failed = true;\n"); + } + } + } + } + } + if (!is_vs) { + text += sprintf(text, + " if (failed)\n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" + " else\n" + " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"); + } + text += sprintf(text, "}\n"); + + shader = piglit_compile_shader_text(shader_type, full_text); + + free(full_text); + + return shader; +} + +/** + * Choose the set of varyings necessary to properly run the given test + * configuration, given the implementation's reported value of + * max_varying_floats. + */ +static unsigned +choose_varyings(struct varying_desc *varyings, + const struct type_desc *test_type, GLboolean test_array, + unsigned max_varying_floats) +{ + unsigned num_varyings = 0; + unsigned components_in_test_type + = test_type->num_cols * test_type->num_rows; + unsigned num_test_varyings + = max_varying_floats / components_in_test_type; + unsigned num_extra_varyings + = max_varying_floats + - num_test_varyings * components_in_test_type; + unsigned i; + if (test_array) { + varyings[num_varyings].type = test_type; + varyings[num_varyings].array_elems = num_test_varyings; + ++num_varyings; + } else { + for (i = 0; i < num_test_varyings; ++i) { + varyings[num_varyings].type = test_type; + varyings[num_varyings].array_elems = 0; + ++num_varyings; + } + } + for (i = 0; i < num_extra_varyings; ++i) { + varyings[num_varyings].type = &float_type; + varyings[num_varyings].array_elems = 0; + ++num_varyings; + } + + return num_varyings; +} + +void +print_usage_and_exit(const char *prog_name) +{ + unsigned i; + printf("Usage: %s <type> <arrayspec>\n" + " where <type> is one of:\n", prog_name); + for (i = 0; all_types[i]; ++i) + printf(" %s\n", all_types[i]->name); + printf(" and <arrayspec> is one of:\n" + " array: test using an array of the above type\n" + " separate: test using separately declared varyings\n"); + piglit_report_result(PIGLIT_FAIL); +} + +void +piglit_init(int argc, char **argv) +{ + unsigned i; + const struct type_desc *test_type; + GLboolean test_array; + GLint max_varying_floats; + struct varying_desc *varyings; + unsigned num_varyings; + GLuint vs, fs; + + if (argc != 3) + print_usage_and_exit(argv[0]); + for (i = 0; all_types[i]; ++i) { + if (strcmp(argv[1], all_types[i]->name) == 0) + break; + } + if (all_types[i]) + test_type = all_types[i]; + else + print_usage_and_exit(argv[0]); + if (strcmp(argv[2], "array") == 0) + test_array = GL_TRUE; + else if (strcmp(argv[2], "separate") == 0) + test_array = GL_FALSE; + else + print_usage_and_exit(argv[0]); + + piglit_require_gl_version(20); + piglit_require_GLSL_version(test_type->glsl_version_required); + glGetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_floats); + + varyings = malloc(sizeof(*varyings) * max_varying_floats); + num_varyings = choose_varyings(varyings, test_type, + test_array, max_varying_floats); + + vs = get_shader(true, test_type->glsl_version_required, + num_varyings, varyings); + fs = get_shader(false, test_type->glsl_version_required, + num_varyings, varyings); + prog = piglit_link_simple_program(vs, fs); + i_location = glGetUniformLocation(prog, "i"); +} + +enum piglit_result +piglit_display(void) +{ + GLboolean pass = GL_TRUE; + float green[] = { 0.0, 1.0, 0.0, 1.0 }; + + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(prog); + glUniform1i(i_location, 0); + piglit_draw_rect(-1, -1, 2, 2); + pass = piglit_probe_rect_rgba(0, 0, piglit_width, piglit_height, green) + && pass; + + piglit_present_results(); + + return pass ? PIGLIT_PASS : PIGLIT_FAIL; +} -- 1.8.0.1 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/piglit