mirror of
https://github.com/elima/gpu-playground.git
synced 2025-06-06 23:46:17 +00:00
Initial commit
This commit is contained in:
commit
c9dd226c67
13
.dir-locals.el
Normal file
13
.dir-locals.el
Normal file
@ -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))
|
||||||
|
)
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
render-nodes-minimal/render-nodes-minimal
|
5
Makefile
Normal file
5
Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
all: Makefile
|
||||||
|
make -C render-nodes-minimal all
|
||||||
|
|
||||||
|
clean:
|
||||||
|
make -C render-nodes-minimal clean
|
12
render-nodes-minimal/Makefile
Normal file
12
render-nodes-minimal/Makefile
Normal file
@ -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)
|
165
render-nodes-minimal/main.c
Normal file
165
render-nodes-minimal/main.c
Normal file
@ -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 <https://en.wikipedia.org/wiki/Direct_Rendering_Manager#Render_nodes> and
|
||||||
|
* <https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#render-nodes>.
|
||||||
|
*
|
||||||
|
* Tested on Linux 4.0, Mesa 12.0, Intel GPU (gen7+).
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* * Eduardo Lima Mitev <elima@igalia.com>
|
||||||
|
*
|
||||||
|
* 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 <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
#include <GLES3/gl31.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <gbm.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user