| Name |
| |
| NV_pixel_buffer_object |
| |
| Name Strings |
| |
| GL_NV_pixel_buffer_object |
| |
| Contributors |
| |
| Contributors to ARB_pixel_buffer_object |
| Greg Roth, NVIDIA |
| |
| Contact |
| |
| Mathias Heyer, NVIDIA Corporation (mheyer 'at' nvidia.com) |
| |
| Status |
| |
| Complete. |
| |
| Version |
| |
| Last Modified Date: April 27th, 2020 |
| Revision: 3.0 |
| |
| Number |
| |
| OpenGL ES Extension #134 |
| |
| Dependencies |
| |
| Written based on the wording of the OpenGL ES 2.0 specification. |
| |
| OES_mapbuffer affects the definition of this specification |
| EXT_map_buffer_range affects the definition of this specification |
| |
| Overview |
| |
| This extension permits buffer objects to be used not only with vertex |
| array data, but also with pixel data. The intent is to provide more |
| acceleration opportunities for OpenGL pixel commands. |
| |
| While a single buffer object can be bound for both vertex arrays and |
| pixel commands, we use the designations vertex buffer object (VBO) |
| and pixel buffer object (PBO) to indicate their particular usage in |
| a given situation. |
| |
| This extension does not add any new functionality to buffer objects |
| themselves. It simply adds two new targets to which buffer objects |
| can be bound: GL_PIXEL_PACK_BUFFER_NV and GL_PIXEL_UNPACK_BUFFER_NV. |
| When a buffer object is bound to the GL_PIXEL_PACK_BUFFER_NV target, |
| commands such as glReadPixels pack (write) their data into a buffer |
| object. When a buffer object is bound to the GL_PIXEL_UNPACK_BUFFER_NV |
| target, commands such as glTexImage2D unpack (read) their |
| data from a buffer object. |
| |
| There are a several approaches to improve graphics performance |
| with PBOs. Some of the most interesting approaches are: |
| |
| - Streaming texture updates: If the application uses |
| glMapBufferOES/glMapBufferRangeEXT/glUnmapBufferOES to write |
| its data for glTexSubImage into a buffer object, at least one of |
| the data copies usually required to download a texture can be |
| eliminated, significantly increasing texture download performance. |
| |
| - Asynchronous glReadPixels: If an application needs to read back a |
| number of images and process them with the CPU, the existing GL |
| interface makes it nearly impossible to pipeline this operation. |
| The driver will typically send the hardware a readback command |
| when glReadPixels is called, and then wait for all of the data to |
| be available before returning control to the application. Then, |
| the application can either process the data immediately or call |
| glReadPixels again; in neither case will the readback overlap with |
| the processing. If the application issues several readbacks |
| into several buffer objects, however, and then maps each one to |
| process its data, then the readbacks can proceed in parallel with |
| the data processing. |
| |
| - Render to vertex array: The application can use a fragment |
| program to render some image into one of its buffers, then read |
| this image out into a buffer object via glReadPixels. Then, it can |
| use this buffer object as a source of vertex data. |
| |
| |
| New Procedures and Functions |
| |
| None. |
| |
| |
| New Tokens |
| |
| Accepted by the <target> parameters of BindBuffer, BufferData, |
| BufferSubData, MapBufferOES, MapBufferRangeEXT, UnmapBufferOES, |
| FlushMappedBufferRangeEXT, GetBufferParameteriv, and |
| GetBufferPointervOES: |
| |
| PIXEL_PACK_BUFFER_NV 0x88EB |
| PIXEL_UNPACK_BUFFER_NV 0x88EC |
| |
| Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, |
| GetFloatv: |
| |
| PIXEL_PACK_BUFFER_BINDING_NV 0x88ED |
| PIXEL_UNPACK_BUFFER_BINDING_NV 0x88EF |
| |
| |
| Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL Operation) |
| |
| -- Section 2.9 "Buffer Objects" |
| |
| Replace the first two paragraphs with: |
| |
| "The vertex data arrays described in section 2.8 are stored in |
| client memory. It is sometimes desirable to store frequently accessed |
| client data, such as vertex array and pixel data, in high-performance |
| server memory. GL buffer objects provide a mechanism for clients to |
| use to allocate, initialize, and access such memory." |
| |
| The name space for buffer objects is the unsigned integer, with zero |
| reserved for the GL. A buffer object is created by binding an unused |
| name to a buffer target. The binding is effected by calling |
| |
| void BindBuffer(enum target, uint buffer); |
| |
| <target> must be one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, |
| PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV. The ARRAY_BUFFER |
| target is discussed in section 2.9.1 The ELEMENT_ARRAY_BUFFER target |
| is discussed in section 2.9.2. The PIXEL_UNPACK_BUFFER_NV and |
| PIXEL_PACK_BUFFER_NV targets are discussed later in sections 3.7.1 and |
| 4.3. If the buffer object named <buffer> has not been |
| previously bound or has been deleted since the last binding, the |
| GL creates a new state vector, initialized with a zero-sized memory |
| buffer and comprising the state values listed in table 2.5." |
| |
| Replace the 5th paragraph with: |
| |
| "Initially, each buffer object target is bound to zero. There is |
| no buffer object corresponding to the name zero so client attempts |
| to modify or query buffer object state for a target bound to zero |
| generate an INVALID_OPERATION error." |
| |
| Replace the phrase listing the valid targets for BufferData in the |
| 9th paragraph with: |
| |
| "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, |
| PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV," |
| |
| In the 10th paragraph describing buffer object usage modes, replace |
| the phrase "specified once" with "specified once per repetition of |
| the usage pattern" for the STREAM_* and STATIC_* usage values. |
| |
| Also in the 10th paragraph describing buffer object usage modes, |
| replace the phrases "of a GL drawing command." and "for GL drawing |
| commands." with "for GL drawing and image specification commands." for |
| the *_DRAW usage values. |
| |
| Replace the phrase listing the valid targets for BufferSubData with: |
| |
| "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, |
| PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV." |
| |
| Replace the phrase listing the valid targets for MapBufferOES with: |
| |
| "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, |
| PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV." |
| |
| Replace the phrase listing the valid targets for UnmapBufferOES with: |
| |
| "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, |
| PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV." |
| |
| Replace the phrase listing the valid targets for MapBufferRangeEXT |
| with: |
| |
| "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, |
| PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV." |
| |
| Replace the phrase listing the valid targets for |
| FlushMappedBufferRangeEXT with: |
| |
| "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, |
| PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV." |
| |
| -- Section 2.9.2 "Array Indices in Buffer Objects" |
| |
| Delete the 3rd paragraph that explains how the ELEMENT_ARRAY_BUFFER |
| target is acceptable for the commands specified in section 2.9. |
| The updated section 2.9 language already says this. |
| |
| Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization) |
| |
| -- Section 3.6 "Pixel Rectangles" |
| |
| Replace the last two paragraphs with: |
| |
| "This section describes only how these rectangles are defined in |
| buffer object and client memory, and the steps involved in |
| transferring pixel rectangles from buffer object or client memory |
| to the GL or vice-versa. |
| Parameters controlling the encoding of pixels in buffer object or |
| client memory (for reading and writing) are set with the command |
| PixelStorei." |
| |
| -- Rename Section 3.6.1 "Pixel Storage Modes and Pixel Buffer Objects" |
| |
| Add to the end of the section: |
| |
| "In addition to storing pixel data in client memory, pixel data |
| may also be stored in buffer objects (described in section 2.9). |
| The current pixel unpack and pack buffer objects are designated |
| by the PIXEL_UNPACK_BUFFER_NV and PIXEL_PACK_BUFFER_NV targets |
| respectively. |
| |
| Initially, zero is bound for the PIXEL_UNPACK_BUFFER_NV, indicating |
| that image specification commands such as TexImage*D source their |
| pixels from client memory pointer parameters. However, if a non-zero |
| buffer object is bound as the current pixel unpack buffer, then |
| the pointer parameter is treated as an offset into the designated |
| buffer object." |
| |
| |
| -- Section 3.6.2 "Transfer of Pixel Rectangles", page 61. |
| |
| Change the 1st sentence of the 1st paragraph to read: |
| |
| "The process of transferring pixels encoded in buffer object |
| or client memory is diagrammed in figure 3.5." |
| |
| Change the 4th sentence of the 2nd paragraph to read: |
| |
| "<data> refers to the data to be transferred." |
| |
| [data is no longer necessarily a pointer.] |
| |
| Change the initial phrase in the 1st sentence of the 1st paragraph |
| in subsection "Unpacking" to read: |
| |
| "Data are taken from the currently bound pixel unpack buffer or |
| client memory as a sequence of..." |
| |
| Insert this paragraph after the 1st paragraph in subsection |
| "Unpacking": |
| |
| "If a pixel unpack buffer is bound (as indicated by a non-zero |
| value of PIXEL_UNPACK_BUFFER_BINDING_NV), <data> is an offset |
| into the pixel unpack buffer and the pixels are unpacked from the |
| buffer relative to this offset; otherwise, <data> is a pointer to |
| a block client memory and the pixels are unpacked from the client |
| memory relative to the pointer. If a pixel unpack buffer object |
| is bound and unpacking the pixel data according to the process |
| described below would access memory beyond the size of the pixel |
| unpack buffer's memory size, INVALID_OPERATION results. If a pixel |
| unpack buffer object is bound and <data> is not evenly divisible |
| into the number of basic machine units needed to store in memory the |
| corresponding GL data type from table 3.4 for the <type> parameter, |
| INVALID_OPERATION results." |
| |
| -- Section 3.7.1 "Texture Image Specification", page 66. |
| |
| Replace the last phrase in the 2nd to last sentence in the 1st |
| paragraph with: |
| |
| "and a reference to the image data in the currently bound pixel unpack |
| buffer or client memory, as described in section 3.6.2." |
| |
| Replace the 1st sentence in the 9th paragraph with: |
| |
| "The image itself (referred to by <data>) is a sequence of groups |
| of values." |
| |
| Replace the last paragraph with: |
| |
| "If the data argument of TexImage2D is a NULL pointer, and the |
| pixel unpack buffer object is zero, a two- or three-dimensional |
| texel array is created with the specified target, level, internalformat, |
| border, width, height, and depth, but with unspecified image contents. |
| In this case no pixel values are accessed in client memory, and no pixel |
| processing is performed. Errors are generated, however, exactly as though |
| the data pointer were valid. Otherwise if the pixel unpack buffer object |
| is non-zero, the data argument is treatedly normally to refer to the |
| beginning of the pixel unpack buffer object's data." |
| |
| -- Section 3.7.3 "Compressed Texture Images", page 73. |
| |
| Replace the 3rd sentence of the 2nd paragraph with: |
| |
| "<data> refers to compressed image data stored in the compressed |
| image format corresponding to internalformat. If a pixel |
| unpack buffer is bound (as indicated by a non-zero value of |
| PIXEL_UNPACK_BUFFER_BINDING_NV), <data> is an offset into the |
| pixel unpack buffer and the compressed data is read from the buffer |
| relative to this offset; otherwise, <data> is a pointer to a block |
| client memory and the compressed data is read from the client memory |
| relative to the pointer." |
| |
| Replace the 2nd sentence in the 3rd paragraph with: |
| |
| "Compressed texture images are treated as an array of <imageSize> |
| ubytes relative to <data>. If a pixel unpack buffer object is bound |
| and data+imageSize is greater than the size of the pixel buffer, |
| INVALID_OPERATION results." |
| |
| Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment |
| Operations and the Frame Buffer) |
| |
| -- Section 4.3 "Reading Pixels", page 104. |
| |
| Replace the first paragraph with: |
| |
| "Pixels may be read from the framebuffer to pixel pack buffer or |
| client memory using the ReadPixels commands, as described below. |
| Pixels may also be copied from pixel unpack buffer, client memory or |
| the framebuffer to texture images in the GL using the TexImage2D and |
| CopyTexImage2D commands, as described in section 3.7.1. |
| |
| -- Section 4.3.1 "Reading Pixels", page 104. |
| |
| Replace 1st sentence of the 1st paragraph with: |
| |
| "The method for reading pixels from the framebuffer and placing them in |
| pixel pack buffer or client memory is diagrammed in figure 4.2." |
| |
| Add this paragraph after the 1st paragraph: |
| |
| "Initially, zero is bound for the PIXEL_PACK_BUFFER_NV, indicating |
| that image read and query commands such as ReadPixels return |
| pixels results into client memory pointer parameters. However, if |
| a non-zero buffer object is bound as the current pixel pack buffer, |
| then the pointer parameter is treated as an offset into the designated |
| buffer object." |
| |
| Rename "Placement in Client Memory" to "Placement in Pixel Pack |
| Buffer or Client Memory". |
| |
| Insert this paragraph at the start of the newly renamed |
| subsection "Placement in Pixel Pack Buffer or Client Memory": |
| |
| "If a pixel pack buffer is bound (as indicated by a non-zero value |
| of PIXEL_PACK_BUFFER_BINDING_NV), <data> is an offset into the |
| pixel pack buffer and the pixels are packed into the |
| buffer relative to this offset; otherwise, <data> is a pointer to a |
| block client memory and the pixels are packed into the client memory |
| relative to the pointer. If a pixel pack buffer object is bound and |
| packing the pixel data according to the pixel pack storage state |
| would access memory beyond the size of the pixel pack buffer's |
| memory size, INVALID_OPERATION results. If a pixel pack buffer object |
| is bound and <data> is not evenly divisible into the number of basic |
| machine units needed to store in memory the corresponding GL data type |
| from table 3.5 for the <type> parameter, INVALID_OPERATION results." |
| |
| |
| Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions) |
| |
| None |
| |
| |
| Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State |
| Requests) |
| |
| --- Section 6.1.3 Enumerated Queries |
| |
| Change the 1st sentence of the 3rd paragraph to read: |
| "The command |
| void GetBufferParameteriv( enum target, enum value, T data ); |
| returns information about <target>, which may be one of ARRAY_BUFFER, |
| ELEMENT_ARRAY_BUFFER, PIXEL_PACK_BUFFER_NV, PIXEL_UNPACK_BUFFER_NV |
| indicating the currently bound vertex array, element array, pixel pack |
| and pixel unpack buffer object." |
| |
| -- Section 6.1.13 "Buffer Object Queries". |
| |
| (description of glGetBufferPointervOES) |
| Change the 2nd sentence of the 2nd paragraph to read: |
| "<target> is ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, PIXEL_PACK_BUFFER_NV, |
| or PIXEL_UNPACK_BUFFER_NV." |
| |
| |
| Errors |
| |
| INVALID_ENUM is generated if the <target> parameter of |
| BindBuffer, BufferData, BufferSubData, MapBufferOES, UnmapBufferOES, |
| GetBufferParameteriv or GetBufferPointervOES is not |
| one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, PIXEL_PACK_BUFFER_NV, |
| or PIXEL_UNPACK_BUFFER_NV. |
| |
| INVALID_OPERATION is generated if CompressedTexImage2D, |
| CompressedTexSubImage2D, TexImage2D or TexSubImage2D would unpack |
| (read) data from the currently bound PIXEL_UNPACK_BUFFER_NV buffer |
| object such that the memory reads required for the command would exceed |
| the memory (data store) size of the buffer object. |
| |
| INVALID_OPERATION is generated if ReadPixels or ReadnPixelsEXT |
| would pack (write) data to the currently bound PIXEL_PACK_BUFFER_NV |
| buffer object such that the memory writes required for the command would |
| exceed the memory (data store) size of the buffer object. |
| |
| INVALID_OPERATION is generated by ReadPixels or ReadnPixelsEXT |
| if the current PIXEL_PACK_BUFFER_BINDING_NV value is non-zero and the |
| table/image/values/span/img/data parameter is not evenly divisible |
| into the number of basic machine units needed to store in memory a |
| datum indicated by the type parameter. |
| |
| INVALID_OPERATION is generated by TexImage2D or TexSubImage2D |
| if current PIXEL_UNPACK_BUFFER_BINDING_NV value is non-zero and the data |
| parameter is not evenly divisible into the number of basic machine |
| units needed to store in memory a datum indicated by the type |
| parameter. |
| |
| Dependencies on OES_mapbuffer |
| |
| If OES_mapbuffer is not present, references to MapBufferOES and |
| UnmapBufferOES should be ignored and language referring to mapped |
| buffer objects should be removed. |
| |
| Dependencies on EXT_map_buffer_range |
| |
| If EXT_map_buffer_range is not present, references to |
| MapBufferRangeEXT anf FlushMappedBufferRangeEXT should be ignored. |
| |
| New State |
| |
| (table 6.13, Pixels, p. 147) |
| |
| Initial |
| Get Value Type Get Command Value Sec |
| ------------------------------- ---- ----------- ------- ------ |
| PIXEL_PACK_BUFFER_BINDING_NV Z+ GetIntegerv 0 4.3.1 |
| PIXEL_UNPACK_BUFFER_BINDING_NV Z+ GetIntegerv 0 3.6.1 |
| |
| |
| |
| Usage Examples |
| |
| Convenient macro definition for specifying buffer offsets: |
| |
| #define BUFFER_OFFSET(i) ((char *)NULL + (i)) |
| |
| Example 1: Render to vertex array: |
| |
| const int numberVertices = 100; |
| |
| // Create a buffer object for a number of vertices consisting of |
| // 4 float values per vertex |
| glGenBuffers(1, vertexBuffer); |
| glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, vertexBuffer); |
| glBufferData(GL_PIXEL_PACK_BUFFER_NV, numberVertices*4, |
| NULL, GL_DYNAMIC_DRAW); |
| |
| // Render vertex data into 100x1 strip of framebuffer using a |
| // shader program |
| glUseProgram(program); |
| renderVertexData(); |
| glBindProgramARB(FRAGMENT_PROGRAM_ARB, 0); |
| |
| // Read the vertex data back from framebuffer |
| glReadPixels(0, 0, numberVertices, 1, GL_BGRA, GL_UNSIGNED_BYTE, |
| BUFFER_OFFSET(0)); |
| |
| // Change the binding point of the buffer object to |
| // the vertex array binding point |
| glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); |
| |
| glEnableVertexAttribArray(0); |
| glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, BUFFER_OFFSET(0)); |
| glDrawArrays(TRIANGLE_STRIP, 0, numberVertices); |
| |
| |
| Example 2: Streaming textures |
| |
| Streaming textures using pixel buffer objects: |
| |
| const int texWidth = 256; |
| const int texHeight = 256; |
| const int texsize = texWidth * texHeight * 4; |
| void *pboMemory, *texData; |
| |
| // Define texture level zero (without an image); notice the |
| // explicit bind to the zero pixel unpack buffer object so that |
| // pass NULL for the image data leaves the texture image |
| // unspecified. |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER_NV, 0); |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, |
| GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| |
| // Create and bind texture image buffer object |
| glGenBuffers(1, &texBuffer); |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER_NV, texBuffer); |
| |
| // Setup texture environment |
| ... |
| |
| texData = getNextImage(); |
| |
| while (texData) { |
| |
| // Reset the contents of the texSize-sized buffer object |
| glBufferData(GL_PIXEL_UNPACK_BUFFER_NV, texSize, NULL, |
| GL_STREAM_DRAW); |
| |
| // Map the texture image buffer (the contents of which |
| // are undefined due to the previous glBufferData) |
| pboMemory = glMapBufferOES(GL_PIXEL_UNPACK_BUFFER_NV, |
| GL_WRITE_ONLY); |
| |
| // Modify (sub-)buffer data |
| memcpy(pboMemory, texData, texsize); |
| |
| // Unmap the texture image buffer |
| glUnmapBufferOES(GL_PIXEL_UNPACK_BUFFER_NV); |
| |
| // Update (sub-)teximage from texture image buffer |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, |
| GL_RGBA, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)); |
| |
| // Draw textured geometry |
| ... |
| |
| texData = getNextImage(); |
| } |
| |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER_NV, 0); |
| |
| |
| Example 3: Asynchronous glReadPixels |
| |
| Traditional glReadPixels: |
| |
| const int imagewidth = 640; |
| const int imageheight = 480; |
| GLubyte readBuffer[imagewidth*imageheight*4]; |
| |
| // Render to framebuffer |
| renderScene() |
| |
| // Read image from framebuffer |
| glReadPixels(0, 0, imagewidth, imageheight, GL_RGBA, |
| GL_UNSIGNED_BYTE, readBuffer); |
| |
| // Process image when glReadPixels returns after reading the |
| // whole buffer |
| processImage(readBuffer); |
| |
| |
| Asynchronous glReadPixels: |
| |
| const int imagewidth = 640; |
| const int imageheight = 480; |
| const int imageSize = imagewidth*imageheight*4; |
| |
| glGenBuffers(2, imageBuffers); |
| |
| glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[0]); |
| glBufferData(GL_PIXEL_PACK_BUFFER_NV, imageSize / 2, NULL, |
| GL_STREAM_DRAW); |
| |
| glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[1]); |
| glBufferData(GL_PIXEL_PACK_BUFFER_NV, imageSize / 2, NULL, |
| GL_STREAM_DRAW); |
| |
| // Render to framebuffer |
| glDrawBuffer(GL_BACK); |
| renderScene(); |
| |
| // Bind two different buffer objects and start the glReadPixels |
| // asynchronously. Each call will return directly after |
| // starting the DMA transfer. |
| glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[0]); |
| glReadPixels(0, 0, imagewidth, imageheight/2, GL_RGBA, |
| GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)); |
| |
| glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[1]); |
| glReadPixels(0, imageheight/2, imagewidth, imageheight/2, GL_RGBA, |
| GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)); |
| |
| // Process partial images. Mapping the buffer waits for |
| // outstanding DMA transfers into the buffer to finish. |
| glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[0]); |
| pboMemory1 = glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER_NV, 0, |
| imageSize/2, GL_MAP_READ_BIT_EXT); |
| processImage(pboMemory1); |
| glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[1]); |
| pboMemory2 = glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER_NV, 0, |
| imageSize/2, GL_MAP_READ_BIT_EXT); |
| processImage(pboMemory2); |
| |
| // Unmap the image buffers |
| glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[0]); |
| glUnmapBuffer(GL_PIXEL_PACK_BUFFER_NV); |
| glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[1]); |
| glUnmapBuffer(GL_PIXEL_PACK_BUFFER_NV); |
| |
| |
| Issues |
| |
| |
| 1) Can a given buffer be used for both vertex and pixel data? |
| |
| RESOLVED: YES. All buffers can be used with all buffer bindings, |
| in whatever combinations the application finds useful. Consider |
| yourself warned, however, by the following issue. |
| |
| 2) May implementations make use of the target as a hint to select |
| an appropriate memory space for the buffer? |
| |
| RESOLVED: YES, as long as such behavior is transparent to the |
| application. Some implementations may choose different memory |
| spaces for different targets. |
| In fact, one can imagine arbitrarily complicated heuristics for |
| selecting the memory space, based on factors such as the target, |
| the "usage" argument, and the application's observed behavior. |
| |
| While it is entirely legal to create a buffer object by binding |
| it to GL_ARRAY_BUFFER and loading it with data, then using it |
| with the GL_PIXEL_UNPACK_BUFFER_NV or GL_PIXEL_PACK_BUFFER_NV |
| binding, such behavior is liable to confuse the driver and may |
| hurt performance. If the driver implemented the hypothetical |
| heuristic described earlier, such a buffer might have already |
| been located in AGP memory, and so the driver would have to choose |
| between two bad options: relocate the buffer into video memory, or |
| accept lower performance caused by streaming pixel data from AGP. |
| |
| 3) Should the INVALID_OPERATION error be generated if a pixel |
| command would access data outside the range of the bound PBO? |
| |
| RESOLVED: YES. This requires considering the command parameters |
| (such as width/height/depth/format/type/pointer), the current |
| pixel store (pack/unpack) state, and the command operation itself |
| to determine the maximum addressed byte for the pixel command. |
| |
| This behavior should increase the reliability of using PBO and |
| guard against programmer mistakes. |
| |
| This is particularly important for glReadPixels where returning |
| data into a region outside the PBO could cause corruption of |
| application memory. |
| |
| Such bounds checking is substantially more expensive for VBO |
| accesses because bounds checking on a per-vertex element basis |
| for each of multiple enabled vertex arrays prior to performing |
| the command compromises the performance justification of VBO. |
| |
| 4) If a pixel command with a bound PBO accesses data outside the |
| range of the PBO, thereby generating a GL_INVALID_OPERATION error, |
| can the pixel command end up being partially processed? |
| |
| RESOLVED: NO. As for all GL errors excepting GL_OUT_OF_MEMORY |
| situations, "the command generating the error is ignored so that |
| it has no effect on GL state or framebuffer contents." |
| |
| This means implementations must determine before the pixel command |
| is performed whether the resulting read or write operations on |
| the bound PBO will exceed the size of the PBO. |
| |
| This means an implementation is NOT allowed to detect out of |
| bounds accesses in the middle of performing the command. |
| |
| 5) Should an INVALID_OPERATION error be generated if the offset |
| within a pixel buffer to a datum comprising of N basic machine |
| units is not a multiple of N? |
| |
| RESOLVED: YES. This was stated for VBOs but no error was |
| defined if the rule was violated. Perhaps this needs to be |
| better specified for VBO. |
| |
| For PBO, it is reasonable and cheap to enforce the alignment rule. |
| For pixel commands it means making sure the offset is evenly |
| divisible by the component or group size in basic machine units. |
| |
| This check is independent of the pixel store state because the |
| pixel store state is specified in terms of pixels (not basic |
| machine units) so pixel store addressing cannot create an |
| unaligned access as long as the base offset is aligned. |
| |
| Certain commands (specifically, |
| glCompressedTexImage2D, glCompressedTexSubImage2D) are not |
| affected by this error because the data accessed is addressed |
| at the granularity of basic machine units. |
| |
| 6) Various commands do not make explicit reference to supporting |
| packing or unpacking from a pixel buffer object but rather specify |
| that parameters are handled in the same manner as glReadPixels, |
| or the glCompressedTexImage commands. So do such |
| commands (example: glCompressedTexSubImage2D) use pixel buffers? |
| |
| RESOLVED: YES. Commands that have their behavior defined based |
| on commands that read or write from pixel buffers will themselves |
| read or write from pixel buffers. Relying on this reduces the |
| amount of specification language to be updated. |
| |
| 7) What is the complete list of commands that can unpack (read) |
| pixels from the current pixel unpack buffer object? |
| |
| glCompressedTexImage2D |
| glCompressedTexSubImage2D |
| glTexImage2D |
| glTexSubImage2D |
| |
| 8) What is the complete list of commands that can pack (write) |
| pixels into the current pixel pack buffer object? |
| |
| glReadPixels |
| |
| 9) Prior to this extension, passing zero for the data argument of |
| glTexImage2D defined a texture image level without supplying an image. |
| How does this behavior change with this extension? |
| |
| RESOLVED: The "unspecified image" behavior of the glTexImage |
| calls only applies when bound to a zero pixel unpack buffer |
| object. |
| |
| When bound to a non-zero pixel unpack buffer object, the data |
| argument to these calls is treated as an offset rather than |
| a pointer so zero is a reasonable and even likely value that |
| corresponds to the very beginning of the buffer object's data. |
| |
| So to create a texture image level with unspecified image data, |
| you MUST bind to the zero pixel unpack buffer object. |
| |
| See the ammended language at the end of section 3.7.1. |
| |
| 10) How does this extension support video frame grabbers? |
| |
| RESOLVED: This extension extends buffer objects so they can |
| operate with pixel commands, rather than just vertex array |
| commands. |
| |
| We anticipate that a future extension may provide a mechanism |
| for transferring video frames from video frame grabber hardware |
| or vertices from motion capture hardware (or any other source |
| of aquired real-time data) directly into a buffer object to |
| eliminate a copy. Ideally, such transfers would be possible |
| without requiring mapping of the buffer object. But this |
| extension does not provide such functionality. |
| |
| We anticipate such functionality to involve binding a buffer |
| object to a new target type, configuring a source (or sink) for |
| data (video frames, motion capture vertex sets, etc.), and then |
| commands to initiate data transfers to the bound buffer object. |
| |
| 11) Is this the "right" way to expose render-to-vertex-array? |
| |
| DISCUSSION: You can use this extension to render an image |
| into a framebuffer, copy the pixels into a buffer object with |
| glReadPixels, and then configure vertex arrays to source the pixel |
| data as vertex attributes. This necessarily involves a copy |
| from the framebuffer to the buffer object. Future extensions |
| may provide mechanisms for copy-free render-to-vertex-array |
| capabilities but that is not a design goal of this extension. |
| |
| Revision History |
| |
| 3 04/27/2020 fix example code: GL_STREAM_READ is not available in ES2.0 |
| glMapBufferOES does not allow reading from the mapped pointer. |
| 2 10/23/2012 more cleanup, interaction with EXT_map_buffer_range |
| 1 04/19/2012 initial revision |
| - took ARB_pixel_buffer_object, stripped everything not applicable to |
| ES, changed references to tables and sections; changed all wording |
| to fit ES' language. |
| |