OpenGL Pixel Buffer Object (PBO)

http://www.songho.ca/opengl/gl_pbo.html

update: pixel buffer object extension is promoted as a core feature of opengl version 2.1, and removed ARB suffix.
在这里插入图片描述
opengl ARB_pixel_buffer_object extension is very close to ARB_vertex_buffer_object. it simply expands ARB_vertex_buffer_object extension in order to store not only vertex data but also pixel data into the buffer objects. this buffer object storing pixel data is called pixel buffer object (PBO). ARB_pixel_buffer_object extension borrows all VBO framework and apis, plus adds 2 additional “target” tokens. these tokens assist the PBO memory manager (opengl driver) to determine the best location of the buffer object; system memory, shared memory or video memory. also, the target tokens clearly specify that the bound PBO will be used in one of 2 different operations;

GL_PIXEL_PACK_BUFFER to transfer pixel data to a PBO, or GL_PIXEL_UNPACK_BUFFER to transfer pixel data from PBO.

for example, glReadPixels() and glGetTexImage() are “pack” pixel operations, and glDrawPixels(), glTexImage2D() and glTexSubImage2D() are “unpack” operations. when a PBO is bound with GL_PIXEL_PACK_BUFFER token, glReadPixels() reads pixel data from a opengl framebuffer and write (pack) the data into the PBO. when a PBO is bound with GL_PIXEL_UNPACK_BUFFERE token, glDrawPixels() reads (unpack) pixel data from the PBO and copy them to opengl framebuffer.

the main advantage of PBO is fast pixel data transfer to and from a graphics card through DMA (direct memory access) without involing CPU cycles. and, the other advantage of PBO is asynchronous DMA transfer. let us compare a conventional texture transfer method with using a pixel buffer object. the left side of the following diagram is a conventional way to load texture data from an image source (image file or video stream). the source is first loaded into the system memory, and then, copied from the system memory to an opengl texture object with glTexImage2D(). these 2 transfer process (load and copy) are all performed by CPU.

在这里插入图片描述
texture loading without PBO

在这里插入图片描述
texture loading with PBO

on the contrary in the right side diagram, the image source can be directly loaded into the a PBO, which is controlled by opengl. cpu still involves to load the source to the PBO, but, not for transfering the pixel data from a PBO to a texture object. instead, GPU (opengl driver) manages copying data from a PBO to a texture object. this means opengl performs a DMA transfer operation without wasting CPU cycles. further, opengl can schedule an asynchronous DMA transfer for later execution. therefore, glTexImage2D() returns immediately, and CPU can perform sth. else without waiting the pixel transfer is done.

There are 2 major PBO approaches to improve the performance of the pixel data transfer: streaming texture update and asynchronous read-back from the framebuffer.

creating pbo
as mentioned earlier, pixel buffer object borrows all APIs from vertex buffer object. the only difference is there are 2 additional tokens for PBOs: GL_PIXEL_PACK_BUFFER and GL_PIXEL_UNPACK_BUFFER.
GL_PIXEL_PACK_BUFFER is for transferring pixel data from opengl to your application,and GL_PIXEL_PACK_BUFFER means transferring pixel data from an application to opengl. OpenGL refers to these tokens to determine the best memory space of a PBO, for example, a video memory for uploading (unpacking) textures, or system memory for reading (packing) the framebuffer. However, these target tokens are solely hint. OpenGL driver decides the appropriate location for you.

Creating a PBO requires 3 steps;

  1. Generate a new buffer object with glGenBuffers().
  2. Bind the buffer object with glBindBuffer().
  3. Copy pixel data to the buffer object with glBufferData().

If you specify a NULL pointer to the source array in glBufferData(), then PBO allocates only a memory space with the given data size. The last parameter of glBufferData() is another performance hint for PBO to provide how the buffer object will be used. GL_STREAM_DRAW is for streaming texture upload and GL_STREAM_READ is for asynchronous framebuffer read-back.

Please check VBO for more details. http://www.songho.ca/opengl/gl_vbo.html#create

mapping pbo
pbo provides a memory mapping mechanism to map the opengl controlled buffer object to the client’s memory address space. so, the client can modify a portion of the buffer object or the entire buffer by using glMapBuffer() and glUnmapBuffer().

void* glMapBuffer(GLenum target, GLenum access)
GLboolean glUnmapBuffer(GLenum target)

glMapBuffer() returns the pointer to the buffer object if success. otherwise it retuns NULL. the target parameter is either GL_PIXEL_PACK_BUFFER or GL_PIXEL_UNPACK_BUFFER. the second parameter, access specifies what to do with the mapped buffer; read data from the PBO (GL_READ_ONLY), write data to the PBO (GL_WRITE_ONLY), or both (GL_READ_WRITE).

note that if gpu is still working with the buffer object, glMapBuffer() will not return until GPU finishes its job with the cooresponding buffer object. to avoid this stall(wait), call glBufferData() with NULL pointer right before glMapBuffer(). then, opengl will discard the old buffer, and allocate new memory space for the buffer object.

the buffer object must be unmapped with glUnmapBuffer() after use of the PBO. glUnmapBuffer() returns GL_TRUE if success. otherwise, it returns GL_FALSE.

the texture sources are written diectly on the mapped pixel buffer every frame in the PBO modes. then, these data are transfered from the PBO to a texture object using glTexSubImage2D(). by using PBO, opengl can perform asynchronous DMA transfer between a PBO and a texture object. it significantly increases the texture upload performance. if asynchronous DMA transfer is supported. glTexSubImage2D() should return immediately, and CPU can process other jobs without waiting the actual texture copy.

to maximize the streaming transfer performance, u may use multiple pixel buffer objects. the diagram shows that 2 PBOs are used simultaneously; glTexSubImage2D() copies the pixel data from a PBO while the texture source is being written to the other PBO.

for nth frame, PBO 1 is used for glTexSubImage2D() and PBO 2 is used to get new texture source. for n+1th frame, 2 pixel buffers are switching the roles and continue to update the texture. because of asynchronous DMA transfer, the update and copy processes can be performed simultaneously. CPU updates the texture source to a PBO while CPU copies texture from the other PBO.
在这里插入图片描述

// "index" is used to copy pixels from a PBO to a texture object
// "nextIndex" is used to update pixels in the other PBO
index = (index + 1) % 2;
nextIndex = (index + 1) % 2;

// bind the texture and PBO
glBindTexture(GL_TEXTURE_2D, textureId);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[index]);

// copy pixels from PBO to texture object
// Use offset instead of ponter.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, 0);


// bind PBO to update texture source
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[nextIndex]);

// Note that glMapBuffer() causes sync issue.
// If GPU is working with this buffer, glMapBuffer() will wait(stall)
// until GPU to finish its job. To avoid waiting (idle), you can call
// first glBufferData() with NULL pointer before glMapBuffer().
// If you do that, the previous data in PBO will be discarded and
// glMapBuffer() returns a new allocated pointer immediately
// even if GPU is still working with the previous data.
glBufferData(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE, 0, GL_STREAM_DRAW);

// map the buffer object into client's memory
GLubyte* ptr = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
if(ptr)
{
    // update data directly on the mapped buffer
    updatePixels(ptr, DATA_SIZE);
    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer
}

// it is good idea to release PBOs with ID 0 after use.
// Once bound with 0, all pixel operations are back to normal ways.
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值