使用Opengl PBO上传下载数据
来源:互联网 发布:ros系统 与 linux 编辑:程序博客网 时间:2024/06/06 03:52
PBO(pixel buffer object)是储存像素数据的缓冲区对象,主要有两个用途:
1. 上传一帧像素数据到PBO中,GL_UNPACK_ALIGNMENT
3. 对于一对PBO buffer和texture,首先pbo buffer绑定用于上传数据的GL_PIXEL_UNPACK_BUFFER
4. 通过glMapBuffer拿到地址,并把需要上传的数据拷贝到其中
5. 绑定texture,通过调用glTexSubImage2D把pbo的数据拷贝到texture里
对比不使用PBO的方法,很简单,直接从memory地址读取:
简单来说,对比不使用pbo的方法,glTexSubImage2D会造成cpu阻塞,而使用pbo的话glTexSubImage2D则会立刻返回。具体分析如下:
2. 绑定希望输出的FBO
3. 准备读取GL_COLOR_ATTACHMENT0对应的texture内容
4. 绑定GL_PIXEL_PACK_BUFFER到刚创建的下载用pbo buffer
6. 通过glMapBuffer拿到GL_PIXEL_PACK_BUFFER地址,通过memcpy拷贝出来到cpu内存
相比之下,不使用pbo的简单方法,直接读取到cpu分配的内存downloadData里:
1. 上传一帧像素数据到PBO中,GL_UNPACK_ALIGNMENT
2. 从PBO中读取像素到cpu内存空间, GL_PIXEL_PACK_BUFFER
其实不使用PBO也可以上传下载数据,那么PBO好处何在?我们对比两种方式上传yuv420数据:
使用PBO的方法:
1. 创建用于上传像素数据的PBO buffer
glGenBuffers(1, pbo);glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[i]);glBufferData(GL_PIXEL_UNPACK_BUFFER, data_size, NULL, GL_STREAM_DRAW);2. 创建texture用于存储数据,只用GL_RED
glGenTextures(1, texture);glBindTexture(GL_TEXTURE_2D, texture[0]);glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, W, H, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3. 对于一对PBO buffer和texture,首先pbo buffer绑定用于上传数据的GL_PIXEL_UNPACK_BUFFER
GLubyte* dst;glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[0]);
4. 通过glMapBuffer拿到地址,并把需要上传的数据拷贝到其中
dst = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);av_assert0(dst);memcpy(dst, data, W*H); // data is Y/U/V bufferglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
5. 绑定texture,通过调用glTexSubImage2D把pbo的数据拷贝到texture里
glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture[0]);glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // TODOglPixelStorei(GL_UNPACK_IMAGE_HEIGHT, H); // image height in client memoryglPixelStorei(GL_UNPACK_ROW_LENGTH, W); // pitch in client memoryglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RED, GL_UNSIGNED_BYTE, 0);
对比不使用PBO的方法,很简单,直接从memory地址读取:
glGenTextures(1, texture);glBindTexture(GL_TEXTURE_2D, texture[0]);// 创建textureglTexImage2D(GL_TEXTURE_2D, 0, GL_RED, W, H, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);// 直接从bufDataPtr地址读取内容到textureglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RED, GL_UNSIGNED_BYTE, bufDataPtr);
简单来说,对比不使用pbo的方法,glTexSubImage2D会造成cpu阻塞,而使用pbo的话glTexSubImage2D则会立刻返回。具体分析如下:
PBO的主要优点是可以通过DMA (Direct Memory Access) 快速地在显卡上传递像素数据,而不影响CPU的时钟周期(中断)。另一个优势是它还具备异步DMA传输。对比使用PBO前后的纹理传送方法。首先,资源被加载到系统内存中,然后使用glTexSubImage2D()函数从系统内存复制到OpenGL纹理对象中(Client->Server)。这两次数据传输(加载和复制)完全由CPU执行。
使用PBO的情况下,PBO是由OpenGL控制的。虽然CPU有参与加载纹理到PBO,但不涉及将像素数据从PBO传输到纹理对象的工作,而是由GPU(OpenGL驱动)来负责PBO到纹理对象的数据传输的,这也就意味着OpenGL执行DMA传输操作不会占用CPU的时钟周期。此外,OpenGL还可以安排稍后执行的异步DMA传输。所以glTexImage2D()或者glTexSubImage2D()可以立即返回,CPU也无需等待像素数据的传输了,可以继续其他工作。
下面是使用PBO的方式下载数据到cpu内存:
1. 创建PBO buffer
glGenBuffers(1, pbo_down);data_size = W * H;glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_down[0]);glBufferData(GL_PIXEL_PACK_BUFFER, data_size, NULL, GL_STREAM_READ);
2. 绑定希望输出的FBO
GLubyte* src;glBindFramebuffer(GL_FRAMEBUFFER, fbo_render[0]);
3. 准备读取GL_COLOR_ATTACHMENT0对应的texture内容
glReadBuffer(GL_COLOR_ATTACHMENT0);glPixelStorei(GL_PACK_ALIGNMENT, 4); // TODOglPixelStorei(GL_PACK_IMAGE_HEIGHT, H); // image height in client memoryglPixelStorei(GL_PACK_ROW_LENGTH, W); // pitch in client memory
4. 绑定GL_PIXEL_PACK_BUFFER到刚创建的下载用pbo buffer
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_down[0]);
glReadPixels(0, 0, W, H, GL_RED, GL_UNSIGNED_BYTE, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
6. 通过glMapBuffer拿到GL_PIXEL_PACK_BUFFER地址,通过memcpy拷贝出来到cpu内存
src = (GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);av_assert0(src); // TODOav_assert0(out->data[0]);memcpy(out->data[0], src, W*H);glUnmapBuffer(GL_PIXEL_PACK_BUFFER);glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
相比之下,不使用pbo的简单方法,直接读取到cpu分配的内存downloadData里:
glReadPixels(0, 0, W, H, GL_RED, GL_UNSIGNED_BYTE, downloadData);
阅读全文
0 0
- 使用Opengl PBO上传下载数据
- OpenGL---PBO
- cuda8.0使用pbo与opengl交互
- OpenGL Pixel Buffer Object (PBO)
- OPENGL VBO,FBO和PBO
- OpenGL Pixel Buffer Object (PBO)
- OpenGL VBO, PBO与FBO
- OpenGL像素缓冲对象(PBO)
- OpenGL VBO, PBO与FBO
- OpenGL Pixel Buffer Object (PBO)
- OpenGL VBO, PBO与FBO
- PBO
- PBO
- OpenGL Pixel Buffer Object (PBO)【转】
- [转]OpenGL Pixel Buffer Object (PBO)
- cuda与opengl互操作之PBO
- OpenGL之VBO,PBO,FBO技术
- cuda与opengl互操作之PBO
- Python多进程(1)——subprocess与Popen()
- dlib 矩阵操作
- Linux学习资源
- SpringCloud---Eureka Server集群
- 1125. Chain the Ropes (25)
- 使用Opengl PBO上传下载数据
- 设计模式读书笔记-----单例模式
- 快速乘的原理及其代码
- 最小生成树(1)--Kruskal算法
- HDU 5543 Pick The Sticks(0-1背包)
- 【面试题】海量数据处理相关
- The Suspects(POJ
- 一个关于Span的学习资料, 很棒的文档
- Python多进程(2)——mmap模块与mmap对象