From c9dd226c676a4cc0373425257457c73b54505976 Mon Sep 17 00:00:00 2001 From: Eduardo Lima Mitev Date: Tue, 20 Sep 2016 05:06:22 +0200 Subject: [PATCH] Initial commit --- .dir-locals.el | 13 +++ .gitignore | 1 + Makefile | 5 ++ README.md | 0 render-nodes-minimal/Makefile | 12 +++ render-nodes-minimal/main.c | 165 ++++++++++++++++++++++++++++++++++ 6 files changed, 196 insertions(+) create mode 100644 .dir-locals.el create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 render-nodes-minimal/Makefile create mode 100644 render-nodes-minimal/main.c diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..d9a374c --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,13 @@ +((prog-mode + (indent-tabs-mode . nil) + (tab-width . 8) + (c-basic-offset . 3) + (c-file-style . "stroustrup") + (fill-column . 78) + (eval . (progn + (c-set-offset 'case-label '0) + (c-set-offset 'innamespace '0) + (c-set-offset 'inline-open '0))) + ) + (makefile-mode (indent-tabs-mode . t)) + ) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..571c08f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +render-nodes-minimal/render-nodes-minimal diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..98327ff --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +all: Makefile + make -C render-nodes-minimal all + +clean: + make -C render-nodes-minimal clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/render-nodes-minimal/Makefile b/render-nodes-minimal/Makefile new file mode 100644 index 0000000..1fda5a4 --- /dev/null +++ b/render-nodes-minimal/Makefile @@ -0,0 +1,12 @@ +TARGET=render-nodes-minimal + +all: Makefile $(TARGET) + +$(TARGET): main.c + gcc -ggdb -O0 -Wall -std=c99 \ + `pkg-config --libs --cflags glesv2 egl gbm` \ + -o $(TARGET) \ + main.c + +clean: + rm -f $(TARGET) diff --git a/render-nodes-minimal/main.c b/render-nodes-minimal/main.c new file mode 100644 index 0000000..9026bf3 --- /dev/null +++ b/render-nodes-minimal/main.c @@ -0,0 +1,165 @@ +/* + * Example: + * + * Render nodes (minimal): Running a compute shader in a window-less + * EGL + GLES 3.1 context. + * + * This example shows the minimum code necessary to run an OpenGL (ES) compute + * shader (aka, a general purpose program on the GPU), on Linux. + * It uses the DRM render nodes API to gain unprivileged, shared access to the + * GPU. + * + * See and + * . + * + * Tested on Linux 4.0, Mesa 12.0, Intel GPU (gen7+). + * + * Authors: + * * Eduardo Lima Mitev + * + * This code is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * version 3, or (at your option) any later version as published by + * the Free Software Foundation. + * + * THIS CODE IS PROVIDED AS-IS, WITHOUT WARRANTY OF ANY KIND, OR POSSIBLE + * LIABILITY TO THE AUTHORS FOR ANY CLAIM OR DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* a dummy compute shader that does nothing */ +#define COMPUTE_SHADER_SRC " \ +#version 310 es\n \ + \ +layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; \ + \ +void main(void) { \ + /* awesome compute code here */ \ +} \ +" + +int32_t +main (int32_t argc, char* argv[]) +{ + bool res; + + int32_t fd = open ("/dev/dri/renderD128", O_RDWR); + assert (fd > 0); + + struct gbm_device *gbm = gbm_create_device (fd); + assert (gbm != NULL); + + /* setup EGL from the GBM device */ + EGLDisplay egl_dpy = eglGetPlatformDisplay (EGL_PLATFORM_GBM_MESA, gbm, NULL); + assert (egl_dpy != NULL); + + res = eglInitialize (egl_dpy, NULL, NULL); + assert (res); + + const char *egl_extension_st = eglQueryString (egl_dpy, EGL_EXTENSIONS); + assert (strstr (egl_extension_st, "EGL_KHR_create_context") != NULL); + assert (strstr (egl_extension_st, "EGL_KHR_surfaceless_context") != NULL); + + static const EGLint config_attribs[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, + EGL_NONE + }; + EGLConfig cfg; + EGLint count; + + res = eglChooseConfig (egl_dpy, config_attribs, &cfg, 1, &count); + assert (res); + + res = eglBindAPI (EGL_OPENGL_ES_API); + assert (res); + + static const EGLint attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 3, + EGL_NONE + }; + EGLContext core_ctx = eglCreateContext (egl_dpy, + cfg, + EGL_NO_CONTEXT, + attribs); + assert (core_ctx != EGL_NO_CONTEXT); + + res = eglMakeCurrent (egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, core_ctx); + assert (res); + + /* print some compute limits (not strictly necessary) */ + GLint work_group_count[3] = {0}; + for (unsigned i = 0; i < 3; i++) + glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, + i, + &work_group_count[i]); + printf ("GL_MAX_COMPUTE_WORK_GROUP_COUNT: %d, %d, %d\n", + work_group_count[0], + work_group_count[1], + work_group_count[2]); + + GLint work_group_size[3] = {0}; + for (unsigned i = 0; i < 3; i++) + glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, i, &work_group_size[i]); + printf ("GL_MAX_COMPUTE_WORK_GROUP_SIZE: %d, %d, %d\n", + work_group_size[0], + work_group_size[1], + work_group_size[2]); + + GLint max_invocations; + glGetIntegerv (GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &max_invocations); + printf ("GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS: %d\n", max_invocations); + + GLint mem_size; + glGetIntegerv (GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &mem_size); + printf ("GL_MAX_COMPUTE_SHARED_MEMORY_SIZE: %d\n", mem_size); + + /* setup a compute shader */ + GLuint compute_shader = glCreateShader (GL_COMPUTE_SHADER); + + assert (glGetError () == GL_NO_ERROR); + const char *shader_source = COMPUTE_SHADER_SRC; + + glShaderSource (compute_shader, 1, &shader_source, NULL); + assert (glGetError () == GL_NO_ERROR); + + glCompileShader (compute_shader); + assert (glGetError () == GL_NO_ERROR); + + GLuint shader_program = glCreateProgram (); + + glAttachShader (shader_program, compute_shader); + assert (glGetError () == GL_NO_ERROR); + + glLinkProgram (shader_program); + assert (glGetError () == GL_NO_ERROR); + + glDeleteShader (compute_shader); + + glUseProgram (shader_program); + assert (glGetError () == GL_NO_ERROR); + + /* dispatch computation */ + glDispatchCompute (1, 1, 1); + assert (glGetError () == GL_NO_ERROR); + + printf ("Compute shader dispatched and finished successfully\n"); + + /* free stuff */ + glDeleteProgram (shader_program); + eglDestroyContext (egl_dpy, core_ctx); + eglTerminate (egl_dpy); + gbm_device_destroy (gbm); + close (fd); + + return 0; +}