Skip to content

Instantly share code, notes, and snippets.

@yui0
Last active December 16, 2020 09:40
Show Gist options
  • Save yui0/5388d4b8a408e05ea4ebcddd233bee3a to your computer and use it in GitHub Desktop.
Save yui0/5388d4b8a408e05ea4ebcddd233bee3a to your computer and use it in GitHub Desktop.
gpgpu_gl.c
//---------------------------------------------------------
// Cat's eye
//
// ©2020 Yuichiro Nakada
//---------------------------------------------------------
// clang -Os gpgpu_gl.c -o gpgpu_gl `pkg-config --libs --cflags gl egl gbm` -lglfw
// clang -Os gpgpu_gl.c -o gpgpu_gl `pkg-config --libs --cflags glesv2 egl gbm` -lglfw
// dnf install mesa-libgbm-devel libdrm-devel mesa-libGL-devel mesa-libGLU-devel mesa-libEGL-devel mesa-libGLES-devel glfw-
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif
//#define GLFW_INCLUDE_GLU
#ifdef _WIN32
#include <windows.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#elif __APPLE__
#include <OpenGL/gl3.h>
#include <GLFW/glfw3.h>
#elif __linux
#ifdef GPGPU_USE_GLES
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl32.h>
#include <GLES3/gl3ext.h>
//#define GL_CLAMP_TO_BORDER GL_CLAMP_TO_BORDER_OES
#else
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#endif
//#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#define _STRGF(x) # x
#define STRINGIFY(x) _STRGF(x)
//\n#extension GL_ARB_compute_shader: enable\n
const char compute_shader_source[] = STRINGIFY(
\n#version 430\n
uniform uint element_size;
layout(std430, binding = 3) buffer layout_dst
{
float dst[];
};
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
void main() {
uint index = gl_GlobalInvocationID.x;
if (index >= element_size) { return; }
dst[index] = mix(0.0, 3.141592653589, float(index) / element_size);
}
);
void initOpenGL()
{
if (!glfwInit()) {
printf("Can't initialize GLFW.\n");
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
GLFWwindow *window = glfwCreateWindow(1, 1, "invisible", 0, 0);
if (!window) {
glfwTerminate();
//assert(!"glfwCreateWindow error!");
}
glfwMakeContextCurrent(window);
#ifdef _WIN32
#pragma comment(lib, "glew32.lib")
int r = glewInit();
if (r != GLEW_OK) {
printf("error at glewInit!! (%s)\n", glewGetErrorString(r));
}
#endif
printf("%s: OpenGL %s\n", glGetString(GL_RENDERER), glGetString(GL_VERSION));
}
void terminateOpenGL()
{
glfwTerminate();
}
GLuint createComputeShaderProgram(const char* shader_src)
{
GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
glShaderSource(shader, 1, &shader_src, 0);
glCompileShader(shader);
GLint compiles = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiles);
if (compiles == GL_FALSE) {
GLint log_length = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
char *info_log = calloc(log_length, sizeof(char));
glGetShaderInfoLog(shader, log_length, &log_length, info_log);
glDeleteShader(shader);
printf("%s\n", info_log);
printf("\n%s\n", shader_src);
free(info_log);
}
GLuint program = glCreateProgram();
glAttachShader(program, shader);
glLinkProgram(program);
GLint links = 0;
glGetProgramiv(program, GL_LINK_STATUS, &links);
if (links == GL_FALSE) {
GLint log_length = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
char *info_log = calloc(log_length, sizeof(char));
glGetProgramInfoLog(program, log_length, &log_length, info_log);
glDeleteProgram(program);
glDeleteShader(shader);
printf("%s\n", info_log);
free(info_log);
}
glDetachShader(program, shader);
glDeleteShader(shader);
return program;
}
void compute()
{
uint32_t num = 10000;
// uint32_t num = 10;
GLuint shader_program = createComputeShaderProgram(compute_shader_source);
// create buffer
GLuint uniform_element_size = glGetUniformLocation(shader_program, "element_size");
GLuint ssbo;
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, num * sizeof(float), 0, GL_DYNAMIC_COPY);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glUseProgram(shader_program);
glUniform1ui(uniform_element_size, num);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo);
glDispatchCompute(num / 256 + 1, 1, 1);
glUseProgram(0);
float data[num];
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, num * sizeof(float), data);
//glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, num * sizeof(float), data);
// GLvoid* p = glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
// memcpy(p, &shader_data, sizeof(shader_data));
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
/*glBindBuffer(GL_ARRAY_BUFFER, ssbo);
GLvoid* p = glMapBufferRange(GL_ARRAY_BUFFER, 0, num * sizeof(float), GL_MAP_READ_BIT);
//GLvoid *p = glMapBufferOES(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_ACCESS_OES);
printf("%x\n",p);
memcpy(data, p, num * sizeof(float));
glBindBuffer(GL_ARRAY_BUFFER, 0);*/
for (int i=0; i<num; i++) printf("%f ", data[i]);
glDeleteBuffers(1, &ssbo);
glDeleteProgram(shader_program);
}
int main(int argc, char* argv[])
{
initOpenGL();
compute();
terminateOpenGL();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment