Created
April 30, 2013 13:02
-
-
Save okaq/5488546 to your computer and use it in GitHub Desktop.
OpenCL / OpenGL Bridge
This file contains hidden or 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
/* | |
* ===================================================================================== | |
* | |
* 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