1Name 2 3 NV_fence 4 5Name Strings 6 7 GL_NV_fence 8 9Contact 10 11 John Spitzer, NVIDIA Corporation (jspitzer 'at' nvidia.com) 12 Mark Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com) 13 14Contributors 15 16 John Spitzer 17 Mark Kilgard 18 Acorn Pooley 19 20Notice 21 22 Copyright NVIDIA Corporation, 2000, 2001. 23 24IP Status 25 26 NVIDIA Proprietary. 27 28Status 29 30 Shipping as of June 8, 2000 (version 1.0) 31 32 Shipping as of November, 2003 (version 1.1) 33 34 Version 1.2 adds ES support and clarification; otherwise identical to 1.1. 35 36Version 37 38 December 17, 2008 (version 1.2) 39 40Number 41 42 OpenGL Extension #222 43 OpenGL ES Extension #52 44 45Dependencies 46 47 This extension is written against the OpenGL 1.2.1 Specification. 48 It can also be used with OpenGL ES (see the section, "Dependencies on 49 OpenGL ES," below). 50 51Overview 52 53 The goal of this extension is provide a finer granularity of 54 synchronizing GL command completion than offered by standard OpenGL, 55 which offers only two mechanisms for synchronization: Flush and Finish. 56 Since Flush merely assures the user that the commands complete in a 57 finite (though undetermined) amount of time, it is, thus, of only 58 modest utility. Finish, on the other hand, stalls CPU execution 59 until all pending GL commands have completed. This extension offers 60 a middle ground - the ability to "finish" a subset of the command 61 stream, and the ability to determine whether a given command has 62 completed or not. 63 64 This extension introduces the concept of a "fence" to the OpenGL 65 command stream. Once the fence is inserted into the command stream, it 66 can be queried for a given condition - typically, its completion. 67 Moreover, the application may also request a partial Finish -- that is, 68 all commands prior to the fence will be forced to complete until control 69 is returned to the calling process. These new mechanisms allow for 70 synchronization between the host CPU and the GPU, which may be accessing 71 the same resources (typically memory). 72 73 This extension is useful in conjunction with NV_vertex_array_range 74 to determine when vertex information has been pulled from the 75 vertex array range. Once a fence has been tested TRUE or finished, 76 all vertex indices issued before the fence must have been pulled. 77 This ensures that the vertex data memory corresponding to the issued 78 vertex indices can be safely modified (assuming no other outstanding 79 vertex indices are issued subsequent to the fence). 80 81Issues 82 83 Do we need an IsFenceNV command? 84 85 RESOLUTION: Yes. Not sure who would use this, but it's in there. 86 Semantics currently follow the texture object definition -- 87 that is, calling IsFenceNV before SetFenceNV will return FALSE. 88 89 Are the fences sharable between multiple contexts? 90 91 RESOLUTION: No. 92 93 Potentially this could change with a subsequent extension. 94 95 What other conditions will be supported? 96 97 Only ALL_COMPLETED_NV will be supported initially. Future extensions 98 may wish to implement additional fence conditions. 99 100 What is the relative performance of the calls? 101 102 Execution of a SetFenceNV is not free, but will not trigger a 103 Flush or Finish. 104 105 Is the TestFenceNV call really necessary? How often would this be used 106 compared to the FinishFenceNV call (which also flushes to ensure this 107 happens in finite time)? 108 109 It is conceivable that a user may use TestFenceNV to decide 110 which portion of memory should be used next without stalling 111 the CPU. An example of this would be a scenario where a single 112 AGP buffer is used for both static (unchanged for multiple frames) 113 and dynamic (changed every frame) data. If the user has written 114 dynamic data to all banks dedicated to dynamic data, and still 115 has more dynamic objects to write, the user would first want to 116 check if the first dynamic object has completed, before writing 117 into the buffer. If the object has not completed, instead of 118 stalling the CPU with a FinishFenceNV call, it would possibly 119 be better to start overwriting static objects instead. 120 121 What should happen if TestFenceNV is called for a name before SetFenceNV 122 is called? 123 124 We generate an INVALID_OPERATION error, and return TRUE. 125 This follows the semantics for texture object names before 126 they are bound, in that they acquire their state upon binding. 127 We will arbitrarily return TRUE for consistency. 128 129 What should happen if FinishFenceNV is called for a name before 130 SetFenceNV is called? 131 132 RESOLUTION: Generate an INVALID_OPERATION error because the 133 fence id does not exist yet. SetFenceNV must be called to create 134 a fence. 135 136 Do we need a mechanism to query which condition a given fence was 137 set with? 138 139 RESOLUTION: Yes, use glGetFenceivNV with FENCE_CONDITION_NV. 140 141 Should we allow these commands to be compiled within display list? 142 Which ones? How about within Begin/End pairs? 143 144 RESOLUTION: DeleteFencesNV, FinishFenceNV, GenFencesNV, 145 TestFenceNV, and IsFenceNV are executed immediately while 146 SetFenceNV is compiled. Do not allow any of these commands 147 within Begin/End pairs. 148 149 Can fences be used as a form of performance monitoring? 150 151 Yes, with some caveats. By setting and testing or finishing 152 fences, developers can measure the GPU latency for completing 153 GL operations. For example, developers might do the following: 154 155 start = getCurrentTime(); 156 updateTextures(); 157 glSetFenceNV(TEXTURE_LOAD_FENCE, GL_ALL_COMPLETED_NV); 158 drawBackground(); 159 glSetFenceNV(DRAW_BACKGROUND_FENCE, GL_ALL_COMPLETED_NV); 160 drawCharacters(); 161 glSetFenceNV(DRAW_CHARACTERS_FENCE, GL_ALL_COMPLETED_NV); 162 163 glFinishFenceNV(TEXTURE_LOAD_FENCE); 164 textureLoadEnd = getCurrentTime(); 165 166 glFinishFenceNV(DRAW_BACKGROUND_FENCE); 167 drawBackgroundEnd = getCurrentTime(); 168 169 glFinishFenceNV(DRAW_CHARACTERS_FENCE); 170 drawCharactersEnd = getCurrentTime(); 171 172 printf("texture load time = %d\n", textureLoadEnd - start); 173 printf("draw background time = %d\n", drawBackgroundEnd - textureLoadEnd); 174 printf("draw characters time = %d\n", drawCharacters - drawBackgroundEnd); 175 176 Note that there is a small amount of overhead associated with 177 inserting each fence into the GL command stream. Each fence 178 causes the GL command stream to momentarily idle (idling the 179 entire GPU pipeline). The significance of this idling should 180 be small if there are a small number of fences and large amount 181 of intervening commands. 182 183 If the time between two fences is zero or very near zero, 184 it probably means that a GPU-CPU synchronization such as a 185 glFinish probably occurred. A glFinish is an explicit GPU-CPU 186 synchronization, but sometimes implicit GPU-CPU synchronizations 187 are performed by the driver. 188 189 What happens if you set the same fence object twice? 190 191 The second SetFenceNV clobbers whatever status the fence object 192 previously had by forcing the object's status to GL_TRUE. 193 The completion of the first SetFenceNV's fence command placed 194 in the command stream is ignored (its completion does NOT 195 update the fence object's status). The second SetFenceNV sets a 196 new fence command in the GL command stream. This second fence 197 command will update the fence object's status (assuming it is 198 not ignored by a subsequent SetFenceNV to the same fence object). 199 200 What happens to a fence command that is still pending execution 201 when its fence object is deleted? 202 203 The fence command completion is ignored. 204 205 What happens if you use an arbitrary number for the SetFenceNV() <fence> 206 parameter instead of obtaining the name from GenFences()? 207 208 This works fine (just as with texture objects). 209 210New Procedures and Functions 211 212 void GenFencesNV(sizei n, uint *fences); 213 214 void DeleteFencesNV(sizei n, const uint *fences); 215 216 void SetFenceNV(uint fence, enum condition); 217 218 boolean TestFenceNV(uint fence); 219 220 void FinishFenceNV(uint fence); 221 222 boolean IsFenceNV(uint fence); 223 224 void GetFenceivNV(uint fence, enum pname, int *params); 225 226New Tokens 227 228 Accepted by the <condition> parameter of SetFenceNV: 229 230 ALL_COMPLETED_NV 0x84F2 231 232 Accepted by the <pname> parameter of GetFenceivNV: 233 234 FENCE_STATUS_NV 0x84F3 235 FENCE_CONDITION_NV 0x84F4 236 237Additions to Chapter 5 of the OpenGL 1.2.1 Specification (Special Functions) 238 239 Add to the end of Section 5.4 "Display Lists" 240 241 "DeleteFencesNV, FinishFenceNV, GenFencesNV, GetFenceivNV, 242 TestFenceNV, and IsFenceNV are not complied into display lists but 243 are executed immediately." 244 245 After the discussion of Flush and Finish (Section 5.5) add a 246 description of the fence operations: 247 248 "5.X Fences 249 250 The command 251 252 void SetFenceNV(uint fence, enum condition); 253 254 creates a fence object named <fence> if one does not already exist 255 and sets a fence command within the GL command stream. If the named 256 fence object already exists, a new fence command is set within the GL 257 command stream (and any previous pending fence command corresponding 258 to the fence object is ignored). Whether or not a new fence object is 259 created, SetFenceNV assigns the named fence object a status of FALSE 260 and a condition as set by the condition argument. The condition 261 argument must be ALL_COMPLETED_NV. Once the fence's condition is 262 satisfied within the command stream, the corresponding fence object's 263 state is changed to TRUE. For a condition of ALL_COMPLETED_NV, 264 this is completion of the fence command and all preceding commands. 265 No other state is affected by execution of the fence command. The name 266 <fence> may be one returned by GenFencesNV() but that is not required. 267 268 A fence's state can be queried by calling the command 269 270 boolean TestFenceNV(uint fence); 271 272 The command 273 274 void FinishFenceNV(uint fence); 275 276 forces all GL commands prior to the fence to satisfy the condition 277 set within SetFenceNV, which, in this spec, is always completion. 278 FinishFenceNV does not return until all effects from these commands 279 on GL client and server state and the framebuffer are fully realized. 280 281 The command 282 283 void GenFencesNV(sizei n, uint *fences); 284 285 returns n previously unused fence names in fences. These names 286 are marked as used, for the purposes of GenFencesNV only, but 287 corresponding fence objects do not exist (have no state) until created 288 with SetFenceNV(). 289 290 Fences are deleted by calling 291 292 void DeleteFencesNV(sizei n, const uint *fences); 293 294 fences contains n names of fences to be deleted. After a fence is 295 deleted, it has no state, and its name is again unused. Unused names 296 in fences are silently ignored. 297 298 If the fence passed to TestFenceNV or FinishFenceNV is not the name of an 299 existing fence, the error INVALID_OPERATION is generated. In this case, 300 TestFenceNV will return TRUE, for the sake of consistency. 301 302 State must be maintained to indicate which fence integers are 303 currently used or set. In the initial state, no indices are in use. 304 When a fence integer is set, the condition and status of the fence 305 are also maintained. The status is a boolean. The condition is 306 the value last set as the condition by SetFenceNV. 307 308 Once the status of a fence has been finished (via FinishFenceNV) 309 or tested and the returned status is TRUE (via either TestFenceNV 310 or GetFenceivNV querying the FENCE_STATUS_NV), the status remains 311 TRUE until the next SetFenceNV of the fence." 312 313Additions to Chapter 6 of the OpenGL 1.2.1 Specification (State and State Requests) 314 315 Insert new section after Section 6.1.10 "Minmax Query" 316 317 "6.1.11 Fence Query 318 319 The command 320 321 boolean IsFenceNV(uint fence); 322 323 return TRUE if <fence> is the name of an existing fence. If <fence> is 324 not the name of an existing fence, or if an error condition occurs, 325 IsFenceNV returns FALSE. A name returned by GenFencesNV, but not yet set 326 via SetFenceNV, is not the name of an existing fence. 327 328 The command 329 330 void GetFenceivNV(uint fence, enum pname, int *params) 331 332 obtains the indicated fence state for the specified fence in the array 333 params. pname must be either FENCE_STATUS_NV or FENCE_CONDITION_NV. 334 The INVALID_OPERATION error is generated if the named fence does 335 not exist." 336 337Additions to the GLX Specification 338 339 None 340 341GLX Protocol 342 343 Seven new GL commands are added. 344 345 The following rendering command is sent to the sever as part of a 346 glXRender request: 347 348 SetFenceNV 349 2 12 rendering command length 350 2 4143 rendering command opcode 351 4 CARD32 fence 352 4 CARD32 condition 353 354 The remaining five commands are non-rendering commands. These 355 commands are sent separately (i.e., not as part of a glXRender or 356 glXRenderLarge request), using the glXVendorPrivateWithReply request: 357 358 DeleteFencesNV 359 1 CARD8 opcode (X assigned) 360 1 17 GLX opcode (glXVendorPrivateWithReply) 361 2 4+n request length 362 4 1276 vendor specific opcode 363 4 GLX_CONTEXT_TAG context tag 364 4 INT32 n 365 n*4 LISTofCARD32 fences 366 367 GenFencesNV 368 1 CARD8 opcode (X assigned) 369 1 17 GLX opcode (glXVendorPrivateWithReply) 370 2 4 request length 371 4 1277 vendor specific opcode 372 4 GLX_CONTEXT_TAG context tag 373 4 INT32 n 374 => 375 1 1 reply 376 1 unused 377 2 CARD16 sequence number 378 4 n reply length 379 24 unused 380 n*4 LISTofCARD322 fences 381 382 IsFenceNV 383 1 CARD8 opcode (X assigned) 384 1 17 GLX opcode (glXVendorPrivateWithReply) 385 2 4 request length 386 4 1278 vendor specific opcode 387 4 GLX_CONTEXT_TAG context tag 388 4 INT32 n 389 => 390 1 1 reply 391 1 unused 392 2 CARD16 sequence number 393 4 0 reply length 394 4 BOOL32 return value 395 20 unused 396 397 TestFenceNV 398 1 CARD8 opcode (X assigned) 399 1 17 GLX opcode (glXVendorPrivateWithReply) 400 2 4 request length 401 4 1279 vendor specific opcode 402 4 GLX_CONTEXT_TAG context tag 403 4 INT32 fence 404 => 405 1 1 reply 406 1 unused 407 2 CARD16 sequence number 408 4 0 reply length 409 4 BOOL32 return value 410 20 unused 411 412 GetFenceivNV 413 1 CARD8 opcode (X assigned) 414 1 17 GLX opcode (glXVendorPrivateWithReply) 415 2 5 request length 416 4 1280 vendor specific opcode 417 4 GLX_CONTEXT_TAG context tag 418 4 INT32 fence 419 4 CARD32 pname 420 => 421 1 1 reply 422 1 unused 423 2 CARD16 sequence number 424 4 m reply length, m=(n==1?0:n) 425 4 unused 426 4 CARD32 n 427 428 if (n=1) this follows: 429 430 4 INT32 params 431 12 unused 432 433 otherwise this follows: 434 435 16 unused 436 n*4 LISTofINT32 params 437 438 FinishFenceNV 439 1 CARD8 opcode (X assigned) 440 1 17 GLX opcode (glXVendorPrivateWithReply) 441 2 4 request length 442 4 1312 vendor specific opcode 443 4 GLX_CONTEXT_TAG context tag 444 4 INT32 fence 445 => 446 1 1 reply 447 1 unused 448 2 CARD16 sequence number 449 4 0 reply length 450 24 unused 451 452Errors 453 454 INVALID_VALUE is generated if GenFencesNV or DeleteFencesNV parameter <n> 455 is negative. 456 457 INVALID_OPERATION is generated if the fence used in TestFenceNV, 458 FinishFenceNV or GetFenceivNV is not the name of an existing fence. 459 460 INVALID_ENUM is generated if the condition used in SetFenceNV 461 is not ALL_COMPLETED_NV. 462 463 INVALID_OPERATION is generated if any of the commands defined in 464 this extension is executed between the execution of Begin and the 465 corresponding execution of End. 466 467New State 468 469Table 6.X. Fence Objects. 470 471Get value Type Get command Initial value Description Section Attribute 472------------------ ---- ------------ ---------------------------- --------------- ------- --------- 473FENCE_STATUS_NV B GetFenceivNV determined by 1st SetFenceNV Fence status 5.X - 474FENCE_CONDITION_NV Z1 GetFenceivNV determined by 1st SetFenceNV Fence condition 5.X - 475 476New Implementation Dependent State 477 478 None 479 480Dependencies on OpenGL ES 481 482 If implemented for OpenGL ES, NV_fence acts as described in this spec, 483 except: 484 485 * Ignore all references to display lists and immediate mode, including 486 changes to section 5.4 "Display Lists". 487 * Ignore all references to GLX and GLX protocol. 488 489GeForce Implementation Details 490 491 This section describes implementation-defined limits for GeForce: 492 493 SetFenceNV calls are not free. They should be used prudently, 494 and a "good number" of commands should be sent between calls to 495 SetFenceNV. Each fence insertion will cause the GPU's command 496 processing to go momentarily idle. Testing or finishing a fence 497 may require an one or more somewhat expensive uncached reads. 498 499 Do not leave a fence untested or unfinished for an extremely large 500 interval of intervening fences. If more than approximately 2 501 billion (specifically 2^31-1) intervening fences are inserted into 502 the GL command stream before a fence is tested or finished, said 503 fence may indicate an incorrect status. Note that certain GL 504 operations involving display lists, compiled vertex arrays, and 505 textures may insert fences implicitly for internal driver use. 506 507 In practice, this limitation is unlikely to be a practical 508 limitation if fences are finished or tested within a few frames 509 of their insertion into the GL command stream. 510 511Revision History 512 513 November 13, 2000 - GLX enumerant values assigned 514 515 October 3, 2003 - Changed version to 1.1. glFinishFenceNV should 516 not be compiled into display lists but rather executed immediately 517 when called during display list construction. Version 1.0 allowed 518 this though it should not have been allowed. Changed GLX protocol 519 so that FinishFenceNV is a non-render request with a reply now. 520 Thanks to Bob Beretta for noticing this issue. 521 522 Also fix a typo in the GLX protocol specification for IsFenceNV so 523 the reply is 32 (not 33) bytes. 524 525 December 17. 2008 - Add "Dependencies on OpenGL ES" section. Clarify 526 generation of fence name vs creation of the fence itself. 527