1Name 2 3 APPLE_flush_buffer_range 4 5Name Strings 6 7 GL_APPLE_flush_buffer_range 8 9Contact 10 11 Chris Niederauer, Apple (ccn 'at' apple.com) 12 13Status 14 15 Shipping on Mac OS X. 16 17Version 18 19 Last Modified Date: 19 March 2008 20 Author Revision: 1.1 21 22Number 23 24 321 25 26Dependencies 27 28 Buffer Objects as per ARB_vertex_buffer_object or OpenGL 1.5 are required. 29 30 If ARB_pixel_buffer_object is NOT supported and the OpenGL version is less 31 than 2.1, ignore references to PIXEL_UNPACK_BUFFER and PIXEL_PACK_BUFFER. 32 33 If APPLE_fence or similar fencing mechanism is NOT suppported, Finish can 34 be used in place of TestObject, FinishObject, TestFence and FinishFence. 35 36 Written based on the wording of the OpenGL 2.1 specification. 37 38Overview 39 40 APPLE_flush_buffer_range expands the buffer object API to allow greater 41 performance when a client application only needs to write to a sub-range 42 of a buffer object. To that end, this extension introduces two new buffer 43 object features: non-serialized buffer modification and explicit sub-range 44 flushing for mapped buffer objects. 45 46 OpenGL requires that commands occur in a FIFO manner meaning that any 47 changes to buffer objects either block until the data has been processed by 48 the OpenGL pipeline or else create extra copies to avoid such a block. By 49 providing a method to asynchronously modify buffer object data, an 50 application is then able to manage the synchronization points themselves 51 and modify ranges of data contained by a buffer object even though OpenGL 52 might still be using other parts of it. 53 54 This extension also provides a method for explicitly flushing ranges of a 55 mapped buffer object so OpenGL does not have to assume that the entire 56 range may have been modified. 57 58 Affects ARB_vertex_buffer_object, ARB_pixel_buffer_object and OpenGL 1.5 59 Buffer Objects. 60 61Issues 62 63 Should the ability to update other Buffer Object state such as BUFFER_SIZE 64 and BUFFER_USAGE be added to BufferParameteriAPPLE? 65 66 RESOLVED: No. API already exists for setting this state and allowing 67 this new API to update this state would add more semantics that this 68 extension is not trying to address. Also as decided when working on 69 the ARB_vertex_buffer_object extension: "It is desirable for the 70 implementation to know the usage when the buffer is initialized, so 71 including it in the initialization command makes sense." 72 73 Should a MapSubBuffer API be added to avoid having the application manually 74 flush memory which is not modified within a buffer object? 75 76 RESOLVED: No. An application may still want to modify multiple 77 sections of a buffer object simultaneously such as for procedural data 78 and providing a range flushing routine allows an implementation to 79 effectively achieve the same performance benefits. 80 81 Secondly, providing a MapSubBuffer routine might be confusing to 82 developers as one might think that MapSubBuffers could know which 83 sections need to block or provide temporary intermediary buffers and 84 in theory achieve the same benefits as adding a flag that states that 85 the application would like to asynchronously modify some buffer object 86 data; however, implementing a "smart" MapSubBuffer function would be 87 difficult to make efficient. 88 89 When flushing ranges manually, should new API be added or should 90 BufferSubData be overloaded? 91 92 RESOLVED: New API should be added specifically for this task. Trying 93 to override BufferSubData becomes cumbersome for many reasons. In 94 order to use BufferSubData, the behavior would need to change when 95 called inside of a MapBuffer/UnmapBuffer pair to not throw an error and 96 the <data> parameter would then either not be used or cause a specific 97 behavior. It is much simpler to provide new API specifically targeted 98 at the task of manually flushing memory regions. This is also less 99 prone to errors in legacy applications that may incorrectly use 100 BufferSubData in situations that should cause invalid operation errors 101 prior to the introduction of this extension. 102 103New Procedures and Functions 104 105 void BufferParameteriAPPLE(enum target, enum pname, int param); 106 107 void FlushMappedBufferRangeAPPLE(enum target, intptr offset, 108 sizeiptr size); 109 110New Tokens 111 112 Accepted by the <pname> parameter of BufferParameteriAPPLE and 113 GetBufferParameteriv: 114 115 BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 116 BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 117 118Additions to Chapter 2 of the OpenGL 2.0 Specification (Buffer Objects) 119 120 - (2.9, p. 33) Add new BufferParameter parameters: 121 122 Add to Table 2.6 (p. 34): 123 124 Name Type Initial Value Legal Values 125 ------------------------------ ------- ------------- ------------ 126 BUFFER_SERIALIZED_MODIFY_APPLE boolean TRUE TRUE, FALSE 127 BUFFER_FLUSHING_UNMAP_APPLE boolean TRUE TRUE, FALSE 128 129 Change Table 2.7 (p. 36) caption to: 130 131 Table 2.7: Buffer object state set by BufferData. 132 133 Add to the end of Section 2.9 (p. 38): 134 135 The serialized modification and flushing unmap parameters are specified by 136 calling 137 138 void BufferParameteriAPPLE(enum target, enum pname, int param); 139 140 with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, 141 PIXEL_UNPACK_BUFFER, or PIXEL_PACK_BUFFER. <pname> is one of 142 BUFFER_SERIALIZED_MODIFY_APPLE or BUFFER_FLUSHING_UNMAP_APPLE and <param> 143 specifies the new value for parameter <pname>. 144 By setting the value of the parameter BUFFER_SERIALIZED_MODIFY_APPLE to 145 FALSE, the client must then manually synchronize any modifcations to the 146 buffer object data and usage by OpenGL. In order to maintain coherency 147 when BUFFER_SERIALIZED_MODIFY_APPLE is disabled, synchronization must be 148 done after drawing with a buffer object prior to mapping its data for 149 modification using fences. A fence, such as the type of fence defined in 150 the APPLE_fence extension, allows selective synchronization. The client 151 can set a fence immediately after drawing with the data in question and 152 test or finish that fence prior to calling MapBuffer or BufferSubData. 153 This serialization relaxation also applies to all OpenGL commands which may 154 write to a buffer object such as ReadPixels and GetTexImage. 155 Setting the value of the parameter BUFFER_FLUSHING_UNMAP_APPLE to FALSE 156 allows the client to specify regions of a mapped buffer object that have 157 been modified by calling 158 159 void FlushMappedBufferRangeAPPLE(enum target, intptr offset, 160 sizeiptr size); 161 162 prior to unmapping. <target> must be set to one of ARRAY_BUFFER, 163 ELEMENT_ARRAY_BUFFER, PIXEL_UNPACK_BUFFER, or PIXEL_PACK_BUFFER. <offset> 164 and <size> indicate the range of data in the buffer object that has been 165 modified in terms of basic machine units. An INVALID_VALUE error is 166 generated if <offset> or <size> is less than zero, or if <offset> + <size> 167 is greater than the value of BUFFER_SIZE. When BUFFER_FLUSHING_UNMAP_APPLE 168 is set to FALSE, FlushMappedBufferRangeAPPLE must be called on all modified 169 ranges of a mapped buffer object after the data within each specified range 170 has been modified and prior to unmapping it, allowing OpenGL to flush only 171 the portions of the buffer object that have been modified. Any modified 172 ranges of a mapped buffer object that are not explicitly flushed prior to 173 unmapping when BUFFER_FLUSHING_UNMAP_APPLE is set to FALSE become 174 undefined. 175 176Errors 177 178 INVALID_ENUM is generated if the <target> parameter of 179 BufferParameteriAPPLE and FlushMappedBufferRangeAPPLE is not ARRAY_BUFFER, 180 ELEMENT_ARRAY_BUFFER, PIXEL_PACK_BUFFER or PIXEL_UNPACK_BUFFER. 181 182 INVALID_ENUM is generated if the <pname> parameter of BufferParameteriAPPLE 183 is not BUFFER_SERIALIZED_MODIFY_APPLE or BUFFER_NON_FLUSHING_UNMAP_APPLE. 184 185 INVALID_OPERATION is generated if BufferParameteriAPPLE or 186 FlushMappedBufferRangeAPPLE is executed while zero is bound to the <target> 187 parameter. 188 189 INVALID_OPERATION is generated if FlushMappedBufferRangeAPPLE is called 190 outside the execution of a MapBuffer and the corresponding execution of 191 UnmapBuffer. 192 193 INVALID_OPERATION may be generated if any of the commands defined in this 194 extension is executed between the execution of Begin and the corresponding 195 execution of End. 196 197 INVALID_VALUE is generated if the <offset> or <size> parameters of 198 FlushMappedBufferRangeAPPLE are negative. 199 200 INVALID_VALUE is generated if the <offset> and <size> parameters of 201 FlushMappedBufferRangeAPPLE define a region of memory that extends beyond 202 that allocated by BufferData. 203 204New State 205 206 Add to Table 6.9 (p. 274): 207 Initial 208 Get Value Type Get Command Value Description Sec Attrib 209 ------------------------------ ---- -------------------- ------- ------------------------------ --- ------ 210 BUFFER_SERIALIZED_MODIFY_APPLE B GetBufferParameteriv TRUE Buffer serialized modify param 2.9 - 211 BUFFER_FLUSHING_UNMAP_APPLE B GetBufferParameteriv TRUE Buffer flushing unmap param 2.9 - 212 213New Implementation Dependent State 214 215 None 216 217Usage Examples 218 219 This extension can be used in place of using multiple buffer objects for 220 applications that may have algorithms that can not efficiently use the 221 existing buffer object API. 222 223 Convenient macro definition for specifying buffer offsets: 224 225 #define BUFFER_OFFSET(i) ((char *)NULL + (i)) 226 227 Example of updating small amounts of data in a large VBO: 228 229 // setup time 230 glBindBuffer(GL_ARRAY_BUFFER, my_vbo); 231 glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW); 232 glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); 233 234 // update/draw time 235 glBindBuffer(GL_ARRAY_BUFFER, my_vbo); 236 GLvoid *data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); 237 for i to n { 238 if (need_to_change_region_i) { 239 // modify region i 240 glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, BUFFER_OFFSET(region_i_offset), region_i_size); 241 } 242 } 243 glUnmapBuffer(GL_ARRAY_BUFFER); 244 // draw from vertex data in buffer object 245 246 Example of updating sections of a VBO serializing with APPLE_fence: 247 248 // setup time 249 glBindBuffer(GL_ARRAY_BUFFER, my_vbo); 250 glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW); 251 glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_SERIALIZING_MODIFY_APPLE, GL_FALSE); 252 glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); 253 254 // update/draw time 255 glBindBuffer(GL_ARRAY_BUFFER, my_vbo); 256 while(!glTestFenceAPPLE(current_regions_fence)) 257 { 258 // Do some more work if OpenGL is still using the 259 // portions of the VBO that we want to modify. 260 } 261 GLvoid *data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); 262 for i to n in regions { 263 if (need_to_change_region_i) { 264 // modify region i 265 glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, BUFFER_OFFSET(region_i_offset), region_i_size); 266 } 267 } 268 glUnmapBuffer(GL_ARRAY_BUFFER); 269 // draw from vertex data in region and set appropriate fence afterward 270 271Revision History 272 273 03/19/2008 1.1 274 - Introduced errors when FlushMappedBufferRangeAPPLE is given bad 275 offset or size parameters. 276 - Clarified that FlushMappedBufferRangeAPPLE must be called after the 277 data in the mapped buffer object range has been modified. 278 279 10/04/2006 1.0 280 - Initial public revision. 281