最近在學習OpenGL,過程中需要使用CUDA進行並行計算。因此,需要解決OpenGL與CUDA的交互問題。學習記錄如下:
- Step1. 共享數據區
- GLuint bufferObj;
- GLuint bufferObj;
CUDA:
- cudaGraphicsResource *resource;
- cudaGraphicsResource *resource;
- Step2.將顯卡設備與OpenGL關聯(已廢除)
- cudaDeviceProp prop;
- int dev;
- memset(&prop, 0, sizeof(cudaDeviceProp));
- prop.major = 1;
- prop.minor = 0;
- cudaChooseDevice(&dev, &prop);
- cudaGLSetGLDevice(dev);
- cudaDeviceProp prop;
- int dev;
- memset(&prop, 0, sizeof(cudaDeviceProp));
- prop.major = 1;
- prop.minor = 0;
- cudaChooseDevice(&dev, &prop);
- cudaGLSetGLDevice(dev);
- Step3. 初始化OpenGL
- #define DIM 512
- glutInit(argc, argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
- glutInitWindowSize(DIM, DIM);
- glutCreateWindow("bitmap");
- glewInit();
- #define DIM 512
- glutInit(argc, argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
- glutInitWindowSize(DIM, DIM);
- glutCreateWindow("bitmap");
- glewInit();
這裏需要注意的是:
- Step4. 使用OpenGL API創建數據緩衝區
- const GLubyte* a;
- a = glGetString(GL_EXTENSIONS);
- glGenBuffers(1, &bufferObj);//生成一個緩衝區句柄
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj);//將句柄綁定到像素緩衝區(即緩衝區存放的數據類型爲:PBO)
- glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, DIM*DIM*4, NULL, GL_DYNAMIC_DRAW_ARB);//申請內存空間並設置相關屬性以及初始值
- const GLubyte* a;
- a = glGetString(GL_EXTENSIONS);
- glGenBuffers(1, &bufferObj);//生成一個緩衝區句柄
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj);//將句柄綁定到像素緩衝區(即緩衝區存放的數據類型爲:PBO)
- glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, DIM*DIM*4, NULL, GL_DYNAMIC_DRAW_ARB);//申請內存空間並設置相關屬性以及初始值
- GL_PIXEL_UNPACK_BUFFER_ARB
- GL_PIXEL_UNPACK_BUFFER_ARB
- GL_DYNAMIC_DRAW_ARB
- GL_DYNAMIC_DRAW_ARB
- Step5. 把緩衝區分享給CUDA
- cudaGraphicsGLRegisterBuffer(&resource, bufferObj, cudaGraphicsMapFlagsNone)
- cudaGraphicsGLRegisterBuffer(&resource, bufferObj, cudaGraphicsMapFlagsNone)
代碼中的resource即之前定義的:
- cudaGraphicsResource *resource;
- cudaGraphicsResource *resource;
- Step6. 讓CUDA映射共享資源,並獲取相對於顯卡而言的設備指針
- uchar4* devPtr;
- size_t size;
- cudaGraphicsMapResources(1, &resource, NULL);
- cudaGraphicsResourceGetMappedPointer((void**)&devPtr, &size, resource);
- uchar4* devPtr;
- size_t size;
- cudaGraphicsMapResources(1, &resource, NULL);
- cudaGraphicsResourceGetMappedPointer((void**)&devPtr, &size, resource);
Map graphics resources for access by CUDA. Maps the count graphics resources in resources for access by CUDA.
The resources in resources may be accessed by CUDA until they are unmapped. The graphics API from whichresources were registered should not access any resources while they are mapped by CUDA. If an application does so, the results are undefined.
- Step7. 執行CUDA核函數
- dim3 grids(DIM/16, DIM/16);
- dim3 threads(16, 16);
- kernel_opengl<<<grids, threads>>>(devPtr);
- dim3 grids(DIM/16, DIM/16);
- dim3 threads(16, 16);
- kernel_opengl<<<grids, threads>>>(devPtr);
一個簡單的核函數kernel_opengl的定義如下:
- __global__ void kernel_opengl(uchar4* ptr){
- int x = threadIdx.x + blockIdx.x * blockDim.x;
- int y = threadIdx.y + blockIdx.y * blockDim.y;
- int offset = x + y * blockDim.x * gridDim.x;
- float fx = x/(float)DIM - 0.5f;
- float fy = y/(float)DIM - 0.5f;
- unsigned char green = 128 + 127 * sin(abs(fx*100) - abs(fy*100));
- ptr[offset].x = 0;
- ptr[offset].y = green;
- ptr[offset].z = 0;
- ptr[offset].w = 255;
- }
- __global__ void kernel_opengl(uchar4* ptr){
- int x = threadIdx.x + blockIdx.x * blockDim.x;
- int y = threadIdx.y + blockIdx.y * blockDim.y;
- int offset = x + y * blockDim.x * gridDim.x;
- float fx = x/(float)DIM - 0.5f;
- float fy = y/(float)DIM - 0.5f;
- unsigned char green = 128 + 127 * sin(abs(fx*100) - abs(fy*100));
- ptr[offset].x = 0;
- ptr[offset].y = green;
- ptr[offset].z = 0;
- ptr[offset].w = 255;
- }
- Step8. 解除CUDA對共享緩衝區的映射
- cudaGraphicsUnmapResources(1, &resource, NULL)
- cudaGraphicsUnmapResources(1, &resource, NULL)
- Step9. 調用OpenGL API顯示
- glutKeyboardFunc(key_func);
- glutDisplayFunc(draw_func);
- glutMainLoop();
- glutKeyboardFunc(key_func);
- glutDisplayFunc(draw_func);
- glutMainLoop();
其中,顯示回調函數爲:
- static void draw_func(void){
- glDrawPixels(DIM, DIM, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- glutSwapBuffers();
- }
- static void draw_func(void){
- glDrawPixels(DIM, DIM, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- glutSwapBuffers();
- }
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj);
- void glDrawPixels(
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- const GLvoid *pixels
- );
- void glDrawPixels(
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- const GLvoid *pixels
- );
轉自:http://blog.csdn.net/lingling_y/article/details/8915163