CUDA与OpenGL交互开发
最近在学习OpenGL,过程中需要使用CUDA进行并行计算。因此,需要解决OpenGL与CUDA的交互问题。学习记录如下:
- Step1. 共享数据区
GLuint bufferObj;
CUDA:
cudaGraphicsResource *resource;
- Step2.将显卡设备与OpenGL关联(已废除)
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();
这里需要注意的是:
- 需要使用opengl扩展库:glew32.dll。若您没有glew32扩展库,点此下载 (其安装方式与glut,freeglut等相同)
- (重要)需要在opengl初始化代码最后加上:glewInit(),否则会在后面执行到glGenBuffers报运行时错误:0xC0000005: Access violation.
- 使用glew库需要: #include "gl/glew.h",且其声明的位置尽量放在代码最顶端,否则编译报错。
- 具体示例代码,点此下载
—————————————————— 华丽的分割线 ————————————————————
- 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);//申请内存空间并设置相关属性以及初始值
这里,我们使用如下枚举值:
GL_PIXEL_UNPACK_BUFFER_ARB
表示指定缓冲区存储的内容是一个Pixel Buffer Object(PBO)
GL_DYNAMIC_DRAW_ARB
表示应用程序将会对缓冲区进行修改
![](https://img-my.csdn.net/uploads/201304/25/1366892538_3560.png)
可以看到,我的环境是支持GL_ARB_pixel_buffer_object的,如果您的环境不支持该枚举值,可能需要您更新glew扩展库版本。
- Step5. 把缓冲区分享给CUDA
cudaGraphicsGLRegisterBuffer(&resource, bufferObj, cudaGraphicsMapFlagsNone)
代码中的resource即之前定义的:
cudaGraphicsResource *resource;
- Step6. 让CUDA映射共享资源,并获取相对于显卡而言的设备指针
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 which resources 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);
一个简单的核函数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;
}
此时,执行完核函数,CUDA的使命也就完成了。它的产出就是: 缓冲区的数据已经被更新了~~
- Step8. 解除CUDA对共享缓冲区的映射
cudaGraphicsUnmapResources(1, &resource, NULL)
如果不解除映射,那么OpenGL将没有权限访问共享数据区,因此也就没有办法完成图像的渲染显示了。
- Step9. 调用OpenGL API显示
glutKeyboardFunc(key_func);
glutDisplayFunc(draw_func);
glutMainLoop();
其中,显示回调函数为:
static void draw_func(void){glDrawPixels(DIM, DIM, GL_RGBA, GL_UNSIGNED_BYTE, 0);glutSwapBuffers();
}
乍一看,可能感觉会比较奇怪。因为draw_func里面没有使用到缓冲区句柄bufferObj,那么数据如何会显示呢?
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj);
该调用将共享缓冲区指定为一个像素源,OpenGL驱动程序随后会在所有对glDrawPixels()的调用中使用这个像素源。这也就说明了我们为什么使用glDrawPixels来绘制图形了。
void glDrawPixels(GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid *pixels
);
不难发现其最后一个参数为一个缓冲区指针。如果没有任何缓冲区被指定为GL_PIXEL_UNPACK_BUFFER_ARB源,那么OpenGL将从这个参数指定的缓冲区进行数据复制并显示。但在本例中,我们已经将共享数据缓冲区指定为GL_PIXEL_UNPACK_BUFFER_ARB。此时,该参数含义将变为:已绑定缓冲区内的偏移量,由于我们要绘制整个缓冲区,因此这便宜量就是0.
![](https://img-my.csdn.net/uploads/201304/25/1366894497_7126.png)
CUDA与OpenGL交互开发相关推荐
- Android OpenGL ES 开发教程(20):颜色Color
OpenGL ES 支持的颜色格式为RGBA模式(红,绿,蓝,透明度).颜色的定义通常使用Hex格式0xFF00FF 或十进制格式(255,0,255), 在OpenGL 中却是使用0-1之间的浮点数 ...
- 在Android中使用OpenGL ES开发第(五)节:GLSL基础语法
一.前期基础储备 笔者之前的四篇文综述了Android中使用OpenGL ES绘制基本图形和实现了简单的相机预览,初次接触OpenGL ES开发的读者可能对其中新的概念比较迷惑,尤其是其中的顶点着色器 ...
- 单片机小精灵t2_搭建S5P4418 ARM环境下 GPU OPENGL ES开发环境(适用 NANOPI2,3,M2,M3,T2,T3)...
本帖最后由 3guoyangyang7 于 2017-8-20 22:38 编辑 先说一下背景,这几天做一个摄像头处理的qt项目,摄像头的像素是1280*720的,25fps,用qt的painter重 ...
- CUDA:CUDA转OPENGL的实例
CUDA:CUDA转OPENGL的实例 #include <helper_cuda.h>// clamp x to range [a, b] __device__ float clamp( ...
- VR游戏交互开发的一些体验
VR游戏交互开发的一些体验 本文主要写Unity开发手游过程中VR交互输入控制的一些浅薄的经验 交互方面,头控和视线按钮依然较为主流,可以获得传感器数据来获得输入 除了实体按钮输入之外还可以探索其他交 ...
- 【OpenGL游戏开发之二】OpenGL常用API
OpenGL常用API 开发基于OpenGL的应用程序,必须先了解OpenGL的库函数.它采用C语言风格,提供大量的函数来进行图形的处理和显示.OpenGL库函数的命名方式非常有规律.所有OpenGL ...
- 【OpenGL】OpenGL引擎开发视频教程
OpenGL引擎开发 ☆CSDN 网址" / "☆51CTO网址" 课程1 图形学理论视频课程-实现OpenGL精简内核 http://edu.csdn.net/cour ...
- 虚拟现实三维数字沙盘电子沙盘可视化交互开发教程第5课
虚拟现实三维数字沙盘电子沙盘可视化交互开发教程第5课 设置system.ini 如下内容 Server=122.112.229.220 user=GisTest Password=chinamtouc ...
- OpenGL交互——菜单控制(基础教程)
相关单词:entry有"条目,项目,账目,词目,词条的含义",一般含义"进入,入口,门口". GLUT教程 ...
最新文章
- php 任意文件上传,任意文件上传漏洞
- matlab多元回归程序,多元回归程序MATLAB程序
- Nuget 多平台多目标快速自动打包
- x 6什么意思python_Python基础_6
- 读取unicode编码文件的乱码解决
- 集成Silverlight 2的AJAX框架 Visual WebGui
- JAVA中的观察者模式observer
- springboot项目层次结构_Springboot项目结构Springboot项目结构
- Coding Interview Guide -- 判断二叉树是否为平衡二叉树
- 那些年,我们一起学过的汇编----之子程序设计
- 一个网页如何决定是当前页打开还是新窗口打开?
- GPS 相关知识科普
- 学会这个前端特效520还怕没CP伴侣
- java扫码枪键盘_JAVA读取USB扫描枪
- 计算机上表格怎么算减法,表格里的减法怎么弄/在excle如何用函数进行加减法
- 关于无法完全停止windowsUpdate的解决方法
- html5三国策略,HTML5新游《乱弹三国》今日首曝
- 目前流行的操作系统有哪些
- 文献阅读_Radiogenomic analysis of vascular endothelial growth factor in patients with diffuse gliomas
- 三相维也纳pfc,开关电源,三相AC输入无桥pfc±400vDC输出,已经量产两年非常成熟,包括源代码