找回密码
 注册会员
更新自动建库工具PCB Footprint Expert 2024.04 Pro / Library Expert 破解版

[嵌入式/ARM] CUDA和OpenGL互操作的实现及分析

[复制链接]
admin 发表于 2013-3-24 13:57:38 | 显示全部楼层 |阅读模式

本文包含原理图、PCB、源代码、封装库、中英文PDF等资源

您需要 登录 才可以下载或查看,没有账号?注册会员

×
摘  要: CUDA和OpenGL互操作的基本方式是使用CUDA生成数据,再利用OpenGL在屏幕上绘制出数据所表示的图形。两者的结合可以通过使用OpenGL的PBO(像素缓冲区对象)或VBO(顶点缓冲区对象)两种方式来实现。描述了CUDA和OpenGL互操作的步骤并展示了一个使用PBO的实例。该实例运行结果表明,互操作的方式比单纯使用OpenGL方式快了7~8倍。
关键词: CUDA;OpenGL;像素缓冲区对象;顶点缓冲区对象
   1 CUDA与OpenGL概述
 OpenGL是图形硬件的软件接口,它是在SGI等多家世界着名的计算机公司的倡导下,以SGI的GL三维图形库为基础制定的一个通用、共享的、开放式的、性能卓越的三维图形标准。OpenGL在医学成像、地理信息、石油勘探、气候模拟以及娱乐动画上有着广泛应用,它已经成为高性能图形和交互式视景处理的工业标准。
 OpenGL不是一种编程语言,而是一种API(应用程序编程接口)。程序员可以使用某种编程语言(如C或C++)编写绘图软件,其中调用了一个或多个OpenGL库函数。作为一种API,OpenGL遵循C语言的调用约定。OpenGL开发资料可参考文献[1]和参考文献[2]。
 图形处理器(GPU)原本是处理计算机图形的专用设备,近十年来,由于高清晰度复杂图形实时处理的需求,GPU发展成为高并行度、多线程、多核的处理器。目前,主流GPU的运算能力已超过主流通用CPU,从发展趋势上来看将来差距会越拉越大。为了合理地利用GPU 资源,CUDA(统一计算设备架构)应运而生。CUDA是一种由NVIDIA推出的通用并行计算架构[3],该架构使GPU能够解决复杂的计算问题,并且由于CUDA编程语言基于标准的C语言,从而大大提高了可编程性。
CUDA和OpenGL互操作的基本方式是使用CUDA生成数据,然后使用OpenGL在屏幕上绘制出数据所表示的图形。两者的结合可以通过两种方式来实现:
 (1)使用OpenGL的PBO(像素缓冲区对象)。在该方式下,CUDA直接生成像素数据,OpenGL显示这些像素;
 (2)使用OpenGL的VBO(顶点缓冲区对象)。在该方式下,CUDA生成顶点网格数据,OpenGL可以根据需要绘制出平滑的表面图或线框图或一系列顶点。
