chevydevil

CL/GL Interop with c++ bindings

Discussion created by chevydevil on Jan 9, 2010
Latest reply on May 16, 2012 by Meteorhead

I'm trying to get the interop with the c++ bindings to run under windows. Is it possible and if what do i have to do? In the cl.hpp are the clEnqueueAcquireObject and clEnqueueReleaseObjects forwarded so I thought there has to be a way. Here is my source code:

///Kernel//////////// #pragma OPENCL EXTENSION cl_khr_gl_sharing : enable __kernel void squareArray( __global float* input2, __global float* output, float stime) { output[get_global_id(0)] = input2[get_global_id(0)]*stime; }; /////cl_test.hpp/////////////////// #include <utility> #define __NO_STD_VECTOR // Use cl::vector and cl::string and #define __NO_STD_STRING // not STL versions, more on this later #include <gl/glee.h> #include <gl/Gl.h> #include <gl/glu.h> #include <gl/glut.h> #include <CL/cl.hpp> #include <cl/cl_gl.h> #include <cstdio> #include <cstdlib> #include <fstream> #include <iostream> #include <string> #include <ctime> const size_t problemSize = 4000000; class CL_test { public: CL_test(); ~CL_test(); void setupCL(); void setupCLKernels(const char*, const char*); void runCLKernels(); cl_float random(cl_float, cl_float); void updatekernel(cl_float); inline void checkErr(cl_int, const char*); cl::Context context; cl::Kernel kernel; cl::vector<cl::Device> devices; cl::Program program; cl::CommandQueue cmdQ; cl_int err; cl::Buffer inputBuffer; cl::Buffer inputBuffer2; cl::Buffer outputBuffer; cl_float stime; cl_float input[problemSize]; cl_float input2[problemSize]; cl_float output[problemSize]; GLuint vbo[1]; cl_mem out; protected: void allocateMemory(); private: }; ////////////cl_test.cpp/////////////////// #include "cl_test.hpp" CL_test::CL_test(){ stime = 0.02; }; CL_test::~CL_test(){ #if defined (_WIN32) _aligned_free(output); _aligned_free(input2); _aligned_free(input); #else free(output); free(input2); free(input); #endif } inline void CL_test::checkErr(cl_int err, const char *name){ if (err != CL_SUCCESS) { std::cerr << "ERROR: " << name << "("<< err <<")" << std::endl; //exit(EXIT_FAILURE); } } cl_float CL_test::random(cl_float low, cl_float high){ cl_float range = high - low; cl_float multiplier = ( cl_float ) rand() / RAND_MAX; return range * multiplier + low; } void CL_test::setupCL(){ //create context containing the target devices cl::vector<cl::Platform> platforms; err = cl::Platform::get(&platforms); checkErr(err, "Platform::get()"); // cl::vector<cl::Platform>::iterator i; // for (i = platforms.begin(); i!= platforms.end(); ++i) { // // pick a platform and do something // std::cout<< " Platform Name: " << (*i).getInfo<CL_PLATFORM_VENDOR>().c_str() << std::endl; // } cl::vector<cl::Platform>::iterator i; if(platforms.size() > 0) { for(i = platforms.begin(); i != platforms.end(); ++i) { std::cout<<(*i).getInfo<CL_PLATFORM_VENDOR>().c_str()<<std::endl; if(!strcmp((*i).getInfo<CL_PLATFORM_VENDOR>().c_str(), "Advanced Micro Devices, Inc.")) { break; } } } err = (*i).getDevices(CL_DEVICE_TYPE_GPU, &devices); checkErr(err, "Device::getDevice"); // cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(*i)(), 0 }; //is this right or do i miss something? cl_context_properties lProperties[] = {CL_CONTEXT_PLATFORM, (cl_context_properties)(*i)(),CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(), CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(), 0 }; // cl::Context context(CL_DEVICE_TYPE_GPU, cps, NULL, NULL, &err); context = cl::Context(devices, lProperties, NULL, NULL, &err); checkErr(err, "Context::Context()"); } void CL_test::setupCLKernels(const char* _kernelfile, const char* _kernelname){ //read __kernels std::ifstream file(_kernelfile); checkErr(file.is_open() ? CL_SUCCESS:-1, _kernelfile); std::string prog( std::istreambuf_iterator<char>(file), (std::istreambuf_iterator<char>())); //Gather all the kernel sources for the OpenCL program cl::Program::Sources source; source.push_back(std::make_pair(prog.c_str(), prog.length()+1)); //Make an OpenCl program program= cl::Program (context, source); //get all available devices in context devices = context.getInfo<CL_CONTEXT_DEVICES>(); checkErr(devices.size() > 0 ? CL_SUCCESS : -1, "devices.size() > 0"); //build kernel source for devices in context err = program.build(devices); checkErr(err, "Program::build()"); //get squareArray kernel = cl::Kernel(program, _kernelname, &err); checkErr(err, "Program::build()"); allocateMemory(); err=clEnqueueAcquireGLObjects(cmdQ, 1, &out, 0, NULL,NULL); //doesnt work because cmdQ is cl:CommandCueue checkErr(err, "clEnqueueAcquireGLObjects"); // err = kernel.setArg(0, inputBuffer); // checkErr(err, "kernel.setarg0)"); err = kernel.setArg(0, inputBuffer2); checkErr(err, "kernel.setarg1"); err = kernel.setArg(1, out); checkErr(err, "kernel.setarg2)"); err = kernel.setArg(2, stime); checkErr(err, "kernel.setarg3"); cmdQ.finish(); } void CL_test::runCLKernels(){ //Get a Functor which will run the kernel on every input item in blocks of 64 threads cl::KernelFunctor func =kernel.bind(cmdQ, cl::NDRange(problemSize), cl::NDRange(200) ); //wait for kernel to finish func().wait(); //for outputdata // cmdQ.enqueueReadBuffer(outputBuffer, // true, // 0, // sizeof(cl_float) * problemSize, // &output[0]); // err = clEnqueueReleaseGLObjects(cmdQ, 1, &out, 0, NULL, NULL); //same problem as above // checkErr(err, "clEnqueueReleaseGLObjects"); std::cout<<"!"; } void CL_test::allocateMemory(){ //queue for jobs on specified compute device cmdQ = cl::CommandQueue(context, devices[0],0, &err); checkErr(err, "CommandQueue::CommandQueue"); //allocate memory for input // inputBuffer = cl::Buffer(context, // CL_MEM_READ_ONLY, // sizeof(cl_float) * problemSize, // 0, // &err // ); // checkErr(err,"Buffer::inputBuffer"); inputBuffer2 = cl::Buffer(context, CL_MEM_READ_ONLY, sizeof(cl_float) * problemSize, 0, &err ); checkErr(err,"Buffer::inputBuffer"); //clEnqueueAcquireGLObjects() // cmdQ.enqueueWriteBuffer(inputBuffer, // CL_TRUE, // 0, // sizeof(cl_float) * problemSize, // input); cmdQ.enqueueWriteBuffer(inputBuffer2, CL_TRUE, 0, sizeof(cl_float) * problemSize, input2); //allocate memory for output out = clCreateFromGLBuffer(context,CL_MEM_READ_WRITE, vbo[0],&err); //again cl_context vs cl::Context checkErr(err,"createFromOpenGLBuffer"); } void CL_test::updatekernel(cl_float _stime){ err = kernel.setArg(2, _stime); checkErr(err, "kernel.setarg1"); } ///main.cpp #include "cl_test.hpp" CL_test test; cl_float up=0.0; // rotation values for the navigation float rotation[3] = { 0.0, 0.0, 0.0 }; //----------------------------------------------------------------------------- // parameters for the navigation // position of the mouse when pressed int mousePressedX = 0, mousePressedY = 0; // mouse button states int leftMouseButtonActive = 0; //----------------------------------------------------------------------------- void mouseFunc(int button, int state, int x, int y) { // get the mouse buttons if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) leftMouseButtonActive += 1; else leftMouseButtonActive -= 1; mousePressedX = x; mousePressedY = y; } //----------------------------------------------------------------------------- void mouseMotionFunc(int x, int y) { // rotation if (leftMouseButtonActive) { rotation[0] += ((mousePressedY - y)); rotation[1] += ((mousePressedX - x)); mousePressedY = y; mousePressedX = x; } } //----------------------------------------------------------------------------- void init(){ for (int i=0; i<problemSize-3; i+=3){ test.output[i]=test.random(0.1,30.0); test.output[i+1]=test.random(0.1,30); test.output[i+2]=test.random(0.1,30.0); } for (int i=0; i<problemSize-3; i+=3){ test.input2[i]=test.random(0.1,30.0); test.input2[i+1]=test.random(0.1,30); test.input2[i+2]=test.random(0.1,30.0); } glGenBuffers(1, test.vbo); glBindBuffer(GL_ARRAY_BUFFER, test.vbo[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(cl_float) * problemSize, test.output, GL_DYNAMIC_COPY_ARB); glBindBuffer(GL_ARRAY_BUFFER, 0); } void idlefunc(){ up +=0.002; if (up>=15) { up=0.0; } test.updatekernel(up); glutPostRedisplay(); } void draw(){ glBindBuffer(GL_ARRAY_BUFFER, test.vbo[0]); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, 0); glDrawArrays(GL_POINTS, 0, problemSize/3); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableClientState(GL_VERTEX_ARRAY); } void displayfunc() { glClearColor(0.0 ,0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); glPointSize(1.0); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glColor3f(1.0f,0.0f,1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef( rotation[0], 1.0f, 0.0f, 0.0f ); glRotatef( rotation[1], 0.0f, 1.0f, 0.0f ); test.runCLKernels(); draw(); glFlush(); glutSwapBuffers(); } void reShape(int w,int h) { glViewport(0, 0, w, h); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(33.0, 1.33, 1.0, 1000.0); glTranslatef(-10.0,-10.0,-120.0); //gluLookAt (0.0, 0.0, -2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0); } int main(int argc,char** argv) { glutInit(&argc, argv); glutInitWindowSize (640, 480); glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("GLEW Test"); glutMouseFunc (mouseFunc); glutMotionFunc (mouseMotionFunc); glutDisplayFunc(displayfunc); glutReshapeFunc(reShape); glutIdleFunc(idlefunc); test.setupCL(); init(); test.setupCLKernels("lesson1_kernels.cl","squareArray"); glutMainLoop(); return 0; }

Outcomes