Disclaimer (Must read!) ): This translation is from the following links, only for learning and communication purposes, do not carry out commercial communication. Also, do not remove this statement when reproduced. In case of any dispute, there is no relationship between the blogger and the person who published the translation. Thank you for your cooperation! http://www.songho.ca/opengl/gl_pbo.html
OpenGL's Arb_pixel_buffer_object extension is very close to arb_vertex_buffer_object. It is designed to store vertex data (vertex) and pixel data (Pixel) in a buffered object, simply extending the arb_vertex_buffer_object. The buffer object for this storage pixel is called a pixel buffer object (PBO, Pixelbuffer object). The Arb_pixel_buffer_object extension borrows the framework and API for the entire VBO, plus 2 additional "target" flags added. These flags assist the bound PBO memory manager (OpenGL driver) to determine the best location for buffer object storage: system memory, shared memory, or video memory. In addition, the target flag clearly indicates that the PBO binding will be used for 2 operations: Gl_pixel_pack_buffer_arb is used to transfer pixel data to PBO, or Gl_pixel_unpack_buffer_arb transmits PBO to pixel data.
For example, Glreadpixels () and Glgetteximage () are "pack (Pack)" pixel operations, while Gldrawpixels (), glteximage2d (), and gltexsubimage2d () are "unzip (unpack ) "action. When a PBO is bound to the GL_PIXEL_PACK_BUFFER_ARB flag, Glreadpixels () reads the pixel data from the OpenGL frame buffer (framebuffer) and then draws the data ( Pack pack) into the PBO. When a PBO is bound to the GL_PIXEL_UNPACK_ARB flag, Gldrawpixels () reads from PBO (UNPACK) or copies pixel data into OpenGL frame buffer (framebuffer).
The main advantage of PBO is the ability to quickly transfer the pixel data to or from the video card without having to involve CPU cycles through direct memory access (ACCESS,DMA). Another advantage of PBO is the asynchronous direct memory access transfer, which allows us to compare the traditional texture transfer method and use the pixel buffer object. The figure below is the traditional way to load the image data from the source (image file or video stream). The image source data is first loaded into system memory and then copied from the system memory to the OpenGL texture object via Glteximage2d (). These 2 transfer steps (load and copy) are performed by the CPU.
Conversely, the right image, the image data source can be directly loaded into the PBO object and controlled by OpenGL. The same place that the CPU is associated with is the loading of the image data source into the PBO, but does not participate in the transfer of pixel data from PBO to texture objects (texture object). Instead, the GPU (OpenGL driver) manages the copying of data from PBO to texture objects. This means that OpenGL performs direct memory access (DMA) transfer operations without wasting CPU weeks
Period. Further, OpenGL can schedule an asynchronous direct Memory access (DMA) transfer operation to the following execution. Therefore, gltexture2d () returns immediately, and the CPU can perform other things without waiting for the data to be transferred.
Here are 2 main ways to improve the transmission of pixel data:
Stream Texture UploadAnd
asynchronously read back from frame buffer。
---------------------------------------------------------------------------------------------------------------
Create PBO
As mentioned earlier, the pixel buffer object borrows all the APIs of the vertex buffer object. The only difference is that there are two different additional signs Pbo:gl_pixel_pack_buffer_arb and Gl_pixel_unpack_buffer_arb. Gl_pixel_pack_buffer_arb is used to transfer pixel data from OpenGL to your app, while Gl_pixel_unpack_buffer_arb is used to transfer pixel data from the app to OpenGL. OpenGL reference These flags determine the best memory space for the PBO, for example, a video memory used to upload (extract the unpacking) texture, or system memory to read (package packing) frame buffer. These target flags are then used only as hints. The OpenGL driver will determine the right location for you.
Creating a PBO takes 3 steps:
1. Universal Glgenbuffersarb () assigns a new buffer object.
2. Bind the Buffer object through Glbindbufferarb ().
3. Copy the pixel data to the buffered object via Glbufferdataarb ().
If you specify a null pointer in Glbufferdataarb () to point to the source array, then PBO simply allocates the memory space for the given data size. The last parameter of Glbufferdataarb () is another performance hint, suggesting what the PBO will do with the buffered object. Gl_stream_arb is used for streaming texture uploads, and gl_stream_read_arb is used to read back the asynchronous frame buffer.
See Vbo for more details.
----------------------------------------------------------------------------------------------------------- ----
map PBO (Mapping PbO)
PBO provides a memory mapping mechanism to map OpenGL's control buffer objects to the client's memory address space. Therefore, the client can modify a portion of the buffer object or the entire buffer through Glmapbufferarb () and Glunmapbufferarb ().
void* Glmapbufferarb (glenum target, glenum access);
Glboolean Glunmapbufferarb (glenum target);
If successful, Glmapbufferarb () returns a pointer to the buffered object, or null if it fails. The target parameter is Gl_piexel_pack_buffer or Gl_pixel_unpack_buffer_arb. The second parameter, which specifies what the mapped buffer to access will do. Read data from PBO (Gl_read_only_arb), write data to PBO (Gl_write_only_arb), or Read and write (Gl_read_write_arb).
Note that if the GPU is still working with buffered objects, Glmapbufferarb () will not return until the GPU finishes working on his corresponding buffered objects. To avoid this stall (wait), send a null pointer before calling Glmapbufferarb () to invoke the next Glbufferdataarb (). OpenGL then discards the old buffer and allocates a new memory space to the buffered object.
After using the PBO, the buffered object must call the next Glunmapbufferarb () to cancel the mapping. Glunmapbufferarb () If the gl_true is returned successfully. Otherwise, return Gl_false.
----------------------------------------------------------------------------------------------------------- ----
Example: Stream texture Upload
Download source code and binary: Pbounpack.zip
This demo app uses the PBO upload (unzip) stream texture to an OpenGL texture object. You can press the SPACEBAR to switch to a different transmission mode (single PBO, double pob, no PBO) is different than execution.
In PBO mode, the texture source data is written directly to the mapped pixel buffer in each frame. Then, the data is transferred from PBO to the texture object by using gltexsubimage2d (). By using PBO,OPENGL, you can use asynchronous Direct memory access (DMA) transfers between POB and texture objects. He significantly
Improves texture upload performance. If asynchronous direct memory access (DMA) transfers are supported, gltexsubimage2d () should return immediately, while the CPU can do other work without having to wait for the actual texture to replicate.
To maximize streaming performance, you can use a multi-pixel buffer object. The picture shows that 2 PBO is used at the same time, and gltexsubimage2d () can copy pixel data from PBO when the texture source data is written to another PBO.
For nth frames, PBO1 is used for gltexsubimage2d (), and PBO2 is used to obtain new picture data. For n+1 frames, the 2-pixel buffer Exchange rule then continues to update the texture. Because of the asynchronous direct Memory access (DMA) transfer, the update and copy process can be performed concurrently. While the CPU updates texture data to PBO, the GPU copies textures from other PBO.
<span style= "FONT-SIZE:18PX;" >//"Index" is used to copy pixels from PBO to a Texture object//"Nextindex" for updating other PBO pixels index = (index + 1)%2;nextindex = (index + 1)%2;//bind texture and PBOGLB Indtexture (gl_texture_2d, Textureid); Glbindbufferarb (Gl_pixel_unpack_buffer_arb, Pboids[index]);//copy pixels from PBO to texture object/ /Use the offset (offset) instead of the pointer gltexsubimage2d (gl_texture_2d, 0, 0, 0, WIDTH, HEIGHT, Gl_bgra, Gl_unsigned_byte, 0); Bind PBO to update texture source data Glbindebufferarb (Gl_pixel_unpack_buffer_arb, Pboids[nextindex]);//Note glmapbufferarb () will cause synchronization problems 。 If the GPU is processing this buffer,glmapbufferarb () will wait until the GPU finishes its work. To avoid waiting, you can call Glbufferdataarb () and pass in a null pointer before calling//Glmapbufferarb (). If you do this, the data in the PBO above will//be discarded, and then Glmapbufferarb () returns a newly assigned pointer immediately, even if the GPU is still processing the previous data. Glbufferdatearb (Gl_pixel_unpack_buffer_arb, data_size, 0, Gl_stream_draw_arb);//Map buffer object to client memory glubyte* ptr = (GLubyte* ) Glmapbufferarb (Gl_pixel_unpack_buffer_arb, Gl_write_only_arb); if (PTR) {//Update data directly on the map buffer updatepixels (PTR, data_size); Glunmapbufferarb (Gl_PIXEL_UNPACK_BUFFER_ARB); Release map Buffer}//use ID 0 to release PBO is a good idea//once the 0 bindings are used, all pixel operations return the usual way Glbindbufferarb (Gl_pixel_unpack_buffer_arb, 0);</span>
----------------------------------------------------------------------------------------------------------- ----
Example: Asynchronous Read back
download source code and binary: Pbopack.zip
The demo app reads (packs pack) pixels from the frame buffer (left) to PBO, then changes the brightness of the image and draws it back to the right side of the window. You can open/close the PBO by pressing the SPACEBAR and measure the execution speed of the Glreadpixels ().
Regular Glreadpixels () blocks the pipeline, waits until all the pixels have been transferred, and then returns control to the app. Conversely, glreadpixels () with PBO can schedule asynchronous direct memory access transfers without waiting for a direct return. Therefore, when transmitting data in OpenGL (GPU) Direct memory, the application (CPU) can execute other threads immediately.
This demo uses a 2-pixel buffer. In the nth frame, the application uses Glreadpixels () to read pixels from the OpenGL frame buffer to PBO1, while processing pixel data in PBO2. These reads and processes can be done at the same time, because Glreadpixels () to PBO1 is returned immediately, and the CPU does not have to wait to process the data in PBO2. Then, we swap each frame in PBO1 and PBO2.
<span style= "FONT-SIZE:18PX;" >//"Index" is used to read pixel data from the frame buffer to pbo//"nextindex" to update pixels in other PBO index = (index + 1)%2;nextindex = (index + 1)%2;//sets the target framebuffer to read Object Glreadbuffer (Gl_front);//read pixels from the frame buffer to pbo//glreadpixels () should immediately return Glbindbufferarb (Gl_pixel_pack_buffer_arb, pboIds[ Index]); glreadpixels (0, 0, WIDTH, HEIGHT, Gl_bgra, Gl_unsigned_byte, 0);//Map PBO and then use the CPU to process the data Glbindbufferarb (gl_pixel_ Pack_buffer_arb, Pboids[nextindex]); glubyte* ptr = (glubyte*) glmapbufferarb (Gl_pixel_pack_buffer_arb, Gl_read_only_arb), if (PTR) { Processpixels (PTR, ...); Glunmapbufferarb (Gl_pixel_pack_buffer_arb);} Back to normal pixel operation Glbindbufferarb (Gl_pixel_pack_buffer_arb, 0); </span><span style= "FONT-SIZE:24PX;" ></span>
OpenGL pixel Buffer Object (PBO)