blob: d3467afb109f499f52d29f559d40ec4f89020985 [file] [log] [blame]
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.