[Piglit] [RFC] egl: runtime test for EGL_IMG_context_priority extension

Tapani Pälli tapani.palli at intel.com
Wed May 17 08:28:46 UTC 2017


Test creates 2 threads which both run a shader that increments atomic
counter. Assumption is that thread with higher priority set will be
given more time and counter value should be higher. However since the
extension does not set absolute requirement, we do not fail but simply
skip if the assumption is not met.

Signed-off-by: Tapani Pälli <tapani.palli at intel.com>
---

This is an attempt to write a runtime test for EGL_IMG_context_priority.
I got comment from Curro that I should rather try to utilize query for 
GL_TIMESTAMP to measure which thread used more time to execute given
task but then I noticed this query is not available for GLES. I'll be
experimenting with a desktop test with that but here's a GLES version
with counter comparison. I would appreciate any comments and actual real
testing results if you have all needed bits for extension and can run
this test.

Thanks;


 tests/all.py                             |   1 +
 tests/egl/CMakeLists.gles3.txt           |  12 ++
 tests/egl/egl-context-priority-runtime.c | 261 +++++++++++++++++++++++++++++++
 3 files changed, 274 insertions(+)
 create mode 100644 tests/egl/CMakeLists.gles3.txt
 create mode 100644 tests/egl/egl-context-priority-runtime.c

diff --git a/tests/all.py b/tests/all.py
index 49a8c9f..885f54d 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -4547,6 +4547,7 @@ with profile.test_list.group_manager(
       run_concurrent=False)
     g(['egl-invalid-attr'])
     g(['egl-context-priority'])
