1Name 2 3 NV_sync 4 5Name Strings 6 7 EGL_NV_sync 8 9Contributors 10 11 Gary King 12 Gregory Prisament 13 Acorn Pooley 14 Jon Leech 15 16Contacts 17 18 Acorn Pooley, NVIDIA Corporation (apooley 'at' nvidia.com) 19 Gary King, NVIDIA Corporation (gking 'at' nvidia.com) 20 21Status 22 23 Complete 24 25Version 26 27 Version 7, July 27, 2010 28 29Number 30 31 EGL Extension #19 32 33Dependencies 34 35 Requires EGL 1.1 36 37 This extension is written against the wording of the EGL 1.2 38 Specification. 39 40Overview 41 42 This extension introduces the concept of "sync objects" into EGL. 43 Sync objects are a synchronization primitive, representing events 44 whose completion can be tested or waited upon. This extension 45 borrows heavily from the GL_ARB_sync extension, and like that 46 extension, introduces only a single type of sync object, the 47 "fence sync object." Additional types of sync objects may be 48 introduced in later extensions. 49 50 Fence sync objects have corresponding fences, which are inserted 51 into client API command streams. A sync object can be queried 52 for a given condition, such as completion of the corresponding 53 fence. Fence completion allows applications to request a partial 54 Finish of an API command stream, wherein all commands issued in 55 a particular client API context will be forced to complete before 56 control is returned to the calling thread. 57 58 This extension is nearly identical to NVIDIA's original proposal for the 59 EGL_KHR_sync extension, which some minor differences outlined in Issue 7 60 below. 61 62New Types 63 64 /* 65 * EGLSyncNV is an opaque handle to an EGL sync object 66 */ 67 typedef void* EGLSyncNV; 68 69 /* 70 * EGLTimeNV is a 64-bit unsigned integer representing intervals in 71 * nanoseconds (unadjusted standard time). A type defined in the 72 * standard Khronos <KHR/khrplatform.h> header is used instead of 73 * a less-portable native C type. 74 */ 75 #include <KHR/khrplatform.h> 76 typedef khronos_utime_nanoseconds_t EGLTimeNV; 77 78New Procedures and Functions 79 80 EGLSyncNV eglCreateFenceSyncNV( EGLDisplay dpy, 81 EGLenum condition, 82 const EGLint *attrib_list ); 83 84 EGLBoolean eglDestroySyncNV( EGLSyncNV sync ); 85 86 EGLBoolean eglFenceNV( EGLSyncNV sync ); 87 88 EGLint eglClientWaitSyncNV( EGLSyncNV sync, 89 EGLint flags, EGLTimeNV timeout ); 90 91 EGLBoolean eglSignalSyncNV( EGLSyncNV sync, EGLenum mode ); 92 93 EGLBoolean eglGetSyncAttribNV( EGLSyncNV sync, EGLint attribute, 94 EGLint *value ); 95 96 97New Tokens 98 99 Accepted in the <condition> parameter of eglCreateFenceSyncNV, and 100 returned in <value> when eglGetSyncAttribNV is called with <attribute> 101 EGL_SYNC_CONDITION_NV: 102 103 EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 104 105 Accepted as an attribute name in the <attrib_list> parameter of 106 eglCreateFenceSyncNV, and by the <attribute> parameter of 107 eglGetSyncAttribNV: 108 109 EGL_SYNC_STATUS_NV 0x30E7 110 111 Accepted as an attribute value in the <attrib_list> parameter of 112 eglCreateFenceSyncNV for the EGL_SYNC_STATUS_NV attribute, by 113 the <mode> parameter of eglSignalSyncNV and returned in <value> 114 when eglGetSyncAttribNV is called with <attribute> 115 EGL_SYNC_STATUS_NV: 116 117 EGL_SIGNALED_NV 0x30E8 118 EGL_UNSIGNALED_NV 0x30E9 119 120 Accepted in the <flags> parameter of eglClientWaitSyncNV: 121 122 EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001 123 124 Accepted in the <timeout> parameter of eglClientWaitSyncNV: 125 126 EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull 127 128 Returned by eglClientWaitSyncNV: 129 130 EGL_ALREADY_SIGNALED_NV 0x30EA 131 EGL_TIMEOUT_EXPIRED_NV 0x30EB 132 EGL_CONDITION_SATISFIED_NV 0x30EC 133 134 Accepted in the <attribute> parameter of eglGetSyncAttribNV: 135 136 EGL_SYNC_TYPE_NV 0x30ED 137 EGL_SYNC_CONDITION_NV 0x30EE 138 139 Returned in <value> when eglGetSyncAttribNV is called with 140 <attribute> EGL_SYNC_TYPE_NV: 141 142 EGL_SYNC_FENCE_NV 0x30EF 143 144 Returned by eglCreateFenceSyncNV in the event of an error: 145 146 EGL_NO_SYNC_NV ((EGLSyncNV)0) 147 148 149 150Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) 151 152 Add a new subsection at the end of Section 3.8, page 43 153 (Synchronization Primitives) 154 155 "3.8.1 Sync Objects 156 In addition to the aforementioned synchronization functions, which 157 provide an efficient means of serializing client and native API 158 operations within a thread, "Sync Objects" are provided to enable 159 synchronization of client API operations between threads and/or between 160 API contexts. Sync objects may be tested or waited upon by application 161 threads. 162 163 Sync objects have a status with two possible states: <signaled> and 164 <unsignaled>. Events may be associated with a sync object. When an 165 event is initially associated with a sync object, the object is 166 unsignaled (its status is set to unsignaled). Once a sync object has 167 been created, EGL may be asked to wait for a sync object to become 168 signaled. Sync objects may also be signaled or unsignaled explicitly. 169 Sync objects are associated with an EGLDisplay; this association 170 is made when the sync object is created. 171 172 Only one type of sync object is defined, the fence sync object, whose 173 associated events are triggered by fence commands which are inserted 174 into the command streams of client API contexts. Fence sync objects may 175 be used to wait for partial completion of a client API command stream, 176 as a more flexible form of glFinish / vgFinish. 177 178 The command 179 180 EGLSyncNV eglCreateFenceSyncNV( EGLDisplay dpy, 181 enum condition, 182 EGLint *attrib_list ); 183 184 creates a fence sync object for the specified display <dpy> and returns 185 a handle to the new object. The sync object is assigned a type of 186 EGL_SYNC_FENCE_NV. <condition> must be 187 EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV. <attrib_list> is an attribute-value 188 list specifying other attributes of the sync object, terminated by an 189 attribute entry EGL_NONE. Attributes not specified in the list will be 190 assigned their default values. Attributes accepted by fence sync objects 191 are listed in table 3.aa 192 193 Attribute Name Attribute Value(s) Default Value 194 --------------- ------------------------------------ -------------- 195 EGL_SYNC_STATUS_NV EGL_SIGNALED_NV, EGL_UNSIGNALED_NV EGL_SIGNALED_NV 196 197 Table 3.aa Fence Sync Object Attributes 198 199 * If <dpy> is not the name of a valid, initialized EGLDisplay, 200 EGL_NO_SYNC_NV is returned and an EGL_BAD_DISPLAY error is generated. 201 202 * If <condition> is not EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV, 203 EGL_NO_SYNC_NV is returned and an EGL_BAD_PARAMETER error is generated. 204 205 * If any attribute not appearing in table 3.?? is specified in 206 <attrib_list>, EGL_NO_SYNC_NV is returned and an EGL_BAD_ATTRIBUTE error is 207 generated. 208 209 210 The command 211 212 EGLBoolean eglFenceNV( EGLSyncNV sync ); 213 214 inserts a fence command into the command stream of the bound API's current 215 context (i.e., the context returned by eglGetCurrentContext), and 216 assoicates it with sync object <sync>. <sync> must be a sync object 217 created with eglCreateFenceSyncNV, and the display associated with <sync> 218 must match the current display (i.e., the display returned by 219 eglGetCurrentDisplay). Calling eglFenceNV unsignals <sync>. 220 221 When the condition of <sync> is satisfied by the fence command, <sync> is 222 signaled by the associated client API context, causing any 223 eglClientWaitSyncNV commands (see below) blocking on <sync> to unblock. 224 The condition EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV is satisfied by completion 225 of the fence command corresponding to the sync object, and all preceding 226 commands in the associated client API context's command stream. <sync> 227 will not be signaled until all effects from these commands on the client 228 API's internal and framebuffer state are fully realized. No other state 229 is affected by execution of the fence command. 230 231 Multiple fence commands may be inserted in any client API command stream 232 for a single sync object. The sync object is unsignaled every time a new 233 fence command is issued, and signaled every time a previous fence command 234 completes, so its status is indeterminate until all fence commands 235 associated with the sync object have completed. However, each time a fence 236 command completes (signaling the sync object), at least one 237 eglClientWaitSyncNV command blocking on that sync object will unblock. 238 239 EGL_TRUE is returned upon successful insertion of the fence command. 240 241 * If <sync> is not a valid sync object with a type of EGL_SYNC_FENCE_NV, 242 EGL_FALSE is returned and an EGL_BAD_PARAMETER error is generated. 243 244 * If the display associated with <sync> does not match the current 245 display, EGL_FALSE is returned and an EGL_BAD_MATCH error is generated. 246 247 * If no context is current for the bound API (i.e., eglGetCurrentContext 248 returns EGL_NO_CONTEXT), EGL_FALSE is returned and an EGL_BAD_MATCH error 249 is generated. 250 251 The command 252 253 EGLint eglClientWaitSyncNV( EGLSyncNV sync, uint flags, 254 EGLTimeNV timeout ); 255 256 blocks the calling thread until the specified sync object <sync> is 257 signaled, or until a specified timeout value expires. If <sync> is 258 signaled at the time eglClientWaitSyncNV is called then eglClientWaitSyncNV 259 will not block. If <sync> is unsignaled at the time eglClientWaitSyncNV is 260 called then eglClientWaitSyncNV will wait up to <timeout> nanoseconds for 261 <sync> to become signaled. 262 263 If the value of <timeout> is zero, then eglClientWaitSyncNV will never 264 block and simply tests the current status of <sync>. If the value of 265 <timeout> is the special value EGL_FOREVER_NV then eglClientWaitSyncNV 266 does not time out. 267 268 eglClientWaitSyncNV returns one of three status values describing the 269 reason for returning. A return value of EGL_ALREADY_SIGNALED_NV will 270 always be returned if <sync> was signaled when eglClientWaitSyncNV was 271 called, even if <timeout> is zero. A return value of 272 EGL_TIMEOUT_EXPIRED_NV indicates that indicates that the specified 273 timeout period expired before <sync> was signaled. A return value of 274 EGL_CONDITION_SATISFIED_NV indicates that <sync> was signaled before 275 the timeout expired. 276 277 Note that a fence sync object can be in the signaled state because one of 278 three events has occured: 279 280 1. A previously inserte fence has completed and has signaled the sync 281 object. 282 2. The sync object was created. Creation of a sync object sets it in the 283 signaled state by default, unless the attribute EGL_SYNC_STATUS_NV 284 is set to EGL_UNSIGNALED_NV in the attribute list. 285 3. The sync object was signaled by a previously issued 286 eglSignalSyncNV(sync, EGL_SIGNALED_NV) command. 287 288 If the sync object being blocked upon will not be signaled in finite time 289 (for example, by an associated fence command issued previously, but not 290 yet flushed to the graphics pipeline), then eglClientWaitSyncNV may 291 wait forever. To help prevent this behavior (footnote1), if the 292 EGL_SYNC_FLUSH_COMMANDS_BIT_NV bit is set in <flags>, and <sync> is 293 unsignaled when eglClientWaitSyncNV is called, then the equivalent of 294 Flush() will be performed for the current API context (i.e., the context 295 returned by eglGetCurrentContext()) before blocking on <sync>. If no 296 context is current for the bound API, the EGL_SYNC_FLUSH_COMMANDS_BIT_NV 297 bit is ignored. 298 299 (footnote 1): The simple Flush behavior defined by 300 EGL_SYNC_FLUSH_COMMANDS_BIT_NV will not help when waiting for a fence 301 command issued in a different context's command stream. Applications 302 which block on a fence sync object must take additional steps to ensure 303 that the context from which the associated fence command was issued 304 has flushed that command to the graphics pipeline. 305 306 If a sync object is deleted when an eglClientWaitSyncNV is blocking on 307 that object, the behavior of eglClientWaitSyncNV is undefined. Some 308 possible behaviors are to return immediately, to wait for fence commands 309 associated with the deleted sync to complete, or to not return until the 310 timeout period expires. 311 312 * If <sync> is not a valid sync object, EGL_FALSE is returned and an 313 EGL_BAD_PARAMETER error is generated. 314 315 316 The command 317 318 EGLBoolean eglSignalSyncNV( EGLSyncNV sync, enum mode ); 319 320 signals or unsignals the sync object <sync> by changing its status to 321 <mode>, which must be one of the values in table 3.bb. If, as a 322 result of calling eglSignalSyncNV, the status of <sync> transitions 323 from unsignaled to signaled, then at least one eglClientWaitSyncNV 324 commands blocking on <sync> will unblock. 325 326 Assuming no errors are generated, EGL_TRUE is returned. 327 328 Mode Effect 329 ------------------ ------------- 330 EGL_SIGNALED_NV Set the status of <sync> to signaled 331 EGL_UNSIGNALED_NV Set the status of <sync> to unsignaled 332 333 Table 3.bb Modes Accepted by eglSignalSyncNV Command 334 335 * If <sync> is not a valid sync object, EGL_FALSE is returned and an 336 EGL_BAD_PARAMETER error is generated. 337 338 339 The command 340 341 EGLBoolean eglGetSyncAttribNV( EGLSyncNV sync, EGLint attribute, 342 EGLint *value ); 343 344 is used to query attributes of the sync object <sync>. Legal values for 345 <attribute> depend on the type of sync object; these are listed in table 3.cc. 346 Assuming no errors are generated, EGL_TRUE is returned and the value of 347 the queried attribute is returned in <value>. 348 349 Attribute Description Supported Sync Objects 350 ----------------- ----------------------- --------------------- 351 EGL_SYNC_TYPE_NV Type of the sync object All 352 EGL_SYNC_STATUS_NV Status of the sync object All 353 EGL_SYNC_CONDITION_NV Signaling condition EGL_SYNC_FENCE_NV 354 355 * If <sync> is not a valid sync object, EGL_FALSE is returned and an 356 EGL_BAD_PARAMETER error is generated. 357 358 The command 359 360 EGLBoolean eglDestroySyncNV( EGLSyncNV sync ); 361 362 is used to destroy an existing sync object. If any eglClientWaitSyncNV 363 commands are blocking on <sync> when eglDestroySyncNV is called, their 364 behavior is undefined. After calling eglDestroySyncNV, <sync> is no 365 longer a valid sync object. Assuming no errors are generated, EGL_TRUE 366 is returned. 367 368 * If <sync> is not a valid sync object, EGL_FALSE is returned and an 369 EGL_BAD_PARAMETER error is generated. 370 371Issues 372 373 1. Explain the key choices made in this extension. 374 375 RESPONSE: This extension has been written to enable adoption to be as wide 376 as possible, and to behave as similarly as possible to synchronization 377 primitives available in desktop OpenGL (e.g., NV_fence, ARB_sync). 378 379 In the interest of enabling widespread adoption, this extension (following 380 the ARB_sync model) has foregone the inclusion of synchronization primitives 381 and synchronization tests which may be performed entirely inside client 382 API command streams, instead performing synchronization tests 383 (eglClientWaitSyncNV) inside the application & host CPU. 384 385 In the interest of maintaining similarity with previous synchronization 386 primitives, this extension attempts to copy the ARB_sync specification 387 wherever possible (both functionally and stylistically), only making 388 changes where needed to operate inside EGL (rather than a client API 389 context) and match EGL naming conventions. 390 391 2. Why place this behavior in EGL, rather than in the client APIs? 392 393 RESPONSE: Ultimately, synchronization between multiple asynchronous client 394 API contexts (potentially executing in different threads) is a problem 395 which affects or will affect all EGL client APIs. Rather than creating 396 separate synchronization primitives in each of the client APIs (and then 397 wrapping them in an EGL container), in the interest of developer simplicity 398 & consistency this behavior is being placed inside EGL. 399 400 3. What does this extension provide that can not be accomplished with the 401 existing, more efficient eglWaitClient and eglWaitNative API functions? 402 403 RESPONSE: eglWaitClient and eglWaitNative may be implemented in extremely 404 lightweight manners, in some cases not blocking the calling thread at 405 all; however, they can not be used to synchronize between client API 406 contexts and native APIs executing in separate threads (or simply between 407 client API contexts executing in separate threads), such as between a 408 thread with an active OpenGL context and a second thread performing 409 video decode. 410 411 4. What does this extension provide that could not be accomplished with 412 native platform synchronization primitives and the existing client API 413 Finish commands? 414 415 RESPONSE: This extension provides a lighter-weight mechanism for 416 synchronizing an application with client API command streams than the 417 all-or-nothing Finish commands, enabling applications to block until 418 a subset of issued client API commands have completed. 419 420 5. Should integration with native platform synchronization objects be 421 included in this extension, or reserved for future (platform-specific) 422 extensions? 423 424 RESOLVED: Integration with native platform synchronization objects should 425 not be part of this extension, but can be added as future layered 426 extensions if needed. These layered extensions can be platform-specific, 427 or perhaps OpenKODE based. 428 429 Originally, this extension included the ability to create native platform 430 synchronization objects from EGLSync objects. This feature was removed 431 for a few reasons: 432 433 i) The proposed mechanism suggested mapping EGLSync objects to pthread 434 conditional variables on platforms with pthread support. However, 435 pthread conditional variables require an associated mutex and there 436 was no mechanism to relay this associated mutex to the application. 437 438 ii) On certain platforms support for converting to native platform 439 synchronization objects adds great complexity to the implementation. 440 441 iii) Now that OpenKODE is more mature, it would be better to allow 442 conversion from EGLSyncNV objects to OpenKODE synchronization 443 primitives rather than platform-specific ones. We suggest that this 444 functionality, if needed, be added as a layered extension instead of 445 being included here. This way, EGL_NV_sync remains minimal and easy 446 to implement on a variety of platforms. 447 448 6. Please provide a more detailed description of how ClientWaitSyncNV 449 behaves. 450 451 RESPONSE: Issue 18 in the ARB_sync specification includes a very 452 detailed description of ClientWaitSyncARB (the ARB_sync equivalent of 453 ClientWaitSyncNV). This is provided (unmodified) below: 454 455 Does ClientWaitSyncARB wait on an event, or on sync object 456 status? What is the meaning of sync object status? 457 458 RESOLVED: ClientWaitSyncARB blocks until the status of the sync 459 object transitions to the signaled state. Sync object status is 460 either signaled or unsignaled. More detailed rules describing 461 signalling follow (these need to be imbedded into the actual 462 spec language): 463 464 R1) A sync object has two possible status values: signaled or 465 unsignaled (corresponding to SYNC_STATUS_ARB values of 466 SIGNALED_ARB or UNSIGNALED_ARB, respectively). 467 468 R2) When created, the state of the sync object is signaled by 469 default, but may be explicitly set to unsignaled. 470 471 R3) A fence command is inserted into a command stream. A sync 472 object is not. 473 474 R4) When a fence command is inserted into a command stream using 475 FenceARB(), the status of the sync object associated with 476 that fence command is set to the unsignaled state. 477 478 R5) Multiple fence commands can be associated with the same sync 479 object. 480 481 R6) A fence command, once its condition has been met, will set 482 its associated sync object to the signaled state. The only 483 condition currently supported is 484 SYNC_PRIOR_COMMANDS_COMPLETE_ARB. 485 486 R7) A wait function, such as ClientWaitSyncARB, waits on a sync 487 object, not on a fence. 488 489 R8) A wait function, such as ClientWaitSyncARB, called on a sync 490 object in the unsignaled state will block. It unblocks 491 (note, not "returns to the application") when the sync 492 object transitions to the signaled state. 493 494 Some of the behaviors resulting from these rules are: 495 496 B1) Calling ClientWaitSyncARB with a timeout of 0 will return 497 TRUE if the sync object is in the signaled state. Note that 498 calling ClientWaitSyncARB with a timeout of 0 in a loop can 499 miss state transitions. 500 B2) Stacking fences is allowed. Each fence, once its condition 501 has been met, will set its associated sync object to the 502 signaled state. If the sync object is already in the 503 signaled state, it stays in that state. 504 B3) ClientWaitSyncARB could take a timeout parameter and return 505 a boolean. If the timeout period has expired, 506 ClientWaitSyncARB will unblock and return FALSE to the 507 caller. If ClientWaitSyncARB unblocks because the sync 508 object it was waiting on is in the signaled state, it will 509 return TRUE. 510 B4) We could define a FinishMultipleSync() command that will 511 unblock once all (or any) of the sync objects passed to it 512 are in the signaled state (also see issue 12). 513 B5) We could define a set/resetSyncObject function to manually 514 set the sync object in the signaled or unsignaled state. 515 This makes it easy for apps to reuse a sync object in the 516 multi-context case, so the sync object can be blocked upon 517 before a fence command is associated with it in the command 518 stream. 519 B6) We could define an API to convert a sync object into an OS 520 specific synchronization primitive (Events on Windows, file 521 descriptors or X-events or semaphores on Unix?) 522 523 7) How does this extension differ from (relate to) EGL_KHR_sync: 524 525 RESPONSE: 526 As of the time of writing this, the EGL_KHR_sync specification has not 527 been finalized by Khronos and continues to undergo revision. However, 528 NVIDIA has the functionality outlined in this specification implemented 529 and has decided to make it available to developers immediately. 530 531 For the most part, EGL_KHR_sync is identical to revision 5 of EGL_KHR_sync 532 with the following changes: 533 534 a) Enum values are different 535 b) EGLTimeNV is unsigned long long instead of uint64_t. 536 c) Behaviour when there are multiple waiting threads is undefined. 537 538Revision History 539 540#7 (Jon Leech, July 27, 2010) 541 - Redefine EGLTimeNV type to use a typedef from the standard 542 Khronos headers instead of a native C type, for portability. 543#6 (Greg Prisament, May 28, 2009) 544 - Branch spec & turn it into an _NV extension. 545#5 (Greg Prisament, July 22, 2008) 546 - Removed NativeSyncKHR, CreateNativeSyncKHR, and corresponding wording. 547 - Correct EGLuint to EGLint (EGLuint doesn't exist). 548#4 (Jon Leech, November 20, 2007) 549 - Corrected 'enum' to 'EGLenum' in prototypes. 550#3 (Jon Leech, April 5, 2007) 551 - Added draft Status and TBD Number 552#2 (November 27, 2006) 553 - Changed OES token to KHR 554 555