这两种方式的核心都是利用cudaGLMapBufferObject函数将OpenGL的缓冲区映射到CUDA的内存空间上,这样,程序员就可以充分利用CUDA的优点写出性能高的程序在该内存空间上生成数据,这些数据不需要传送,OpenGL可以直接使用。如果不使用CUDA,这些数据需要由CPU来计算产生。一方面,CPU的计算速度通常比GPU慢;另一方面,这些数据需要传送到GPU上以供OpenGL显示使用。鉴于此,当数据量很大时,CUDA和OpenGL的混合使用效果明显。
2 CUDA和OpenGL互操作的过程[4]
 CUDA和OpenGL互操作具体步骤如下:
 (1)创建窗口及OpenGL运行环境。
 (2)设置OpenGL视口和坐标系。要根据绘制的图形是2D还是3D等具体情况设置。(1)和(2)是所有OpenGL程序必需的,这里也没什么特殊之处,需要注意的是,后面的一些功能需要OpenGL 2.0及以上版本支持,所以在这里需要进行版本检查。
 (3)创建CUDA环境。可以使用cuGLCtxCreate或cudaGLSetGLDevice来设置CUDA环境。该设置一定要放在其他CUDA的API调用之前。
 (4)产生一个或多个OpenGL缓冲区用以和CUDA共享。使用PBO和使用VBO差不多,只是有些函数调用参数不同。以下是具体过程。
 GLuint bufferID;
 glGenBuffers(1,&bufferID);//产生一个buffer ID
 glBindBuffer(parameter1,bufferID);
 //将其设置为当前非压缩缓冲区,如果是PBO方式,parameter1设置为GL_PIXEL_UNPACK_BUFFER,如果
 是VBO方式,parameter1设置为GL_ARRAY_BUFFER
 glBufferData(parameter1,parameter2,NULL,GL_DYNAMIC _COPY);
 //给该缓冲区分配数据,PBO方式下,parameter1设置为GL_PIXEL_UNPACK_BUFFER,parameter1设置为图像的长度*宽度*4。VBO方式下,parameter1设置为GL_ARRAY_BUFFER,parameter2设置为顶点数*16,因为每个顶点包含3个浮点坐标(x,y,z)和4个颜色字节(RGBA),这样一个顶点包含16 B
 (5)用CUDA登记缓冲区。登记可以使用cuGLRegisterBufferObject或cudaGLRegisterBufferObject,该命令告诉OpenGL和CUDA 驱动程序该缓冲区为二者共同使用。
 (6)将OpenGL缓冲区映射到CUDA内存。可以使用cuGLMapBufferObject或cudaGLMapBufferObject,它实际是将CUDA内存的指针指向OpenGL的缓冲区,这样如果只有一个GPU,就不需要数据传递。当映射完成后,OpenGL不能再使用该缓冲区。
 (7)使用CUDA往该映射的内存写图像数据。前面的准备工作在这里真正发挥作用了,此时可以调用CUDA的kernel,像使用全局内存一样使用映射了的缓冲区,向其中写数据。
 (8)取消OpenGL缓冲区映射。要等前面CUDA的活动完成以后,使用cuGLUnmapBufferObject或cudaGLUnmapBufferObject函数取消映射。
 (9)前面的步骤完成以后就可以真正开始绘图了, OpenGL的PBO和VBO的绘图方式不同,分别为以下两个过程。
 ①如果只是绘制平面图形,需要使用OpenGL的PBO及纹理。
 glEnable(GL_TEXTURE_2D); //使纹理可用
 glGenTextures(1,&textureID); //生成一个textureID
 glBindTexture(GL_TEXTURE_2D,textureID);
 //使该纹理成为当前可用纹理
 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,Width, Height,0,GL_BGRA,GL_UNSIGNED_BYTE,NULL);
 //分配纹理内存。最后的参数设置数据来源,这里设置为NULL,表示数据来自PBO,不是来自主机内存
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN _FILTER,GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_ FILTER,GL_LINEAR);//必须设置滤波模式,GL_LINEAR允许图形伸缩时线性差值。如果不需要线性差值,可以用GL_TEXTURE_RECTANGLE_ARB代替GL_TEXTURE_2D以提高性能,同时在glTexParameteri()调用里使用GL_NEAREST替换GL_LINEAR
 然后就可以指定4个角的纹理坐标,绘制长方形了。
 ②绘制3D场景,需要使用VBO。
glEnableClientState(GL_VERTEX_ARRAY);
//使顶点和颜色数组可用
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3,GL_FLOAT,16,0);
//设置顶点和颜色指针
glColorPointer(4,GL_UNSIGNED_BYTE,16,12);
glDrawArrays(GL_POINTS,0,numVerticies);
//根据顶点数据绘图,参数可以使用GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES,GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS,GL_QUAD_STRIP,GL_POLYGON
(10)前后缓存区来回切换,实现动画显示效果。调用SwapBuffers(),缓冲区切换通常会在垂直刷新间隙来处理,因此,可以在控制面板上关掉垂直同步,使得缓冲区切换立刻进行。
3 CUDA和OpenGL互操作性能实例分析
3.1 测试实例
*滑块验证:
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

QQ|手机版|MCU资讯论坛 ( 京ICP备18035221号-2 )|网站地图

GMT+8, 2024-12-26 01:05 , Processed in 0.053306 second(s), 9 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表