Catalyst status: Part 11 & 12 failed V4: * Use standard piglit_report_subtest_result (with basic test number) * use standard bool versus GLBoolean * Merge VS shader with the help of __VERSION__ * asprintf shader with a common GLSL version --- tests/all.tests | 1 + .../arb_separate_shader_objects/CMakeLists.gl.txt | 3 + .../ValidateProgramPipeline.c | 437 ++++++++++++++++++++ 3 files changed, 441 insertions(+) create mode 100644 tests/spec/arb_separate_shader_objects/ValidateProgramPipeline.c
diff --git a/tests/all.tests b/tests/all.tests index ce5e260..4e2c541 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -1106,6 +1106,7 @@ spec['ARB_separate_shader_objects'] = arb_separate_shader_objects arb_separate_shader_objects['sso-GetProgramPipelineiv'] = concurrent_test('arb_separate_shader_object-GetProgramPipelineiv') arb_separate_shader_objects['sso-IsProgramPipeline'] = concurrent_test('arb_separate_shader_object-IsProgramPipeline') arb_separate_shader_objects['sso-mix_pipeline_useprogram'] = concurrent_test('arb_separate_shader_object-mix_pipeline_useprogram') +arb_separate_shader_objects['sso-ValidateProgramPipeline'] = concurrent_test('arb_separate_shader_object-ValidateProgramPipeline') # Group ARB_sampler_objects arb_sampler_objects = Group() diff --git a/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt b/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt index e651956..f0f8864 100644 --- a/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt +++ b/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt @@ -12,3 +12,6 @@ link_libraries ( piglit_add_executable (arb_separate_shader_object-IsProgramPipeline IsProgramPipeline.c) piglit_add_executable (arb_separate_shader_object-GetProgramPipelineiv GetProgramPipelineiv.c) piglit_add_executable (arb_separate_shader_object-mix_pipeline_useprogram mix_pipeline_useprogram.c) +piglit_add_executable (arb_separate_shader_object-ValidateProgramPipeline ValidateProgramPipeline.c) + +# vim: ft=cmake: diff --git a/tests/spec/arb_separate_shader_objects/ValidateProgramPipeline.c b/tests/spec/arb_separate_shader_objects/ValidateProgramPipeline.c new file mode 100644 index 0000000..142988e --- /dev/null +++ b/tests/spec/arb_separate_shader_objects/ValidateProgramPipeline.c @@ -0,0 +1,437 @@ +/* + * Copyright © 2013 Gregory Hainaut <gregory.hain...@gmail.com> + * + * 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. + */ + + +/* INVALID_OPERATION: + * + * • A program object is active for at least one, but not all of the shader stages + * that were present when the program was linked. + * • One program object is active for at least two shader stages and a second + * program is active for a shader stage between two stages for which the first + * program was active. The active compute shader is ignored for the purposes + * of this test. + * • There is an active program for tessellation control, tessellation evaluation, or + * geometry stages with corresponding executable shader, but there is no active + * program with executable vertex shader. + * • There is no current program object specified by UseProgram, there is a cur- + * rent program pipeline object, and the current program for any shader stage + * has been relinked since being applied to the pipeline object via UsePro- + * gramStages with the PROGRAM_SEPARABLE parameter set to FALSE. + */ + +#define _GNU_SOURCE +#include "piglit-util-gl-common.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 21; + + config.window_width = 32; + config.window_height = 32; + +PIGLIT_GL_TEST_CONFIG_END + +static bool pass; + +enum piglit_result +piglit_display(void) +{ + /* UNREACHED */ + return PIGLIT_FAIL; +} + +static void +validate_pipe(GLuint pipe, bool expected, char* msg) +{ + GLint status; + + pass &= piglit_check_gl_error(GL_NO_ERROR); + + status = piglit_program_pipeline_check_status_quiet(pipe); + + if (status != expected) { + fprintf(stderr, "!!! Wrong pipeline validation status. Got %d, expected %d\n\n", status, expected); + piglit_report_subtest_result(PIGLIT_FAIL, msg); + pass = false; + } else { + piglit_report_subtest_result(PIGLIT_PASS, msg); + } +} + +static GLuint +create_prog(GLint sh1, GLint sh2) { + GLint p = 0; + + p = glCreateProgram(); + glProgramParameteri(p, GL_PROGRAM_SEPARABLE, GL_TRUE); + if (sh1) glAttachShader(p, sh1); + if (sh2) glAttachShader(p, sh2); + glLinkProgram(p); + + pass &= piglit_link_check_status(p); + + return p; +} + +void +piglit_init(int argc, char **argv) +{ + GLint vs, fs, gs, tes, tcs; + GLuint pipe; + GLint prog_vs, prog_fs, prog_gs, prog_tcs, prog_tes, prog_tess; + GLint prog_vs_fs, prog_vs_gs; + GLint separable; + int version; + + char *vs_source, *fs_source, *gs_source, *te_source, *tc_source; + const char *vs_source_template = + "#version %d\n" + "#extension GL_ARB_separate_shader_objects : enable\n" + "\n" + "#if __VERSION__ > 140\n" + "out gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "};\n" + "\n" + "in vec4 position;\n" + "#endif\n" + "\n" + "void main()\n" + "{\n" + "#if __VERSION__ > 140\n" + " gl_Position = position;\n" + "#else\n" + " gl_Position = gl_Vertex;\n" + "#endif\n" + "}\n"; + const char *fs_source_template = + "#version %d\n" + "#extension GL_ARB_separate_shader_objects : enable\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(0.0, 1.0, 0.0, 0.0);\n" + "}\n"; + const char *gs_source_template = + "#version %d\n" + "#extension GL_ARB_separate_shader_objects : enable\n" + "\n" + "in gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "} gl_in[];\n" + "\n" + "out gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "};\n" + "\n" + "layout(triangles) in;\n" + "layout(triangle_strip, max_vertices = 3) out;\n" + "void main() {\n" + " for(int i = 0; i < gl_in.length(); i++) {\n" + " gl_Position = gl_in[i].gl_Position;\n" + " EmitVertex();\n" + " }\n" + " EndPrimitive();\n" + "}\n"; + const char *tc_source_template = + "#version %d\n" + "#extension GL_ARB_separate_shader_objects : enable\n" + "#extension GL_ARB_tessellation_shader : enable\n" + "\n" + "in gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "} gl_in[];\n" + "\n" + "out gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "} gl_out[];\n" + "\n" + "layout( vertices = 3 ) out;\n" + "void main( )\n" + "{\n" + " gl_out[ gl_InvocationID ].gl_Position = gl_in[ gl_InvocationID ].gl_Position;\n" + " gl_TessLevelOuter[0] = 1.0;\n" + " gl_TessLevelOuter[1] = 1.0;\n" + " gl_TessLevelOuter[2] = 1.0;\n" + " gl_TessLevelInner[0] = 1.0;\n" + " gl_TessLevelInner[1] = 1.0;\n" + "}\n"; + const char *te_source_template = + "#version %d\n" + "#extension GL_ARB_separate_shader_objects : enable\n" + "#extension GL_ARB_tessellation_shader : enable\n" + "\n" + "in gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "} gl_in[];\n" + "\n" + "out gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "};\n" + "\n" + "layout( triangles, equal_spacing) in;\n" + "\n" + "void main( )\n" + "{\n" + " vec4 p0 = gl_in[0].gl_Position;\n" + " vec4 p1 = gl_in[1].gl_Position;\n" + " vec4 p2 = gl_in[2].gl_Position;\n" + " \n" + " vec3 p = gl_TessCoord.xyz;\n" + " \n" + " gl_Position = p0*p.x + p1*p.y + p2*p.z;\n" + "}\n"; + + bool has_tess = piglit_is_extension_supported("GL_ARB_tessellation_shader"); + bool has_geo = piglit_is_extension_supported("GL_ARB_geometry_shader4"); + + piglit_require_gl_version(21); + piglit_require_extension("GL_ARB_separate_shader_objects"); + + if (piglit_get_gl_version() >= 32) + version = 150; + else + version = 120; + + pass = true; + + /* create the shader program */ + asprintf(&vs_source, vs_source_template, version); + asprintf(&fs_source, fs_source_template, version); + asprintf(&gs_source, gs_source_template, version); + asprintf(&te_source, te_source_template, version); + asprintf(&tc_source, tc_source_template, version); + + vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_source); + fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_source); + pass &= fs && vs; + if (has_geo) { + gs = piglit_compile_shader_text(GL_GEOMETRY_SHADER, gs_source); + pass &= gs; + } + if (has_tess) { + tes = piglit_compile_shader_text(GL_TESS_EVALUATION_SHADER, te_source); + tcs = piglit_compile_shader_text(GL_TESS_CONTROL_SHADER, tc_source); + pass &= tes && tcs; + } + + prog_vs = create_prog(vs, 0); + prog_fs = create_prog(fs, 0); + prog_vs_fs = create_prog(vs, fs); + if (has_geo) { + prog_gs = create_prog(gs, 0); + prog_vs_gs = create_prog(vs, gs); + } + if (has_tess) { + prog_tcs = create_prog(tcs, 0); + prog_tes = create_prog(tes, 0); + prog_tess = create_prog(tcs, tes); + } + + /* Setup or compilation failure. Stop here */ + pass &= piglit_check_gl_error(GL_NO_ERROR); + if (!pass) { + piglit_report_result(PIGLIT_FAIL); + return; + } + + if (has_tess && has_geo) { + printf("INFO: ALL stages supported: running all test\n"); + } else { + if (!has_tess) + printf("INFO: GL_ARB_tessellation_shader not supported: tesselation test disabled\n"); + if (!has_geo) + printf("INFO: GL_ARB_geometry_shader4 not supported: geometry test disabled\n"); + } + + /* Create the pipeline */ + glGenProgramPipelines(1, &pipe); + + printf("TEST 1: sanity check prog_vs_fs\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, prog_vs_fs); + + validate_pipe(pipe, GL_TRUE, "TEST_01"); + + if (has_geo) { + printf("TEST 2: bad: prog_gs in the middle of prog_vs_fs\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, prog_vs_fs); + glUseProgramStages(pipe, GL_GEOMETRY_SHADER_BIT, prog_gs); + + validate_pipe(pipe, GL_FALSE, "TEST_02"); + } else { + printf("TEST 2: bad: prog_gs in the middle of prog_vs_fs => Skipped\n"); + piglit_report_subtest_result(PIGLIT_SKIP, "TEST_02"); + } + + printf("TEST 3: bad: prog_fs and only VS of prog_vs_fs\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, prog_fs); + glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT, prog_vs_fs); + + validate_pipe(pipe, GL_FALSE, "TEST_03"); + + printf("TEST 4: good: prog_vs_fs in 2 step\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, prog_vs_fs); + glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT, prog_vs_fs); + + validate_pipe(pipe, GL_TRUE, "TEST_04"); + + if (has_geo) { + printf("TEST 5: bad: prog_gs without prog_vs\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, prog_fs); + glUseProgramStages(pipe, GL_GEOMETRY_SHADER_BIT, prog_gs); + + validate_pipe(pipe, GL_FALSE, "TEST_05"); + } else { + printf("TEST 5: bad: prog_gs without prog_vs => Skipped\n"); + piglit_report_subtest_result(PIGLIT_SKIP, "TEST_05"); + } + + if (has_geo) { + printf("TEST 6: bad: only GS of prog_vs_gs\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, prog_fs); + glUseProgramStages(pipe, GL_GEOMETRY_SHADER_BIT, prog_vs_gs); + glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT, prog_vs); + + validate_pipe(pipe, GL_FALSE, "TEST_06"); + } else { + printf("TEST 6: bad: only GS of prog_vs_gs => Skipped\n"); + piglit_report_subtest_result(PIGLIT_SKIP, "TEST_06"); + } + + printf("TEST 7: good: sanity check all single prog\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, prog_fs); + if (has_geo) { + glUseProgramStages(pipe, GL_GEOMETRY_SHADER_BIT, prog_gs); + } + glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT, prog_vs); + if (has_tess) { + glUseProgramStages(pipe, GL_TESS_CONTROL_SHADER_BIT, prog_tcs); + glUseProgramStages(pipe, GL_TESS_EVALUATION_SHADER_BIT, prog_tes); + } + + validate_pipe(pipe, GL_TRUE, "TEST_07"); + + if (has_tess) { + printf("TEST 8: bad: prog_tcs in the middle of prog_vs_gs\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, prog_vs_gs); + glUseProgramStages(pipe, GL_TESS_CONTROL_SHADER_BIT, prog_tcs); + + validate_pipe(pipe, GL_FALSE, "TEST_08"); + } else { + printf("TEST 8: bad: prog_tcs in the middle of prog_vs_gs => Skipped\n"); + piglit_report_subtest_result(PIGLIT_SKIP, "TEST_08"); + } + + if (has_tess) { + printf("TEST 9: bad: prog_tes in the middle of prog_vs_gs\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, prog_vs_gs); + glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, prog_fs); + glUseProgramStages(pipe, GL_TESS_EVALUATION_SHADER_BIT, prog_tes); + + validate_pipe(pipe, GL_FALSE, "TEST_09"); + } else { + printf("TEST 9: bad: prog_tes in the middle of prog_vs_gs => Skipped\n"); + piglit_report_subtest_result(PIGLIT_SKIP, "TEST_09"); + } + + if (has_tess) { + printf("TEST 10: bad: only tes of prog_tess\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, prog_fs); + glUseProgramStages(pipe, GL_TESS_EVALUATION_SHADER_BIT, prog_tess); + glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT, prog_vs); + + validate_pipe(pipe, GL_FALSE, "TEST_10"); + } else { + printf("TEST 10: bad: only tes of prog_tess => Skipped\n"); + piglit_report_subtest_result(PIGLIT_SKIP, "TEST_10"); + } + + if (has_tess) { + printf("TEST 11: bad: prog_tess without prog_vs\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, prog_tess); + glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, prog_fs); + + validate_pipe(pipe, GL_FALSE, "TEST_11"); + } else { + printf("TEST 11: bad: prog_tess without prog_vs => Skipped\n"); + piglit_report_subtest_result(PIGLIT_SKIP, "TEST_11"); + } + + printf("TEST 12: bad: relink attached prog_fs without GL_PROGRAM_SEPARABLE\n"); + glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0); + + glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, prog_fs); + glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT, prog_vs); + + /* sanity check */ + validate_pipe(pipe, GL_TRUE, "TEST_12a"); + + glGetProgramiv(prog_fs, GL_PROGRAM_SEPARABLE, &separable); + if (!separable) { + printf("Error: %d was not a separable program\n", prog_fs); + pass = false; + } + + glProgramParameteri(prog_fs, GL_PROGRAM_SEPARABLE, GL_FALSE); + + glGetProgramiv(prog_fs, GL_PROGRAM_SEPARABLE, &separable); + if (separable) { + printf("Error: fail to remove separable flags of program %d\n", prog_fs); + pass = false; + } + + glLinkProgram(prog_fs); + pass &= piglit_link_check_status(prog_fs); + validate_pipe(pipe, GL_FALSE, "TEST_12b"); + + piglit_present_results(); + + if (pass) + piglit_report_result(PIGLIT_PASS); + else + piglit_report_result(PIGLIT_FAIL); +} -- 1.7.10.4 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/piglit