Add tests that verify that the xfb overflow query correctly detects overflow on streams 0 and 1. Also add tests that check its interaction with glBeginConditionalRender, and with ARB_query_buffer_object.
v2: - add test to all.py (Ilia Mirkin) - Add check for ARB_transform_feedback_overflow_query extension v3: - skip some tests when GL_ARB_transform_feedback3 or GL_ARB_gpu_shader5 are not present, and add specific tests for those cases (Ilia Mirkin) Signed-off-by: Rafael Antognolli <rafael.antogno...@intel.com> --- tests/all.py | 6 + tests/spec/CMakeLists.txt | 1 + .../CMakeLists.gl.txt | 12 + .../CMakeLists.txt | 1 + .../arb_transform_feedback_overflow_query/basic.c | 591 +++++++++++++++++++++ 5 files changed, 611 insertions(+) create mode 100644 tests/spec/arb_transform_feedback_overflow_query/CMakeLists.gl.txt create mode 100644 tests/spec/arb_transform_feedback_overflow_query/CMakeLists.txt create mode 100644 tests/spec/arb_transform_feedback_overflow_query/basic.c diff --git a/tests/all.py b/tests/all.py index 03cf0c8..888f25f 100644 --- a/tests/all.py +++ b/tests/all.py @@ -3677,6 +3677,12 @@ with profile.test_list.group_manager( with profile.test_list.group_manager( PiglitGLTest, + grouptools.join('spec', 'arb_transform_feedback_overflow_query')) as g: + g(['arb_transform_feedback_overflow_query-basic'], + 'arb_transform_feedback_overflow_query-basic', run_concurrent=False) + +with profile.test_list.group_manager( + PiglitGLTest, grouptools.join('spec', 'arb_uniform_buffer_object')) as g: g(['arb_uniform_buffer_object-bindbuffer-general-point'], 'bindbuffer-general-point') diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt index 4ac1a53..6115c5a 100644 --- a/tests/spec/CMakeLists.txt +++ b/tests/spec/CMakeLists.txt @@ -74,6 +74,7 @@ add_subdirectory (arb_texture_view) add_subdirectory (arb_timer_query) add_subdirectory (arb_transform_feedback2) add_subdirectory (arb_transform_feedback3) +add_subdirectory (arb_transform_feedback_overflow_query) add_subdirectory (arb_viewport_array) add_subdirectory (ati_envmap_bumpmap) add_subdirectory (ext_depth_bounds_test) diff --git a/tests/spec/arb_transform_feedback_overflow_query/CMakeLists.gl.txt b/tests/spec/arb_transform_feedback_overflow_query/CMakeLists.gl.txt new file mode 100644 index 0000000..d75418f --- /dev/null +++ b/tests/spec/arb_transform_feedback_overflow_query/CMakeLists.gl.txt @@ -0,0 +1,12 @@ +include_directories( + ${GLEXT_INCLUDE_DIR} + ${OPENGL_INCLUDE_PATH} +) + +link_libraries ( + piglitutil_${piglit_target_api} + ${OPENGL_gl_LIBRARY} +) + +piglit_add_executable (arb_transform_feedback_overflow_query-basic basic.c) +# vim: ft=cmake: diff --git a/tests/spec/arb_transform_feedback_overflow_query/CMakeLists.txt b/tests/spec/arb_transform_feedback_overflow_query/CMakeLists.txt new file mode 100644 index 0000000..144a306 --- /dev/null +++ b/tests/spec/arb_transform_feedback_overflow_query/CMakeLists.txt @@ -0,0 +1 @@ +piglit_include_target_api() diff --git a/tests/spec/arb_transform_feedback_overflow_query/basic.c b/tests/spec/arb_transform_feedback_overflow_query/basic.c new file mode 100644 index 0000000..25c3355 --- /dev/null +++ b/tests/spec/arb_transform_feedback_overflow_query/basic.c @@ -0,0 +1,591 @@ +/* + * Copyright (c) 2016 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. + */ + +#include "piglit-util-gl.h" + +/** + * @file basic.c + * + * This test verifies the basic functionality of + * ARB_transform_feedback_overflow_query: that it detects overflow for specific + * streams, and on any stream too if requested. It does so by causing overflow + * first on stream 0, and then on stream 1. + */ + +#define BUFFER_OFFSET(i) ((void *)((char *)NULL + i)) + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 32; + config.supports_gl_core_version = 32; + +PIGLIT_GL_TEST_CONFIG_END + +static const char vs_pass_thru_text[] = + "#version 150\n" + "void main() {\n" + " gl_Position = vec4(gl_VertexID);\n" + "}\n"; + +static const char gs_overflow_single[] = + "#version 150\n" + "layout(points) in;\n" + "layout(points, max_vertices = 1) out;\n" + "out vec2 stream0_out;\n" + "void main() {\n" + " gl_Position = gl_in[0].gl_Position;\n" + + " stream0_out = vec2(gl_Position[0], gl_Position[1]);\n" + " EmitVertex();\n" + " EndPrimitive();\n" + "}"; + +static const char gs_overflow_multi[] = + "#version 150\n" + "#extension GL_ARB_gpu_shader5 : enable\n" + "layout(points) in;\n" + "layout(points, max_vertices = 4) out;\n" + "layout(stream = 0) out vec2 stream0_out;\n" + "layout(stream = 1) out vec2 stream1_out;\n" + "void main() {\n" + " gl_Position = gl_in[0].gl_Position;\n" + + " stream0_out = vec2(gl_Position[0], gl_Position[1]);\n" + " EmitStreamVertex(0);\n" + " EndStreamPrimitive(0);\n" + + " stream1_out = vec2(gl_Position[0], gl_Position[1]) + 20;\n" + " EmitStreamVertex(1);\n" + " EndStreamPrimitive(1);\n" + "}"; + +static const char *varyings_single[] = { "stream0_out" }; + +static const char *varyings_multi[] = { + "stream0_out", "gl_NextBuffer", "stream1_out", +}; + +#define STREAMS 2 + +static const char *program_in_use = NULL; + +static bool +build_and_use_program(const char *gs_text, const char **gs_varyings, + int array_size) +{ + GLuint prog; + + if (program_in_use == gs_text) + return true; + + prog = piglit_build_simple_program_multiple_shaders( + GL_VERTEX_SHADER, vs_pass_thru_text, + GL_GEOMETRY_SHADER, gs_text, 0); + + glTransformFeedbackVaryings(prog, array_size, gs_varyings, + GL_INTERLEAVED_ATTRIBS); + + glLinkProgram(prog); + if (!piglit_link_check_status(prog)) + return false; + if (!piglit_check_gl_error(GL_NO_ERROR)) + return false; + + glUseProgram(prog); + + program_in_use = gs_text; + + return true; +} + +static enum piglit_result +simple_query(GLuint query, bool expected) +{ + enum piglit_result pass = PIGLIT_PASS; + GLuint value; + + glGetQueryObjectuiv(query, GL_QUERY_RESULT, &value); + if (value != expected) { + printf("Wrong value for query. expected: %d, value: %d\n", + expected, value); + pass = PIGLIT_FAIL; + } + + return pass; +} + +static enum piglit_result +conditional_render(GLuint query, bool inverted, bool expected) +{ + enum piglit_result pass = PIGLIT_PASS; + bool rendered, render_expected; + GLuint generated_q, value; + GLuint wait = inverted ? GL_QUERY_WAIT_INVERTED : GL_QUERY_WAIT; + + glGenQueries(1, &generated_q); + + glBeginQuery(GL_PRIMITIVES_GENERATED, generated_q); + glBeginTransformFeedback(GL_POINTS); + glBeginConditionalRender(query, wait); + glDrawArrays(GL_POINTS, 0, 1); + glEndConditionalRender(); + glEndTransformFeedback(); + glEndQuery(GL_PRIMITIVES_GENERATED); + + if (!piglit_check_gl_error(GL_NO_ERROR)) + return PIGLIT_FAIL; + + glGetQueryObjectuiv(generated_q, GL_QUERY_RESULT, &value); + + if (!piglit_check_gl_error(GL_NO_ERROR)) + return PIGLIT_FAIL; + + rendered = value == 1; + render_expected = inverted ? !expected : expected; + if (rendered != render_expected) { + printf("Error: expect to render? %d, rendered? %d\n", + render_expected, rendered); + pass = PIGLIT_FAIL; + } + + return pass; +} + +static enum piglit_result +overflow_buffer_object(GLuint query, bool expected) +{ + enum piglit_result pass = PIGLIT_PASS; + GLuint queryBuffer; + const GLuint *readback; + + // Create a buffer object for the query result + glGenBuffers(1, &queryBuffer); + glBindBuffer(GL_QUERY_BUFFER, queryBuffer); + glBufferData(GL_QUERY_BUFFER, sizeof(GLuint), + NULL, GL_DYNAMIC_COPY); + + // Get query results to buffer object + glBindBuffer(GL_QUERY_BUFFER, queryBuffer); + glGetQueryObjectuiv(query, GL_QUERY_RESULT, BUFFER_OFFSET(0)); + + if (!piglit_check_gl_error(GL_NO_ERROR)) { + pass = PIGLIT_FAIL; + goto err_del_buffer; + } + + readback = glMapBuffer(GL_QUERY_BUFFER, GL_READ_ONLY); + if (readback[0] != expected) { + printf("Query buffer object error. Expected: %u, read: %u\n", + expected, readback[0]); + pass = PIGLIT_FAIL; + } + + if (!piglit_check_gl_error(GL_NO_ERROR)) + pass = PIGLIT_FAIL; + + glUnmapBuffer(GL_QUERY_BUFFER); + glBindBuffer(GL_QUERY_BUFFER, 0); +err_del_buffer: + glDeleteBuffers(1, &queryBuffer); + + if (!piglit_check_gl_error(GL_NO_ERROR)) + pass = PIGLIT_FAIL; + + return pass; +} + +static bool +check_multistream_extensions(void) +{ + if (!piglit_is_extension_supported("GL_ARB_gpu_shader5")) { + piglit_loge("context does not support GL_ARB_gpu_shader5; " + "skipping test"); + return false; + } + + if (!piglit_is_extension_supported("GL_ARB_transform_feedback3")) { + piglit_loge("context does not support " + "GL_ARB_transform_feedback3; skipping test"); + return false; + } + + return true; +} + +static enum piglit_result +run_subtest(int n_streams, int array_sizes[], int stream, GLuint query_type, + bool inverted, bool expected, const char *test_type) +{ + enum piglit_result pass = PIGLIT_PASS; + GLuint query; + GLuint *xfb; + GLuint vao; + int varyings_size; + const char *gs_text; + const char **gs_varyings; + + + if (n_streams > 1) { + if (!check_multistream_extensions()) + return PIGLIT_SKIP; + + gs_text = gs_overflow_multi; + gs_varyings = varyings_multi; + varyings_size = ARRAY_SIZE(varyings_multi); + } else { + gs_text = gs_overflow_single; + gs_varyings = varyings_single; + varyings_size = ARRAY_SIZE(varyings_single); + } + + if (!build_and_use_program(gs_text, gs_varyings, varyings_size)) { + printf("Could not build and link program.\n"); + return PIGLIT_FAIL; + } + + xfb = malloc(sizeof(*xfb) * n_streams); + + /* Set up the transform feedback buffers. */ + glGenBuffers(n_streams, xfb); + for (int i = 0; i < n_streams; i++) { + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, xfb[i]); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, + array_sizes[i] * sizeof(float), NULL, + GL_STREAM_READ); + } + + /* Test only records using transform feedback. */ + glEnable(GL_RASTERIZER_DISCARD); + + if (!piglit_check_gl_error(GL_NO_ERROR)) { + pass = PIGLIT_FAIL; + goto err_del_buffers; + } + + glGenQueries(1, &query); + glBeginQueryIndexed(query_type, stream, query); + + if (!piglit_check_gl_error(GL_NO_ERROR)) { + pass = PIGLIT_FAIL; + goto err_del_queries; + } + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + if (!piglit_check_gl_error(GL_NO_ERROR)) { + pass = PIGLIT_FAIL; + goto err_del_vao; + } + + /* Draw and record */ + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS, 0, 3); + glEndQueryIndexed(query_type, stream); + glEndTransformFeedback(); + + if (!piglit_check_gl_error(GL_NO_ERROR)) { + pass = PIGLIT_FAIL; + goto err_del_vao; + } + + if (!strcmp(test_type, "simple_query")) { + pass = simple_query(query, expected); + } else if (!strcmp(test_type, "conditional_render")) { + pass = conditional_render(query, inverted, expected); + } else if (!strcmp(test_type, "buffer_object")) { + pass = overflow_buffer_object(query, expected); + } else { + printf("Unkown test.\n"); + pass = PIGLIT_FAIL; + } + +err_del_vao: + glDeleteVertexArrays(1, &vao); +err_del_queries: + glDeleteQueries(1, &query); +err_del_buffers: + glDeleteBuffers(n_streams, xfb); + free(xfb); + + return pass; +} + +/** + * inverted = false, overflow = true. + */ +static enum piglit_result +test_overflow_single(void *test_data) +{ + GLuint query_type = GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB; + int array_sizes[] = { 5 }; + + return run_subtest(1, array_sizes, 0, query_type, false, true, test_data); +} + +/** + * inverted = false, expected overflow: false + */ +static enum piglit_result +test_no_overflow_single(void *test_data) +{ + GLuint query_type = GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB; + int array_sizes[] = { 6 }; + + return run_subtest(1, array_sizes, 0, query_type, false, false, test_data); +} + +/** + * Overflow on stream 0. + * Query for overflow on stream 0. + * inverted = false, expected overflow: true. + */ +static enum piglit_result +test_overflow_stream_0(void *test_data) +{ + GLuint query_type = GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB; + int array_sizes[] = { 5, 6 }; + + return run_subtest(2, array_sizes, 0, query_type, false, true, test_data); +} + +/** + * Overflow on stream 1. + * Query for overflow on stream 0. + * inverted = true, expected overflow: false. + */ +static enum piglit_result +test_overflow_stream_1(void *test_data) +{ + GLuint query_type = GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB; + int array_sizes[] = { 6, 5 }; + + return run_subtest(2, array_sizes, 0, query_type, true, false, test_data); +} + +/** + * Overflow on stream 1. + * Query for overflow on stream 1. + * inverted = true, expected overflow: true. + */ +static enum piglit_result +test_overflow_stream_2(void *test_data) +{ + GLuint query_type = GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB; + int array_sizes[] = { 6, 5 }; + + return run_subtest(2, array_sizes, 1, query_type, true, true, test_data); +} + +/** + * Overflow on stream 1. + * Query for overflow on any stream. + * inverted = false, expected overflow: true. + */ +static enum piglit_result +test_overflow_stream_any(void *test_data) +{ + GLuint query_type = GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB; + int array_sizes[] = { 6, 5 }; + + return run_subtest(2, array_sizes, 0, query_type, false, true, test_data); +} + +/** + * No overflow. + * Query for overflow on any stream. + * inverted = false, expected overflow: false. + */ +static enum piglit_result +test_no_overflow_stream_any(void *test_data) +{ + GLuint query_type = GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB; + int array_sizes[] = { 6, 6 }; + + return run_subtest(2, array_sizes, 0, query_type, false, false, + test_data); +} + + +const struct piglit_subtest overflow_query_subtests[] = { + { + "arb_transform_feedback_overflow_query-simple_query_single", + "arb_transform_feedback_overflow_query-simple_query_single", + test_overflow_single, + "simple_query" + }, + { + "arb_transform_feedback_overflow_query-simple_query_no_overflow_single", + "arb_transform_feedback_overflow_query-simple_query_no_overflow_single", + test_no_overflow_single, + "simple_query" + }, + { + "arb_transform_feedback_overflow_query-conditional_render_single", + "arb_transform_feedback_overflow_query-conditional_render_single", + test_overflow_single, + "conditional_render" + }, + { + "arb_transform_feedback_overflow_query-conditional_render_no_overflow_single", + "arb_transform_feedback_overflow_query-conditional_render_no_overflow_single", + test_no_overflow_single, + "conditional_render" + }, + { + "arb_transform_feedback_overflow_query-buffer_object_single", + "arb_transform_feedback_overflow_query-buffer_object_single", + test_overflow_single, + "buffer_object" + }, + { + "arb_transform_feedback_overflow_query-buffer_object_no_overflow_single", + "arb_transform_feedback_overflow_query-buffer_object_no_overflow_single", + test_no_overflow_single, + "buffer_object" + }, + { + "arb_transform_feedback_overflow_query-simple_query_0", + "arb_transform_feedback_overflow_query-simple_query_0", + test_overflow_stream_0, + "simple_query" + }, + { + "arb_transform_feedback_overflow_query-simple_query_1", + "arb_transform_feedback_overflow_query-simple_query_1", + test_overflow_stream_1, + "simple_query" + }, + { + "arb_transform_feedback_overflow_query-simple_query_2", + "arb_transform_feedback_overflow_query-simple_query_2", + test_overflow_stream_2, + "simple_query" + }, + { + "arb_transform_feedback_overflow_query-simple_query_any", + "arb_transform_feedback_overflow_query-simple_query_any", + test_overflow_stream_any, + "simple_query" + }, + { + "arb_transform_feedback_overflow_query-simple_query_no_overflow", + "arb_transform_feedback_overflow_query-simple_query_no_overflow", + test_no_overflow_stream_any, + "simple_query" + }, + { + "arb_transform_feedback_overflow_query-conditional_render_0", + "arb_transform_feedback_overflow_query-conditional_render_0", + test_overflow_stream_0, + "conditional_render" + }, + { + "arb_transform_feedback_overflow_query-conditional_render_1", + "arb_transform_feedback_overflow_query-conditional_render_1", + test_overflow_stream_1, + "conditional_render" + }, + { + "arb_transform_feedback_overflow_query-conditional_render_2", + "arb_transform_feedback_overflow_query-conditional_render_2", + test_overflow_stream_2, + "conditional_render" + }, + { + "arb_transform_feedback_overflow_query-conditional_render_any", + "arb_transform_feedback_overflow_query-conditional_render_any", + test_overflow_stream_any, + "conditional_render" + }, + { + "arb_transform_feedback_overflow_query-conditional_render_no_overflow", + "arb_transform_feedback_overflow_query-conditional_render_no_overflow", + test_no_overflow_stream_any, + "conditional_render" + }, + { + "arb_transform_feedback_overflow_query-buffer_object_0", + "arb_transform_feedback_overflow_query-buffer_object_0", + test_overflow_stream_0, + "buffer_object" + }, + { + "arb_transform_feedback_overflow_query-buffer_object_1", + "arb_transform_feedback_overflow_query-buffer_object_1", + test_overflow_stream_1, + "buffer_object" + }, + { + "arb_transform_feedback_overflow_query-buffer_object_2", + "arb_transform_feedback_overflow_query-buffer_object_2", + test_overflow_stream_2, + "buffer_object" + }, + { + "arb_transform_feedback_overflow_query-buffer_object_any", + "arb_transform_feedback_overflow_query-buffer_object_any", + test_overflow_stream_any, + "buffer_object" + }, + { + "arb_transform_feedback_overflow_query-buffer_object_no_overflow", + "arb_transform_feedback_overflow_query-buffer_object_no_overflow", + test_no_overflow_stream_any, + "buffer_object" + }, + {0}, +}; + +void +piglit_init(int argc, char **argv) +{ + enum piglit_result result = PIGLIT_SKIP; + const char **selected_subtests = NULL; + size_t num_selected_subtests = 0; + const struct piglit_subtest *subtests = overflow_query_subtests; + + piglit_require_extension("GL_ARB_transform_feedback_overflow_query"); + + /* Strip common piglit args. */ + piglit_strip_arg(&argc, argv, "-fbo"); + piglit_strip_arg(&argc, argv, "-auto"); + piglit_parse_subtest_args(&argc, argv, subtests, &selected_subtests, + &num_selected_subtests); + + if (argc > 1) { + fprintf(stderr, "usage error\n"); + piglit_report_result(PIGLIT_FAIL); + } + + result = piglit_run_selected_subtests(subtests, selected_subtests, + num_selected_subtests, result); + piglit_report_result(result); +} + +enum piglit_result +piglit_display(void) +{ + /* Should never be reached */ + return PIGLIT_FAIL; +} -- 2.7.4 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/piglit