Last active
December 16, 2020 09:40
-
-
Save yui0/5388d4b8a408e05ea4ebcddd233bee3a to your computer and use it in GitHub Desktop.
gpgpu_gl.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//--------------------------------------------------------- | |
// 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