diff options
author | Laura Ekstrand <laura@jlekstrand.net> | 2015-01-12 14:20:39 -0800 |
---|---|---|
committer | Laura Ekstrand <laura@jlekstrand.net> | 2015-03-09 16:20:42 -0700 |
commit | 4ea10b0e49ad8e0c1c8ce0e5f6d3d07956f26e30 (patch) | |
tree | 17dc904c7b4c09e1cc07039083a512d92901a5ec | |
parent | 4063baa1571d964f2be46ce9b43eb01f25496255 (diff) |
arb_sync: Test to demonstrate ClientWaitSync bug.
glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED)
often returns GL_TIMEOUT_EXPIRED, even though GL_TIMEOUT_IGNORED is a huge
integer (18446744073709551615 on Intel Sandybridge with Mesa). The third
argument to glClientWaitSync should represent the number of nanoseconds the
implementation waits for the signal from fence before giving up and returning
TIMEOUT_EXPIRED.
This test, adapted from bufferstorage-persistent, demonstrates that
glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED)
must be called multiple times before the signal is actually recorded and
either GL_CONDITION_SATISFIED or GL_ALREADY_SIGNALED is returned.
-rw-r--r-- | tests/all.py | 1 | ||||
-rw-r--r-- | tests/spec/arb_sync/CMakeLists.gl.txt | 1 | ||||
-rw-r--r-- | tests/spec/arb_sync/ClientWaitSync-timeout.c | 203 |
3 files changed, 205 insertions, 0 deletions
diff --git a/tests/all.py b/tests/all.py index 89501d2a1..9adf38d8c 100644 --- a/tests/all.py +++ b/tests/all.py @@ -1754,6 +1754,7 @@ with profile.group_manager( g(['arb_sync-sync-initialize'], 'sync-initialize') g(['arb_sync-timeout-zero'], 'timeout-zero') g(['arb_sync-WaitSync-errors'], 'WaitSync-errors') + g(['arb_sync-ClientWaitSync-timeout'], 'ClientWaitSync-timeout') g(['sync_api'], run_concurrent=False) # Group ARB_ES2_compatibility diff --git a/tests/spec/arb_sync/CMakeLists.gl.txt b/tests/spec/arb_sync/CMakeLists.gl.txt index 8784ff777..0a55eef76 100644 --- a/tests/spec/arb_sync/CMakeLists.gl.txt +++ b/tests/spec/arb_sync/CMakeLists.gl.txt @@ -19,3 +19,4 @@ piglit_add_executable (arb_sync-repeat-wait repeat-wait.c) piglit_add_executable (arb_sync-sync-initialize sync-initialize.c) piglit_add_executable (arb_sync-timeout-zero timeout-zero.c) piglit_add_executable (arb_sync-WaitSync-errors WaitSync-errors.c) +piglit_add_executable (arb_sync-ClientWaitSync-timeout ClientWaitSync-timeout.c) diff --git a/tests/spec/arb_sync/ClientWaitSync-timeout.c b/tests/spec/arb_sync/ClientWaitSync-timeout.c new file mode 100644 index 000000000..39875fa61 --- /dev/null +++ b/tests/spec/arb_sync/ClientWaitSync-timeout.c @@ -0,0 +1,203 @@ +/* + * Copyright © 2014 Advanced Micro Devices, Inc. + * All rights reserved. + * Copyright 2015 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. + * + * Authors: + * Marek Olšák <marek.olsak@amd.com> + * Laura Ekstrand <laura@jlekstrand.net> + * + * Adapted to demonstrate a bug in ClientWaitSync by Laura Ekstrand + * <laura@jlekstrand.net>, January 2015 + */ + +#include "piglit-util-gl.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 10; + config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE; + +PIGLIT_GL_TEST_CONFIG_END + +#define BUF_SIZE (12 * 4 * sizeof(float)) + +void +piglit_init(int argc, char **argv) +{ + piglit_require_gl_version(15); + piglit_require_extension("GL_ARB_buffer_storage"); + piglit_require_extension("GL_ARB_map_buffer_range"); + piglit_require_extension("GL_ARB_copy_buffer"); + piglit_require_extension("GL_ARB_sync"); + + piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); +} + +bool +create_mapped_buffer(GLuint *buffer, GLfloat **map, GLboolean coherent, + GLboolean client_storage) +{ + glGenBuffers(1, buffer); + glBindBuffer(GL_ARRAY_BUFFER, *buffer); + glBufferStorage(GL_ARRAY_BUFFER, BUF_SIZE, NULL, + GL_MAP_WRITE_BIT | + GL_MAP_PERSISTENT_BIT | + (coherent ? GL_MAP_COHERENT_BIT : 0) | + GL_DYNAMIC_STORAGE_BIT | + (client_storage ? GL_CLIENT_STORAGE_BIT : 0)); + + piglit_check_gl_error(GL_NO_ERROR); + + *map = glMapBufferRange(GL_ARRAY_BUFFER, 0, BUF_SIZE, + GL_MAP_WRITE_BIT | + GL_MAP_PERSISTENT_BIT | + (coherent ? GL_MAP_COHERENT_BIT : 0)); + + piglit_check_gl_error(GL_NO_ERROR); + + if (!*map) + return false; + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + return true; +} + +static enum piglit_result result = PIGLIT_PASS; +static float array[] = { + 17, 13, 0, + 17, 18, 0, + 12, 13, 0, + 12, 18, 0, + 27, 13, 0, + 27, 18, 0, + 22, 13, 0, + 22, 18, 0, + 37, 13, 0, + 37, 18, 0, + 32, 13, 0, + 32, 18, 0, + 47, 13, 0, + 47, 18, 0, + 42, 13, 0, + 42, 18, 0 +}; + +void +read_subtest(GLboolean coherent, GLboolean client_storage) +{ + GLuint buffer; + GLfloat *map; + bool pass = true; + + int i; + GLuint srcbuf; + GLsync fence; + GLenum wait_cond = GL_TIMEOUT_EXPIRED; + int try_counter = 0; + + if (!create_mapped_buffer(&buffer, &map, coherent, client_storage)) { + piglit_report_subtest_result(PIGLIT_FAIL, + "read%s%s", coherent ? " coherent" : "", + client_storage ? " client-storage" : ""); + result = PIGLIT_FAIL; + return; + } + + glClear(GL_COLOR_BUFFER_BIT); + glGenBuffers(1, &srcbuf); + glBindBuffer(GL_COPY_READ_BUFFER, srcbuf); + glBufferData(GL_COPY_READ_BUFFER, BUF_SIZE, array, GL_STATIC_DRAW); + + /* Copy some data to the mapped buffer and check if the CPU can see it. */ + glBindBuffer(GL_COPY_WRITE_BUFFER, buffer); + glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, + 0, 0, BUF_SIZE); + + glBindBuffer(GL_COPY_READ_BUFFER, 0); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + glDeleteBuffers(1, &srcbuf); + + if (!coherent) + glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); + + /* + * Wait for the GPU to flush. + * This should only take one try because ClientWaitSync with + * GL_TIMEOUT_IGNORED should wait until the signal happens and never + * return GL_TIMEOUT_EXPIRED. + */ + fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + while ((wait_cond == GL_TIMEOUT_EXPIRED) && (try_counter < 100)){ + wait_cond = glClientWaitSync(fence, + GL_SYNC_FLUSH_COMMANDS_BIT, + GL_TIMEOUT_IGNORED); + printf("glClientWaitSync returned %s.\n", + piglit_get_gl_enum_name(wait_cond)); + try_counter++; + + if (wait_cond == GL_WAIT_FAILED) { + /* Give up */ + pass = false; + break; + } + } + + for (i = 0; i < ARRAY_SIZE(array); i++) { + if (map[i] != array[i]) { + printf("Probe [%i] failed. Expected: %f Observed: %f\n", + i, array[i], map[i]); + pass = false; + } + } + + if (try_counter > 1) { + printf("glClientWaitSync called more than once" + " (%d total times).\n", try_counter); + pass = false; + } + + piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL, + "read%s%s", coherent ? " coherent" : "", + client_storage ? " client-storage" : ""); + + if (!pass) + result = PIGLIT_FAIL; +} + +enum piglit_result +piglit_display(void) +{ + /* !Coherent read subtests: require MemoryBarrier */ + if (piglit_is_extension_supported( + "GL_ARB_shader_image_load_store")) { + read_subtest(false, false); + read_subtest(false, true); + } + + /* Coherent read subtests */ + read_subtest(true, false); + read_subtest(true, true); + + return result; +} |