| Name |
| |
| APPLE_flush_buffer_range |
| |
| Name Strings |
| |
| GL_APPLE_flush_buffer_range |
| |
| Contact |
| |
| Chris Niederauer, Apple (ccn 'at' apple.com) |
| |
| Status |
| |
| Shipping on Mac OS X. |
| |
| Version |
| |
| Last Modified Date: 19 March 2008 |
| Author Revision: 1.1 |
| |
| Number |
| |
| 321 |
| |
| Dependencies |
| |
| Buffer Objects as per ARB_vertex_buffer_object or OpenGL 1.5 are required. |
| |
| If ARB_pixel_buffer_object is NOT supported and the OpenGL version is less |
| than 2.1, ignore references to PIXEL_UNPACK_BUFFER and PIXEL_PACK_BUFFER. |
| |
| If APPLE_fence or similar fencing mechanism is NOT suppported, Finish can |
| be used in place of TestObject, FinishObject, TestFence and FinishFence. |
| |
| Written based on the wording of the OpenGL 2.1 specification. |
| |
| Overview |
| |
| APPLE_flush_buffer_range expands the buffer object API to allow greater |
| performance when a client application only needs to write to a sub-range |
| of a buffer object. To that end, this extension introduces two new buffer |
| object features: non-serialized buffer modification and explicit sub-range |
| flushing for mapped buffer objects. |
| |
| OpenGL requires that commands occur in a FIFO manner meaning that any |
| changes to buffer objects either block until the data has been processed by |
| the OpenGL pipeline or else create extra copies to avoid such a block. By |
| providing a method to asynchronously modify buffer object data, an |
| application is then able to manage the synchronization points themselves |
| and modify ranges of data contained by a buffer object even though OpenGL |
| might still be using other parts of it. |
| |
| This extension also provides a method for explicitly flushing ranges of a |
| mapped buffer object so OpenGL does not have to assume that the entire |
| range may have been modified. |
| |
| Affects ARB_vertex_buffer_object, ARB_pixel_buffer_object and OpenGL 1.5 |
| Buffer Objects. |
| |
| Issues |
| |
| Should the ability to update other Buffer Object state such as BUFFER_SIZE |
| and BUFFER_USAGE be added to BufferParameteriAPPLE? |
| |
| RESOLVED: No. API already exists for setting this state and allowing |
| this new API to update this state would add more semantics that this |
| extension is not trying to address. Also as decided when working on |
| the ARB_vertex_buffer_object extension: "It is desirable for the |
| implementation to know the usage when the buffer is initialized, so |
| including it in the initialization command makes sense." |
| |
| Should a MapSubBuffer API be added to avoid having the application manually |
| flush memory which is not modified within a buffer object? |
| |
| RESOLVED: No. An application may still want to modify multiple |
| sections of a buffer object simultaneously such as for procedural data |
| and providing a range flushing routine allows an implementation to |
| effectively achieve the same performance benefits. |
| |
| Secondly, providing a MapSubBuffer routine might be confusing to |
| developers as one might think that MapSubBuffers could know which |
| sections need to block or provide temporary intermediary buffers and |
| in theory achieve the same benefits as adding a flag that states that |
| the application would like to asynchronously modify some buffer object |
| data; however, implementing a "smart" MapSubBuffer function would be |
| difficult to make efficient. |
| |
| When flushing ranges manually, should new API be added or should |
| BufferSubData be overloaded? |
| |
| RESOLVED: New API should be added specifically for this task. Trying |
| to override BufferSubData becomes cumbersome for many reasons. In |
| order to use BufferSubData, the behavior would need to change when |
| called inside of a MapBuffer/UnmapBuffer pair to not throw an error and |
| the <data> parameter would then either not be used or cause a specific |
| behavior. It is much simpler to provide new API specifically targeted |
| at the task of manually flushing memory regions. This is also less |
| prone to errors in legacy applications that may incorrectly use |
| BufferSubData in situations that should cause invalid operation errors |
| prior to the introduction of this extension. |
| |
| New Procedures and Functions |
| |
| void BufferParameteriAPPLE(enum target, enum pname, int param); |
| |
| void FlushMappedBufferRangeAPPLE(enum target, intptr offset, |
| sizeiptr size); |
| |
| New Tokens |
| |
| Accepted by the <pname> parameter of BufferParameteriAPPLE and |
| GetBufferParameteriv: |
| |
| BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 |
| BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 |
| |
| Additions to Chapter 2 of the OpenGL 2.0 Specification (Buffer Objects) |
| |
| - (2.9, p. 33) Add new BufferParameter parameters: |
| |
| Add to Table 2.6 (p. 34): |
| |
| Name Type Initial Value Legal Values |
| ------------------------------ ------- ------------- ------------ |
| BUFFER_SERIALIZED_MODIFY_APPLE boolean TRUE TRUE, FALSE |
| BUFFER_FLUSHING_UNMAP_APPLE boolean TRUE TRUE, FALSE |
| |
| Change Table 2.7 (p. 36) caption to: |
| |
| Table 2.7: Buffer object state set by BufferData. |
| |
| Add to the end of Section 2.9 (p. 38): |
| |
| The serialized modification and flushing unmap parameters are specified by |
| calling |
| |
| void BufferParameteriAPPLE(enum target, enum pname, int param); |
| |
| with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, |
| PIXEL_UNPACK_BUFFER, or PIXEL_PACK_BUFFER. <pname> is one of |
| BUFFER_SERIALIZED_MODIFY_APPLE or BUFFER_FLUSHING_UNMAP_APPLE and <param> |
| specifies the new value for parameter <pname>. |
| By setting the value of the parameter BUFFER_SERIALIZED_MODIFY_APPLE to |
| FALSE, the client must then manually synchronize any modifcations to the |
| buffer object data and usage by OpenGL. In order to maintain coherency |
| when BUFFER_SERIALIZED_MODIFY_APPLE is disabled, synchronization must be |
| done after drawing with a buffer object prior to mapping its data for |
| modification using fences. A fence, such as the type of fence defined in |
| the APPLE_fence extension, allows selective synchronization. The client |
| can set a fence immediately after drawing with the data in question and |
| test or finish that fence prior to calling MapBuffer or BufferSubData. |
| This serialization relaxation also applies to all OpenGL commands which may |
| write to a buffer object such as ReadPixels and GetTexImage. |
| Setting the value of the parameter BUFFER_FLUSHING_UNMAP_APPLE to FALSE |
| allows the client to specify regions of a mapped buffer object that have |
| been modified by calling |
| |
| void FlushMappedBufferRangeAPPLE(enum target, intptr offset, |
| sizeiptr size); |
| |
| prior to unmapping. <target> must be set to one of ARRAY_BUFFER, |
| ELEMENT_ARRAY_BUFFER, PIXEL_UNPACK_BUFFER, or PIXEL_PACK_BUFFER. <offset> |
| and <size> indicate the range of data in the buffer object that has been |
| modified in terms of basic machine units. An INVALID_VALUE error is |
| generated if <offset> or <size> is less than zero, or if <offset> + <size> |
| is greater than the value of BUFFER_SIZE. When BUFFER_FLUSHING_UNMAP_APPLE |
| is set to FALSE, FlushMappedBufferRangeAPPLE must be called on all modified |
| ranges of a mapped buffer object after the data within each specified range |
| has been modified and prior to unmapping it, allowing OpenGL to flush only |
| the portions of the buffer object that have been modified. Any modified |
| ranges of a mapped buffer object that are not explicitly flushed prior to |
| unmapping when BUFFER_FLUSHING_UNMAP_APPLE is set to FALSE become |
| undefined. |
| |
| Errors |
| |
| INVALID_ENUM is generated if the <target> parameter of |
| BufferParameteriAPPLE and FlushMappedBufferRangeAPPLE is not ARRAY_BUFFER, |
| ELEMENT_ARRAY_BUFFER, PIXEL_PACK_BUFFER or PIXEL_UNPACK_BUFFER. |
| |
| INVALID_ENUM is generated if the <pname> parameter of BufferParameteriAPPLE |
| is not BUFFER_SERIALIZED_MODIFY_APPLE or BUFFER_NON_FLUSHING_UNMAP_APPLE. |
| |
| INVALID_OPERATION is generated if BufferParameteriAPPLE or |
| FlushMappedBufferRangeAPPLE is executed while zero is bound to the <target> |
| parameter. |
| |
| INVALID_OPERATION is generated if FlushMappedBufferRangeAPPLE is called |
| outside the execution of a MapBuffer and the corresponding execution of |
| UnmapBuffer. |
| |
| INVALID_OPERATION may be generated if any of the commands defined in this |
| extension is executed between the execution of Begin and the corresponding |
| execution of End. |
| |
| INVALID_VALUE is generated if the <offset> or <size> parameters of |
| FlushMappedBufferRangeAPPLE are negative. |
| |
| INVALID_VALUE is generated if the <offset> and <size> parameters of |
| FlushMappedBufferRangeAPPLE define a region of memory that extends beyond |
| that allocated by BufferData. |
| |
| New State |
| |
| Add to Table 6.9 (p. 274): |
| Initial |
| Get Value Type Get Command Value Description Sec Attrib |
| ------------------------------ ---- -------------------- ------- ------------------------------ --- ------ |
| BUFFER_SERIALIZED_MODIFY_APPLE B GetBufferParameteriv TRUE Buffer serialized modify param 2.9 - |
| BUFFER_FLUSHING_UNMAP_APPLE B GetBufferParameteriv TRUE Buffer flushing unmap param 2.9 - |
| |
| New Implementation Dependent State |
| |
| None |
| |
| Usage Examples |
| |
| This extension can be used in place of using multiple buffer objects for |
| applications that may have algorithms that can not efficiently use the |
| existing buffer object API. |
| |
| Convenient macro definition for specifying buffer offsets: |
| |
| #define BUFFER_OFFSET(i) ((char *)NULL + (i)) |
| |
| Example of updating small amounts of data in a large VBO: |
| |
| // setup time |
| glBindBuffer(GL_ARRAY_BUFFER, my_vbo); |
| glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW); |
| glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); |
| |
| // update/draw time |
| glBindBuffer(GL_ARRAY_BUFFER, my_vbo); |
| GLvoid *data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); |
| for i to n { |
| if (need_to_change_region_i) { |
| // modify region i |
| glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, BUFFER_OFFSET(region_i_offset), region_i_size); |
| } |
| } |
| glUnmapBuffer(GL_ARRAY_BUFFER); |
| // draw from vertex data in buffer object |
| |
| Example of updating sections of a VBO serializing with APPLE_fence: |
| |
| // setup time |
| glBindBuffer(GL_ARRAY_BUFFER, my_vbo); |
| glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW); |
| glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_SERIALIZING_MODIFY_APPLE, GL_FALSE); |
| glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); |
| |
| // update/draw time |
| glBindBuffer(GL_ARRAY_BUFFER, my_vbo); |
| while(!glTestFenceAPPLE(current_regions_fence)) |
| { |
| // Do some more work if OpenGL is still using the |
| // portions of the VBO that we want to modify. |
| } |
| GLvoid *data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); |
| for i to n in regions { |
| if (need_to_change_region_i) { |
| // modify region i |
| glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, BUFFER_OFFSET(region_i_offset), region_i_size); |
| } |
| } |
| glUnmapBuffer(GL_ARRAY_BUFFER); |
| // draw from vertex data in region and set appropriate fence afterward |
| |
| Revision History |
| |
| 03/19/2008 1.1 |
| - Introduced errors when FlushMappedBufferRangeAPPLE is given bad |
| offset or size parameters. |
| - Clarified that FlushMappedBufferRangeAPPLE must be called after the |
| data in the mapped buffer object range has been modified. |
| |
| 10/04/2006 1.0 |
| - Initial public revision. |