Переглянути джерело

Add gl interop example using glutidlefunc

Samuel Thibault 13 роки тому
батько
коміт
2d353bd5bd

+ 5 - 3
doc/chapters/advanced-examples.texi

@@ -1015,9 +1015,11 @@ be enabled by using the @code{cuda_opengl_interoperability} field of the
 @code{starpu_conf} structure, and the driver loop has to be run by
 the application, by using the @code{not_launched_drivers} field of
 @code{starpu_conf} to prevent StarPU from running it in a separate thread, and
-by using @code{starpu_driver_run} to run the loop. The @code{gl_interop} example
-shows how it articulates in a simple case, where rendering is done in task
-callbacks. TODO: provide glutIdleFunc alternative.
+by using @code{starpu_driver_run} to run the loop. The @code{gl_interop} and
+@code{gl_interop_idle} examples shows how it articulates in a simple case, where
+rendering is done in task callbacks. The former uses @code{glutMainLoopEvent}
+to make GLUT progress from the StarPU driver loop, while the latter uses
+@code{glutIdleFunc} to make StarPU progress from the GLUT main loop.
 
 Then, to use an OpenGL buffer as a CUDA data, StarPU simply needs to be given
 the CUDA pointer at registration, for instance:

+ 8 - 1
examples/Makefile.am

@@ -841,13 +841,20 @@ endif
 
 if HAVE_OPENGL
 examplebin_PROGRAMS +=				\
-	gl_interop/gl_interop
+	gl_interop/gl_interop			\
+	gl_interop/gl_interop_idle
 
 gl_interop_gl_interop_SOURCES =			\
 	gl_interop/gl_interop.c
 
 gl_interop_gl_interop_LDADD =			\
 	$(STARPU_OPENGL_RENDER_LDFLAGS)
+
+gl_interop_gl_interop_idle_SOURCES =		\
+	gl_interop/gl_interop_idle.c
+
+gl_interop_gl_interop_idle_LDADD =		\
+	$(STARPU_OPENGL_RENDER_LDFLAGS)
 endif
 
 ####################

+ 1 - 1
examples/gl_interop/gl_interop.c

@@ -118,7 +118,7 @@ int main(int argc, char **argv)
 	ret = starpu_task_submit(task);
 	STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
 
-	/* And run the driver, which will run the task */
+	/* And run the driver inside main, which will run the task */
 	printf("running the driver\n");
 	starpu_driver_run(&drivers[0]);
 	printf("finished running the driver\n");

+ 152 - 0
examples/gl_interop/gl_interop_idle.c

@@ -0,0 +1,152 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2012 Université de Bordeaux 1
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+/*
+ * This example demonstrates how to use StarPU combined with OpenGL rendering,
+ * which needs:
+ *
+ * - initializing GLUT first,
+ * - enabling it at initialization,
+ * - running the corresponding CUDA worker in the GLUT thread (here, the main
+ *   thread).
+ *
+ * The difference with gl_interop.c is that this version runs StarPU Tasks in
+ * the glut idle handler.
+ */
+
+#include <starpu.h>
+#include <unistd.h>
+#include <GL/glut.h>
+
+void dummy(void *buffers[], void *cl_arg)
+{
+	float *v = (float *) STARPU_VECTOR_GET_PTR(buffers[0]);
+
+	printf("Codelet running\n");
+	cudaMemset(v, 0, STARPU_VECTOR_GET_NX(buffers[0]) * sizeof(float));
+	printf("Codelet done\n");
+}
+
+struct starpu_codelet cl = {
+	.where = STARPU_CUDA,
+	.cuda_funcs = { dummy, NULL },
+	.nbuffers = 1,
+	.modes = { STARPU_W },
+};
+
+void foo(void) {
+}
+
+void display(float i) {
+	glClear(GL_COLOR_BUFFER_BIT);
+	glColor3f(1, 1, 1);
+	glBegin(GL_LINES);
+	glVertex2f(-i, -i);
+	glVertex2f(i, i);
+	glEnd();
+	glFinish();
+	glutPostRedisplay();
+}
+
+static int cuda_devices[] = { 0 };
+static struct starpu_driver drivers[] = {
+	{ .type = STARPU_CUDA_WORKER }
+};
+
+void callback_func(void *foo) {
+	printf("Callback running, rendering\n");
+	float i = 1.;
+	while (i > 0) {
+		usleep(100000);
+		display(i);
+		i -= 0.1;
+	}
+	printf("rendering done\n");
+
+	/* Tell it was already the last submitted task */
+	starpu_drivers_request_termination();
+
+	/* And terminate StarPU */
+	starpu_driver_deinit(&drivers[0]);
+	starpu_shutdown();
+	exit(0);
+}
+
+static void idle(void)
+{
+	starpu_driver_run_once(&drivers[0]);
+}
+
+int main(int argc, char **argv)
+{
+#if !(defined(STARPU_USE_CUDA) && defined(STARPU_OPENGL_RENDER))
+	return 77;
+#else
+	struct starpu_conf conf;
+	int ret;
+	struct starpu_task *task;
+	starpu_data_handle_t handle;
+	int cuda_device = 0;
+
+	cuda_devices[0] = cuda_device;
+	drivers[0].id.cuda_id = cuda_device;
+
+	glutInit(&argc, argv);
+	glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
+	glutInitWindowPosition(0, 0);
+	glutInitWindowSize(300,200);
+	glutCreateWindow("StarPU OpenGL interoperability test");
+	glClearColor (0.5, 0.5, 0.5, 0.0);
+
+	/* Enable OpenGL interoperability */
+	starpu_conf_init(&conf);
+	conf.ncuda = 1;
+	conf.ncpus = 0;
+	conf.nopencl = 0;
+	conf.cuda_opengl_interoperability = cuda_devices;
+	conf.n_cuda_opengl_interoperability = sizeof(cuda_devices) / sizeof(*cuda_devices);
+	conf.not_launched_drivers = drivers;
+	conf.n_not_launched_drivers = sizeof(drivers) / sizeof(*drivers);
+	ret = starpu_init(&conf);
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
+
+	starpu_vector_data_register(&handle, -1, 0, 10, sizeof(float));
+
+	/* Submit just one dumb task */
+	task = starpu_task_create();
+	task->cl = &cl;
+	task->handles[0] = handle;
+	task->callback_func = callback_func;
+	task->callback_arg = NULL;
+	ret = starpu_task_submit(task);
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
+
+	/* And run the driver inside main, which will run the task */
+	printf("running the driver\n");
+	/* Initialize it */
+	starpu_driver_init(&drivers[0]);
+	/* Register driver loop content as idle handler */
+	glutIdleFunc(idle);
+	/* Now run the glut loop */
+	glutMainLoop();
+	starpu_driver_run(&drivers[0]);
+	printf("finished running the driver\n");
+
+	starpu_shutdown();
+
+	return 0;
+#endif
+}