[Piglit] [PATCH 03/15] arb_sync: Test to demonstrate ClientWaitSync bug.

Laura Ekstrand laura at jlekstrand.net
Fri Jan 23 11:03:27 PST 2015


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.
---
 tests/all.py                                 |   1 +
 tests/spec/arb_sync/CMakeLists.gl.txt        |   1 +
 tests/spec/arb_sync/ClientWaitSync-timeout.c | 203 +++++++++++++++++++++++++++
 3 files changed, 205 insertions(+)
 create mode 100644 tests/spec/arb_sync/ClientWaitSync-timeout.c

diff --git a/tests/all.py b/tests/all.py
index 7df3787..7ec9d64 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -1756,6 +1756,7 @@ arb_sync['repeat-wait'] = PiglitGLTest(['arb_sync-repeat-wait'], run_concurrent=
 arb_sync['sync-initialize'] = PiglitGLTest(['arb_sync-sync-initialize'], run_concurrent=True)
 arb_sync['timeout-zero'] = PiglitGLTest(['arb_sync-timeout-zero'], run_concurrent=True)
 arb_sync['WaitSync-errors'] = PiglitGLTest(['arb_sync-WaitSync-errors'], run_concurrent=True)
+arb_sync['ClientWaitSync-timeout'] = PiglitGLTest(['arb_sync-ClientWaitSync-timeout'], run_concurrent=True)
 add_plain_test(arb_sync, ['sync_api'])
 
 # Group ARB_ES2_compatibility
diff --git a/tests/spec/arb_sync/CMakeLists.gl.txt b/tests/spec/arb_sync/CMakeLists.gl.txt
index 8784ff7..0a55eef 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 0000000..4030a3f
--- /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 at amd.com>
+ *    Laura Ekstrand <laura at jlekstrand.net>
+ *
+ * Adapted to demonstrate a bug in ClientWaitSync by Laura Ekstrand
+ * <laura at 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;
+}
-- 
2.1.0



More information about the Piglit mailing list