diff options
author | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2017-08-25 12:48:33 +0200 |
---|---|---|
committer | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2017-10-11 12:05:22 +0200 |
commit | f4488ee9402fed10205e9963ea2a15f385675a76 (patch) | |
tree | 25332487162c114fee598bb0715f285ab406c912 | |
parent | 11ccc0a9b9fb65c0f7e8be9d8a147192c8f2948e (diff) |
arb_query_buffer_object: add additional coherency tests
The existing tests only test that shaders receive the query result.
The new tests also check for earlier pipeline stages.
-rw-r--r-- | tests/all.py | 1 | ||||
-rw-r--r-- | tests/spec/arb_query_buffer_object/CMakeLists.gl.txt | 1 | ||||
-rw-r--r-- | tests/spec/arb_query_buffer_object/coherency.c | 441 |
3 files changed, 443 insertions, 0 deletions
diff --git a/tests/all.py b/tests/all.py index 404c13f3e..fdb4a3e71 100644 --- a/tests/all.py +++ b/tests/all.py @@ -4887,6 +4887,7 @@ with profile.test_list.group_manager( PiglitGLTest, grouptools.join('spec', 'arb_query_buffer_object')) as g: g(['arb_query_buffer_object-qbo'], 'qbo') + g(['arb_query_buffer_object-coherency'], 'coherency') with profile.test_list.group_manager( PiglitGLTest, diff --git a/tests/spec/arb_query_buffer_object/CMakeLists.gl.txt b/tests/spec/arb_query_buffer_object/CMakeLists.gl.txt index 30a545546..82484c81e 100644 --- a/tests/spec/arb_query_buffer_object/CMakeLists.gl.txt +++ b/tests/spec/arb_query_buffer_object/CMakeLists.gl.txt @@ -9,5 +9,6 @@ link_libraries( ) piglit_add_executable(arb_query_buffer_object-qbo qbo.c common.c) +piglit_add_executable(arb_query_buffer_object-coherency coherency.c common.c) # vim: ft=cmake: diff --git a/tests/spec/arb_query_buffer_object/coherency.c b/tests/spec/arb_query_buffer_object/coherency.c new file mode 100644 index 000000000..834daba0d --- /dev/null +++ b/tests/spec/arb_query_buffer_object/coherency.c @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2017 Advanced Micro Devices, Inc. + * + * 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 qbo-coherency.c + * Test coherency of ARB_query_buffer_object results with pre-shader pipeline + * stages: + * 1. Indirect draw + * Write the qbo result to the 'first' member of the indirect draw + * structure, and write the gl_VertexID to a transform feedback buffer. + * 2. Index buffer fetch + * Write the qbo result to the index buffer, and write the gl_VertexID to + * a transform feedback buffer. + * 3. Indirect draw count + * Write the qbo result to the 'drawcount' value for an + * GL_ARB_indirect_parameters multi-draw, and increment an atomic counter + * in the vertex shader. + * 4. Indirect dispatch + * Write the qbo result to the number of groups, and count the groups using + * an atomic counter. + */ + +#include "common.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + config.supports_gl_compat_version = 32; + config.supports_gl_core_version = 32; + config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE | + PIGLIT_GL_VISUAL_DEPTH; +PIGLIT_GL_TEST_CONFIG_END + +#define BUFFER_OFFSET(i) ((void *)((char *)NULL + i)) + +#define DRAW_COUNT_CLAMP_MAX 50 + +static GLuint prog_compute; +static GLuint prog_xfb; +static GLuint prog_vs_atomic; +static GLuint empty_vao; +static GLuint indirect_draw_count_data_bo; + +static const char *arg_consumer_mode; +static const char *arg_query_type; + +struct consumer_mode { + const char *name; + unsigned (*run)(unsigned query); + const char *extensions[2]; + bool amplify; + bool clamped; + unsigned clamp_max; +}; + +static unsigned +indirect_draw(unsigned query) +{ + static const GLuint indirect_data[] = { + 1, /* count */ + 1, /* instanceCount */ + 999, /* first */ + 0, /* baseInstance */ + }; + unsigned indirect_bo; + unsigned xfb_bo; + + glGenBuffers(1, &indirect_bo); + glBindBuffer(GL_QUERY_BUFFER, indirect_bo); + glBufferData(GL_QUERY_BUFFER, sizeof(indirect_data), indirect_data, GL_STATIC_DRAW); + glGetQueryObjectuivARB(query, GL_QUERY_RESULT, BUFFER_OFFSET(2 * sizeof(GLuint))); + + glUseProgram(prog_xfb); + glBindVertexArray(empty_vao); + + glGenBuffers(1, &xfb_bo); + glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_bo, 0, sizeof(GLuint)); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(GLuint), NULL, GL_STREAM_READ); + + glEnable(GL_RASTERIZER_DISCARD); + glBeginTransformFeedback(GL_POINTS); + + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect_bo); + glDrawArraysIndirect(GL_POINTS, BUFFER_OFFSET(0)); + + glEndTransformFeedback(); + glDisable(GL_RASTERIZER_DISCARD); + + unsigned result; + glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(result), &result); + + glDeleteBuffers(1, &indirect_bo); + glDeleteBuffers(1, &xfb_bo); + piglit_check_gl_error(GL_NO_ERROR); + + return result; +} + +static unsigned +index_buffer(unsigned query) +{ + static const GLuint index_data[] = { + 999, + }; + unsigned index_bo; + unsigned xfb_bo; + + glGenBuffers(1, &index_bo); + glBindBuffer(GL_QUERY_BUFFER, index_bo); + glBufferData(GL_QUERY_BUFFER, sizeof(index_data), index_data, GL_STATIC_DRAW); + glGetQueryObjectuivARB(query, GL_QUERY_RESULT, BUFFER_OFFSET(0)); + + glUseProgram(prog_xfb); + glBindVertexArray(empty_vao); + + glGenBuffers(1, &xfb_bo); + glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_bo, 0, sizeof(GLuint)); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(GLuint), NULL, GL_STREAM_READ); + + glEnable(GL_RASTERIZER_DISCARD); + glBeginTransformFeedback(GL_POINTS); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_bo); + glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, BUFFER_OFFSET(0)); + + glEndTransformFeedback(); + glDisable(GL_RASTERIZER_DISCARD); + + unsigned result; + glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(result), &result); + + glDeleteBuffers(1, &index_bo); + glDeleteBuffers(1, &xfb_bo); + piglit_check_gl_error(GL_NO_ERROR); + + return result; +} + +static unsigned +indirect_draw_count(unsigned query) +{ + static const unsigned zero = 0; + static const unsigned count_default = 999; + unsigned indirect_count_bo; + unsigned atomic_bo; + + glGenBuffers(1, &indirect_count_bo); + glBindBuffer(GL_QUERY_BUFFER, indirect_count_bo); + glBufferData(GL_QUERY_BUFFER, sizeof(count_default), &count_default, GL_STATIC_DRAW); + glGetQueryObjectuivARB(query, GL_QUERY_RESULT, BUFFER_OFFSET(0)); + + glUseProgram(prog_vs_atomic); + glBindVertexArray(empty_vao); + + glGenBuffers(1, &atomic_bo); + glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atomic_bo, 0, 4); + glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, &zero, GL_STATIC_DRAW); + + glEnable(GL_RASTERIZER_DISCARD); + + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect_draw_count_data_bo); + glBindBuffer(GL_PARAMETER_BUFFER_ARB, indirect_count_bo); + glMultiDrawArraysIndirectCountARB(GL_POINTS, BUFFER_OFFSET(0), 0, + DRAW_COUNT_CLAMP_MAX, 0); + + glDisable(GL_RASTERIZER_DISCARD); + + unsigned result; + glGetBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(result), &result); + + glDeleteBuffers(1, &indirect_count_bo); + glDeleteBuffers(1, &atomic_bo); + piglit_check_gl_error(GL_NO_ERROR); + + return result; +} + +static unsigned +indirect_dispatch(unsigned query) +{ + static const GLuint indirect_data[] = { + 999, /* num_groups_x */ + 1, /* num_groups_y */ + 1, /* num_groups_z */ + }; + static const unsigned zero = 0; + unsigned indirect_bo; + unsigned atomic_bo; + + glGenBuffers(1, &indirect_bo); + glBindBuffer(GL_QUERY_BUFFER, indirect_bo); + glBufferData(GL_QUERY_BUFFER, sizeof(indirect_data), indirect_data, GL_STATIC_DRAW); + glGetQueryObjectuivARB(query, GL_QUERY_RESULT, BUFFER_OFFSET(0)); + + glUseProgram(prog_compute); + + glGenBuffers(1, &atomic_bo); + glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atomic_bo, 0, 4); + glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, &zero, GL_STATIC_DRAW); + + glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, indirect_bo); + glDispatchComputeIndirect(0); + + unsigned result; + glGetBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(result), &result); + + glDeleteBuffers(1, &indirect_bo); + glDeleteBuffers(1, &atomic_bo); + piglit_check_gl_error(GL_NO_ERROR); + + return result; +} + +static const struct consumer_mode consumer_modes[] = { + { "indirect-draw", &indirect_draw, + { "GL_ARB_draw_indirect", NULL } }, + { "index-buffer", &index_buffer, { NULL, } }, + { "indirect-draw-count", &indirect_draw_count, + { "GL_ARB_indirect_parameters", "GL_ARB_shader_atomic_counters" }, + .clamped = true, .clamp_max = DRAW_COUNT_CLAMP_MAX }, + { "indirect-dispatch", &indirect_dispatch, + { "GL_ARB_compute_shader", NULL }, + .amplify = true }, +}; + +static enum piglit_result +run_subtest(const struct consumer_mode *cm, const struct query_type_desc *qdesc) +{ + GLuint query; + bool exact; + unsigned expected, result; + + get_query_values(qdesc, &exact, &expected); + + glGenQueries(1, &query); + + run_query(query, qdesc); + result = cm->run(query); + + glDeleteQueries(1, &query); + + piglit_check_gl_error(GL_NO_ERROR); + + if (cm->clamped) + expected = MIN2(expected, cm->clamp_max); + + if (result != expected && (exact || result < expected)) { + fprintf(stderr, "Result: %u\nExpected: %u\n", result, expected); + return PIGLIT_FAIL; + } + + return PIGLIT_PASS; +} + +enum piglit_result +piglit_display(void) +{ + enum piglit_result result = PIGLIT_PASS; + unsigned qnum_count = num_query_types(); + + for (unsigned cnum = 0; cnum < ARRAY_SIZE(consumer_modes); cnum++) { + const struct consumer_mode *cm = &consumer_modes[cnum]; + bool supported = true; + + if (arg_consumer_mode && strcmp(arg_consumer_mode, cm->name)) + continue; + + for (unsigned i = 0; i < ARRAY_SIZE(cm->extensions); ++i) { + if (cm->extensions[i] && + !piglit_is_extension_supported(cm->extensions[i])) { + supported = false; + break; + } + } + + for (unsigned qnum = 0; qnum < qnum_count; qnum++) { + enum piglit_result subtest_result = PIGLIT_SKIP; + const struct query_type_desc *qdesc = &query_types[qnum]; + + if (arg_query_type && + strcmp(arg_query_type, piglit_get_gl_enum_name(qdesc->type))) + continue; + + supported = supported && is_query_supported(qdesc); + + if (cm->amplify) { + if (qdesc->type == GL_TIMESTAMP || + qdesc->type == GL_TIME_ELAPSED) + continue; + } + + if (supported) { + subtest_result = run_subtest(cm, qdesc); + if (subtest_result != PIGLIT_PASS) + result = subtest_result; + } + + piglit_report_subtest_result( + subtest_result, "%s-%s", + cm->name, + piglit_get_gl_enum_name(qdesc->type)); + } + } + + return result; +} + +static void +prepare_prog_xfb() +{ + static const char *tf_out = "tf_out"; + + prog_xfb = piglit_build_simple_program_unlinked( + "#version 130\n" + "\n" + "out int tf_out;\n" + "\n" + "void main() {\n" + " tf_out = gl_VertexID;\n" + " gl_Position = vec4(0);\n" + "}\n", + NULL); + glTransformFeedbackVaryings(prog_xfb, 1, &tf_out, GL_INTERLEAVED_ATTRIBS); + glLinkProgram(prog_xfb); + if (!piglit_link_check_status(prog_xfb)) + piglit_report_result(PIGLIT_FAIL); + piglit_check_gl_error(GL_NO_ERROR); +} + +static void +prepare_indirect_draw_count() +{ + prog_vs_atomic = piglit_build_simple_program( + "#version 150\n" + "#extension GL_ARB_shader_atomic_counters: require\n" + "\n" + "layout(binding = 0, offset = 0) uniform atomic_uint counter;\n" + "\n" + "void main() {\n" + " atomicCounterIncrement(counter);\n" + " gl_Position = vec4(0);\n" + "}\n", + NULL); + + static const GLuint indirect_draw_template[] = { + 1, /* count */ + 1, /* instanceCount */ + 0, /* first */ + 0, /* baseInstance */ + }; + + char *indirect_draw_count_data = malloc(DRAW_COUNT_CLAMP_MAX * sizeof(indirect_draw_template)); + char *dst = indirect_draw_count_data; + for (unsigned i = 0; i < DRAW_COUNT_CLAMP_MAX; ++i) { + memcpy(dst, indirect_draw_template, sizeof(indirect_draw_template)); + dst += sizeof(indirect_draw_template); + } + + glGenBuffers(1, &indirect_draw_count_data_bo); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect_draw_count_data_bo); + glBufferData(GL_DRAW_INDIRECT_BUFFER, + DRAW_COUNT_CLAMP_MAX * sizeof(indirect_draw_template), + indirect_draw_count_data, GL_STATIC_DRAW); + + free(indirect_draw_count_data); + + piglit_check_gl_error(GL_NO_ERROR); +} + +static void +prepare_prog_compute() +{ + GLuint shader = piglit_compile_shader_text(GL_COMPUTE_SHADER, + "#version 150\n" + "#extension GL_ARB_compute_shader: require\n" + "#extension GL_ARB_shader_atomic_counters: require\n" + "\n" + "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" + "\n" + "layout(binding = 0, offset = 0) uniform atomic_uint counter;\n" + "\n" + "void main() {\n" + " atomicCounterIncrement(counter);\n" + "}\n"); + + prog_compute = glCreateProgram(); + glAttachShader(prog_compute, shader); + glLinkProgram(prog_compute); + glDeleteShader(shader); + + if (!piglit_link_check_status(prog_compute)) + piglit_report_result(PIGLIT_FAIL); + piglit_check_gl_error(GL_NO_ERROR); +} + +void +piglit_init(int argc, char **argv) +{ + piglit_require_extension("GL_ARB_query_buffer_object"); + + if (argc > 1) { + if (argc != 3) { + fprintf(stderr, "usage: %s <consumer> <query_type>\n", argv[0]); + exit(1); + } + + arg_consumer_mode = argv[1]; + arg_query_type = argv[2]; + } + + query_common_init(); + + prepare_prog_xfb(); + + if (piglit_is_extension_supported("GL_ARB_compute_shader")) + prepare_prog_compute(); + + if (piglit_is_extension_supported("GL_ARB_indirect_parameters") && + piglit_is_extension_supported("GL_ARB_shader_atomic_counters")) + prepare_indirect_draw_count(); + + glGenVertexArrays(1, &empty_vao); +} |