+    g(['egl-context-priority-runtime'])
 
 with profile.test_list.group_manager(
         PiglitGLTest,
diff --git a/tests/egl/CMakeLists.gles3.txt b/tests/egl/CMakeLists.gles3.txt
new file mode 100644
index 0000000..3a520a3
--- /dev/null
+++ b/tests/egl/CMakeLists.gles3.txt
@@ -0,0 +1,12 @@
+
+link_libraries (
+	piglitutil_${piglit_target_api}
+	${EGL_LDFLAGS}
+)
+
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+	piglit_add_executable (egl-context-priority-runtime egl-context-priority-runtime.c)
+	target_link_libraries(egl-context-priority-runtime pthread)
+ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+# vim: ft=cmake:
diff --git a/tests/egl/egl-context-priority-runtime.c b/tests/egl/egl-context-priority-runtime.c
new file mode 100644
index 0000000..c220125
--- /dev/null
+++ b/tests/egl/egl-context-priority-runtime.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2017 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-egl.h"
+#include "piglit-util-gl.h"
+#include <unistd.h>
+#ifdef PIGLIT_HAS_PTHREADS
+#include <pthread.h>
+#endif
+
+/**
+ * @file egl-context-priority-runtime.c
+ *
+ * EGL runtime test for IMG_context_priority extension:
+ * https://www.khronos.org/registry/EGL/extensions/IMG/EGL_IMG_context_priority.txt
+ */
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_es_version = 31;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+/* global */
+static EGLDisplay dpy;
+static bool test_active;
+static pthread_mutex_t mutex;
+
+const char *vs_source =
+        "#version 310 es\n"
+        "in vec4 piglit_vertex;\n"
+        "void main() {\n"
+        "       gl_Position = piglit_vertex;\n"
+        "}\n";
+
+const char *fs_source =
+        "#version 310 es\n"
+        "layout(binding = 0, offset = 0) uniform atomic_uint counter;\n"
+        "void main() {\n"
+        "       atomicCounterIncrement(counter);\n"
+        "}\n";
+
+/* dummy */
+enum piglit_result
+piglit_display(void)
+{
+	return PIGLIT_FAIL;
+}
+
+static EGLint
+check_priority(EGLDisplay dpy, EGLContext ctx, EGLint *expected)
+{
+	EGLint value;
+	EGLBoolean status =
+		eglQueryContext(dpy, ctx, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value);
+
+	if (status == EGL_FALSE) {
+		fprintf(stderr, "eglQueryContext failed\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	if (expected && value != *expected) {
+		fprintf(stderr, "%s fail: value 0x%x, expected 0x%x\n",
+			__func__, value, *expected);
+		piglit_report_result(PIGLIT_SKIP);
+	}
+	return value;
+}
+
+static EGLContext
+create_context(EGLDisplay dpy, EGLint priority)
+{
+	EGLint contextAttribs[] = {
+		EGL_CONTEXT_CLIENT_VERSION, 2,
+		EGL_CONTEXT_PRIORITY_LEVEL_IMG, priority,
+		EGL_NONE
+	};
+	EGLContext ctx =
+		eglCreateContext(dpy, EGL_NO_CONFIG_MESA, EGL_NO_CONTEXT, contextAttribs);
+
+	if (ctx == EGL_NO_CONTEXT) {
+		fprintf(stderr, "could not create EGL context\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	/* verify that we got priority that was asked, skip test if not */
+	check_priority(dpy, ctx, &priority);
+
+	return ctx;
+}
+
+static uint32_t
+counter_value()
+{
+	/* Map atomic buffer and check the value. */
+	uint32_t value;
+        uint32_t *ptr =
+		(uint32_t *) glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0,
+			sizeof(uint32_t), GL_MAP_READ_BIT);
+	value = *ptr;
+	glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
+	return value;
+}
+
+static void*
+counter_thread(void *arg)
+{
+	EGLContext ctx;
+	uint32_t *result;
+	GLuint buffer, fbo = 0, vao;
+	GLint prog;
+	uint32_t counter = 0;
+
+	EGLint priority = *(EGLint*)(arg);
+
+        result = malloc(sizeof(*result));
+        *result = 0;
+
+	eglBindAPI(EGL_OPENGL_ES_API);
+
+	ctx = create_context(dpy, priority);
+
+	eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx);
+
+	/* Create fbo with no attachments. */
+	glGenFramebuffers(1, &fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+	/* Setup default width and height. */
+	glFramebufferParameteri(GL_FRAMEBUFFER,
+		GL_FRAMEBUFFER_DEFAULT_WIDTH, piglit_width);
+	glFramebufferParameteri(GL_FRAMEBUFFER,
+		GL_FRAMEBUFFER_DEFAULT_HEIGHT, piglit_height);
+
+	/* Check that fbo is marked complete. */
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
+		GL_FRAMEBUFFER_COMPLETE) {
+		fprintf(stderr, "fbo not complete\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	prog = piglit_build_simple_program(vs_source, fs_source);
+
+	/* Check that there are no errors. */
+	if (!prog || !piglit_check_gl_error(GL_NO_ERROR))
+		piglit_report_result(PIGLIT_FAIL);
+
+	glUseProgram(prog);
+
+	/* Create atomic counter buffer. */
+	glGenBuffers(1, &buffer);
+	glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, buffer);
+	glBufferData(GL_ATOMIC_COUNTER_BUFFER,
+		sizeof(uint32_t), &counter, GL_DYNAMIC_DRAW);
+
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		piglit_report_result(PIGLIT_FAIL);
+
+	/* Render rectangle using our program. */
+	glGenVertexArrays(1, &vao);
+	glBindVertexArray(vao);
+
+	glViewport(0, 0, piglit_width, piglit_height);
+
+	while (true) {
+		piglit_draw_rect(-1, -1, 2, 2);
+		glFlush();
+
+		pthread_mutex_lock(&mutex);
+		if (!test_active) {
+			pthread_mutex_unlock(&mutex);
+			break;
+		}
+		pthread_mutex_unlock(&mutex);
+	}
+
+	*result = counter_value();
+
+	eglDestroyContext(dpy, ctx);
+	return result;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	EGLint major, minor;
+	bool ok;
+
+	pthread_t thread1, thread2;
+
+	/* Require EGL_MESA_platform_surfaceless extension. */
+	const char *exts = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+	if (!strstr(exts, "EGL_MESA_platform_surfaceless"))
+		piglit_report_result(PIGLIT_SKIP);
+
+	dpy = eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA,
+				    EGL_DEFAULT_DISPLAY, NULL);
+
+	ok = eglInitialize(dpy, &major, &minor);
+	if (!ok) {
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	piglit_require_egl_extension(dpy, "EGL_IMG_context_priority");
+	piglit_require_egl_extension(dpy, "EGL_MESA_configless_context");
+
+	test_active = true;
+	pthread_mutex_init(&mutex, NULL);
+
+	EGLint high = EGL_CONTEXT_PRIORITY_HIGH_IMG;
+	EGLint low = EGL_CONTEXT_PRIORITY_LOW_IMG;
+
+	pthread_create(&thread1, NULL, counter_thread, &high);
+	pthread_create(&thread2, NULL, counter_thread, &low);
+
+	/* let them work for some time */
+	sleep(2);
+
+	pthread_mutex_lock(&mutex);
+	test_active = false;
+	pthread_mutex_unlock(&mutex);
+
+	pthread_mutex_destroy(&mutex);
+
+	uint32_t *t1_result = NULL;
+	uint32_t *t2_result = NULL;
+
+	pthread_join(thread1, (void**) &t1_result);
+	pthread_join(thread2, (void**) &t2_result);
+
+	pthread_mutex_destroy(&mutex);
+
+	/* Result is not what we are expecting with the priority levels set. Strictly
+	 * by the spec, we cannot fail so mark test as skipped.
+	 */
+	if (*t1_result < *t2_result) {
+		piglit_report_result(PIGLIT_SKIP);
+	}
+
+	piglit_report_result(PIGLIT_PASS);
+}
-- 
2.9.3



More information about the Piglit mailing list