Skip to content

Instantly share code, notes, and snippets.

@okaq
Created April 30, 2013 13:02
Show Gist options
  • Save okaq/5488546 to your computer and use it in GitHub Desktop.
Save okaq/5488546 to your computer and use it in GitHub Desktop.
OpenCL / OpenGL Bridge
/*
* =====================================================================================
*
* File: chusho.cpp
* Description: OpenGL / OpenCL Bridge
* Created: 04/24/2013 07:54:13 AM
* Compile: g++ chusho.cpp -o chusho -lglut -lOpenCL -lGLEW -std=c++0x
*
* Author: AQ <[email protected]>
* Notes: Seg Fault when run. Invalid GL buffer (catalyst, amd app sdk, unity?)
* Included for reference implementation, OpenCL calls still ok!
*
* =====================================================================================
*/
#include <array>
#include <cstdio>
#include <CL/cl.h>
#include <CL/cl_gl.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glx.h>
// globals
int gWidth = 512;
int gHeight = 512;
GLuint vbo = 0;
GLuint cbo = 0;
cl_context context;
cl_mem vbo_cl;
cl_command_queue cq_gpu;
cl_command_queue cq_apu;
cl_program program_cl;
cl_kernel kernel;
size_t global;
size_t local;
cl_device_id *device_id;
// const
const float V[] = {
0.0f, 0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 1.0f,
};
const float C[] = {
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
};
const unsigned int count = 12;
void initGLEW() {
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
}
void render(void) {
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
/*
glBindBuffer(GL_ARRAY_BUFFER, cbo);
// glEnableVertexAttribArray(3); // set attrib, point to gl_FragColor in shader
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, 0);
*/
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
// glDisableVertexAttribArray(3);
glutSwapBuffers();
return;
}
void idle() {
render();
return;
}
void reshape(int w, int h) {
return;
}
void keybd(unsigned char key, int x, int y) {
return;
}
void initVerts() {
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(V), V, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &cbo);
glBindBuffer(GL_ARRAY_BUFFER, cbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(C), C, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void initGL(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(128, 128);
glutInitWindowSize(gWidth, gHeight);
glutCreateWindow("okaq : opengl / opencl bridge");
glutDisplayFunc(render); // render
glutIdleFunc(idle);
glutReshapeFunc(reshape);
glutKeyboardFunc(keybd);
initGLEW();
// initVerts();
}
void platform() {
cl_int err;
cl_uint num_platforms;
cl_platform_id platform_id;
err = clGetPlatformIDs(1, &platform_id, &num_platforms);
fprintf(stdout, "Err: %d. Platforms: %d\n", err, num_platforms);
std::array<cl_platform_info, 5> platform_name = {
CL_PLATFORM_PROFILE,
CL_PLATFORM_VERSION,
CL_PLATFORM_NAME,
CL_PLATFORM_VENDOR,
CL_PLATFORM_EXTENSIONS
};
for (int i = 0; i < platform_name.size(); i++) {
size_t ret_size = 0;
err = clGetPlatformInfo(platform_id, platform_name[i], 0, NULL, &ret_size);
char info[ret_size];
err = clGetPlatformInfo(platform_id, platform_name[i], sizeof(info), &info, NULL);
fprintf(stdout, "name: %d, info: %s.\n", platform_name[i], info);
}
cl_uint num_devices;
err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices);
fprintf(stdout, "Num devices: %d\n.", num_devices);
// std::array<cl_device_id, num_devices> devices;
cl_device_id devices[num_devices];
err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, num_devices, devices, NULL);
for (int i = 0; i < num_devices; i++) {
size_t ret_size = 0;
err = clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 0, NULL, &ret_size);
char info[ret_size];
err = clGetDeviceInfo(devices[i], CL_DEVICE_NAME, ret_size, &info, NULL);
fprintf(stdout, "type: %s\n", info);
cl_uint uinfo;
err = clGetDeviceInfo(devices[i], CL_DEVICE_MAX_CLOCK_FREQUENCY, 4, &uinfo, NULL);
fprintf(stdout, "clock: %d\n", uinfo);
cl_device_type type;
err = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, 1, &type, NULL);
fprintf(stdout, "type: %s\n", (type == CL_DEVICE_TYPE_GPU) ? "true" : "false");
}
const cl_context_properties props[] = {
CL_GL_CONTEXT_KHR,
(cl_context_properties)glXGetCurrentContext(),
CL_GLX_DISPLAY_KHR,
(cl_context_properties)glXGetCurrentDisplay(),
CL_CONTEXT_PLATFORM,
(cl_context_properties)platform_id,
0,
};
device_id = devices;
// cl_context context;
context = clCreateContext(props, num_devices, devices, NULL, NULL, NULL);
// cl_command_queue cq_gpu;
// cl_command_queue cq_apu;
cq_gpu = clCreateCommandQueue(context, devices[0], CL_QUEUE_PROFILING_ENABLE, &err);
cq_apu = clCreateCommandQueue(context, devices[1], CL_QUEUE_PROFILING_ENABLE, &err);
}
void cleanup() {
clReleaseCommandQueue(cq_gpu);
clReleaseCommandQueue(cq_apu);
clReleaseContext(context);
clReleaseKernel(kernel);
return;
// device[0] Beavercreek GPU 444 MHz
// device[1] AMD APU 800 MHz
}
void verts() {
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 3, NULL, GL_DYNAMIC_DRAW);
// glBindBuffer(GL_ARRAY_BUFFER, 0);
cl_int err;
vbo_cl = clCreateFromGLBuffer(context, CL_MEM_READ_WRITE, vbo, &err);
fprintf(stdout, "GL Err: %s.\n", (err == CL_INVALID_GL_OBJECT) ? "true" : "false");
// amd bug?
err = clEnqueueWriteBuffer(cq_gpu, vbo_cl, CL_TRUE, 0, sizeof(float) * 4 * 3, V, 0, NULL, NULL);
fprintf(stdout, "Write Err: %s.\n", (err == CL_INVALID_MEM_OBJECT) ? "true" : "false");
}
void program() {
const char *src = "\n" \
"__kernel void move( \n" \
"__global float* vertices, \n" \
"const unsigned int num) { \n" \
"int i = get_global_id(0); \n" \
"if ((i < num) && (i % 3 != 0)) { \n" \
"vertices[i] = 1.0f;} \n" \
"} \n" \
"\n";
cl_int err;
// program = clCreateProgramWithSource;
// cl_program program_cl;
program_cl = clCreateProgramWithSource(context, 1, (const char **)&src, NULL, &err);
// err = clBuildProgram;
err = clBuildProgram(program_cl, 0, NULL, NULL, NULL, NULL);
fprintf(stdout, "Build Err: %d.\n", err);
// kernel = clCreateKernel
// cl_kernel kernel;
kernel = clCreateKernel(program_cl, "move", &err);
// err = clSetKernelArg(kernel);
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), vbo_cl);
err = clSetKernelArg(kernel, 1, sizeof(unsigned int), &count);
}
void execute() {
glFinish();
clEnqueueAcquireGLObjects(cq_gpu, 1, &vbo_cl, 0, NULL, NULL);
// size_t global;
// size_t local;
clGetKernelWorkGroupInfo(kernel, device_id[0], CL_KERNEL_WORK_GROUP_SIZE, sizeof(local), &local, NULL);
global = count;
clEnqueueNDRangeKernel(cq_gpu, kernel, 1, NULL, &global, &local, 0, NULL, NULL);
clEnqueueReleaseGLObjects(cq_gpu, 1, &vbo_cl, 0, NULL, NULL);
clFinish(cq_gpu);
}
void initCL() {
platform();
verts();
program();
execute();
return;
}
int main(int argc, char** argv) {
// initCL();
initGL(argc, argv);
initCL();
glutMainLoop();
cleanup();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment