首页 / 更多教程 / OpenGL与CUDA互操作方式总结
OpenGL与CUDA互操作方式总结
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了OpenGL与CUDA互操作方式总结,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6089字,纯文字阅读大概需要9分钟。
内容图文
一、介绍
CUDA是Nvidia推出的一个通用GPU计算平台,对于提升并行任务的效率非常有帮助。本人主管的项目中采用了OpenGL做图像渲染,但是在数据处理方面比较慢,导致帧率一直上不来。于是就尝试把计算工作分解成小的任务,使用核函数在CUDA中加速计算。对于CUDA和OpenGL如何交互以前从来没有接触过,这次在实施时趟了不少的坑。在这里记录下OpenGL与CUDA的互操作的两种方式。
二、基本操作流程
OpenGL与CUDA互操作可以分成两种,一种是OpenGL将Buffer对象注册到CUDA中去,供CUDA读写操作,然后再在OpenGL中使用。一般这种情况下注册的是VBO和PBO,VBO一般用于存储顶点坐标、索引等数据;PBO则一般用于存储图像数据,因此称作Pixel Buffer Object。另一种是OpenGL将Texture对象注册到CUDA中去,经CUDA处理后得到纹理内容,然后在OpenGL中渲染出来。不过不管是哪一种互操作类型,其操作流程是一致的:
- 在OpenGL里面初始化Buffer Object
- 在CUDA中注册OpenGL中的Buffer Object
- CUDA锁定资源,获取操作资源的指针,在CUDA核函数中进行处理
- CUDA释放资源,在OpenGL中使用Buffer Object
下面就以代码为例,讲讲两种方式的异同:
(1)OpenGL PBO/VBO在CUDA中的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// 初始化Buffer Object
//vertex array object
glGenVertexArrays(1, &
this
->VAO);
//Create vertex buffer object
glGenBuffers(2,
this
->VBO);
//Create Element Buffer Objects
glGenBuffers(1, &
this
->EBO);
//Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
glBindVertexArray(
this
->VAO);
// 绑定VBO后即在CUDA中注册Buffer Object
glBindBuffer(GL_ARRAY_BUFFER,
this
->VBO[0]);
glBufferData(GL_ARRAY_BUFFER,
sizeof
(*
this
->malla)*
this
->numPoints,
this
->malla, GL_DYNAMIC_COPY);
cudaGraphicsGLRegisterBuffer(&
this
->cudaResourceBuf[0],
this
->VBO[0], cudaGraphicsRegisterFlagsNone);
glBindBuffer(GL_ARRAY_BUFFER,
this
->VBO[1]);
glBufferData(GL_ARRAY_BUFFER,
sizeof
(*
this
->malla)*
this
->numPoints,
this
->malla, GL_DYNAMIC_COPY);
cudaGraphicsGLRegisterBuffer(&
this
->cudaResourceBuf[1],
this
->VBO[1], cudaGraphicsRegisterFlagsNone);
// 在CUDA中映射资源,锁定资源
cudaGraphicsMapResources(1, &
this
->cudaResourceBuf[0], 0);
cudaGraphicsMapResources(1, &
this
->cudaResourceBuf[1], 0);
point *devicePoints1;
point *devicePoints2;
size_t size = sizeof (* this ->malla)* this ->numPoints; // 获取操作资源的指针,以便在CUDA核函数中使用
cudaGraphicsResourceGetMappedPointer((
void **)&devicePoints1, &size, this ->cudaResourceBuf[0]); cudaGraphicsResourceGetMappedPointer((
void **)&devicePoints2, &size, this ->cudaResourceBuf[1]); // execute kernel
dim3 dimGrid(20, 20, 1);
dim3 dimBlock(
this
->X/dimGrid.x,
this
->Y/dimGrid.y, 1);
modifyVertices<<<dimGrid, dimBlock>>>(devicePoints1, devicePoints2,
this
->X,
this
->Y);
modifyVertices<<<dimGrid, dimBlock>>>(devicePoints2, devicePoints1,
this
->X,
this
->Y);
// 处理完了即可解除资源锁定,OpenGL可以开始利用处理结果了。
// 注意在CUDA处理过程中,OpenGL如果访问这些锁定的资源会出错。
cudaGraphicsUnmapResources(1, &
this
->cudaResourceBuf[0], 0);
cudaGraphicsUnmapResources(1, &
this
->cudaResourceBuf[1], 0);
|
值得注意的是,由于这里绑定的是VBO,属于Buffer对象,因此调用的CUDA API是这两个:
1
2
|
cudaGraphicsGLRegisterBuffer();
cudaGraphicsResourceGetMappedPointer();
|
(2)OpenGL Texture在CUDA中的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
// 初始化两个Texture并绑定
cudaGraphicsResource_t cudaResources[2];
GLuint textureID[2];
glEnable(GL_TEXTURE_2D);
glGenTextures(2, textureID);
glBindTexture(GL_TEXTURE_2D, textureID[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1000, 1000, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, textureID[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1000, 1000, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// 在CUDA中注册这两个Texture
cudaError_t err = cudaGraphicsGLRegisterImage(&cudaResources[0], textureID[0], GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard);
if (err != cudaSuccess) {
std::cout <<
"cudaGraphicsGLRegisterImage: " << err << "Line: " << __LINE__;
return -1; }
err = cudaGraphicsGLRegisterImage(&cudaResources[1], textureID[1], GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard);
if (err != cudaSuccess) {
std::cout <<
"cudaGraphicsGLRegisterImage: " << err << "Line: " << __LINE__;
return -1; }
// 在CUDA中锁定资源,获得操作Texture的指针,这里是CudaArray*类型
cudaError_t err = cudaGraphicsMapResources(2, cudaResource, 0);
err = cudaGraphicsSubResourceGetMappedArray(&
this
->cuArrayL, cudaResource[0], 0, 0);
err = cudaGraphicsSubResourceGetMappedArray(&
this
->cuArrayR, cudaResource[1], 0, 0);
// 数据拷贝至CudaArray。这里因为得到的是CudaArray,处理时不方便操作,于是先在设备内存中
// 分配缓冲区处理,处理完后再把结果存到CudaArray中,仅仅是GPU内存中的操作。
cudaMemcpyToArray(cuArrayL, 0, 0, pHostDataL, imgWidth*imgHeight *
sizeof
(uchar4), cudaMemcpyDeviceToDevice);
cudaMemcpyToArray(cuArrayR, 0, 0, pHostDataR, imgWidth*imgHeight *
sizeof
(uchar4), cudaMemcpyDeviceToDevice);
// 处理完后即解除资源锁定,OpenGL可以利用得到的Texture对象进行纹理贴图操作了。
cudaGraphicsUnmapResources(1, &cudaResource[0], 0);
cudaGraphicsUnmapResources(1, &cudaResource[1], 0);
|
注意这里因为使用的是Texture对象,因此使用了不同的API:
1
2
|
cudaGraphicsGLRegisterImage();
cudaGraphicsSubResourceGetMappedArray();
|
VBO/PBO是属于OpenGL Buffer对象,而OpenGL Texture则是另一种对象。因此,两种类型的处理需要区别对待。在这个地方耽搁了很久,就是因为没有看文档说明。下面一段话正是对这种情况的说明:
From the CUDA Reference Guide entry for `cudaGraphicsResourceGetMappedPointer()`:
> If resource is not a buffer then it cannot be accessed via a pointer and cudaErrorUnknown is returned.
From the CUDA Reference Guide entry for `cudaGraphicsSubResourceGetMappedArray()`:
> If resource is not a texture then it cannot be accessed via an array and cudaErrorUnknown is returned.
In other words, use **GetMappedPointer** for mapped buffer objects. Use **GetMappedArray** for mapped texture objects.
三、参考链接
- http://stackmirror.cn/page/4ejhmgxan1w
- https://stackoverflow.com/questions/21765604/draw-image-from-vertex-buffer-object-generated-with-cuda-using-opengl
- https://stackoverflow.com/questions/19244191/cuda-opengl-interop-draw-to-opengl-texture-with-cuda?rq=1
- https://www.3dgep.com/opengl-interoperability-with-cuda/
原文:http://www.cnblogs.com/zhangzhangY/p/7407397.html
内容总结
以上是互联网集市为您收集整理的OpenGL与CUDA互操作方式总结全部内容,希望文章能够帮你解决OpenGL与CUDA互操作方式总结所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。