| Name |
| |
| NV_sync |
| |
| Name Strings |
| |
| EGL_NV_sync |
| |
| Contributors |
| |
| Gary King |
| Gregory Prisament |
| Acorn Pooley |
| Jon Leech |
| |
| Contacts |
| |
| Acorn Pooley, NVIDIA Corporation (apooley 'at' nvidia.com) |
| Gary King, NVIDIA Corporation (gking 'at' nvidia.com) |
| |
| Status |
| |
| Complete |
| |
| Version |
| |
| Version 7, July 27, 2010 |
| |
| Number |
| |
| EGL Extension #19 |
| |
| Dependencies |
| |
| Requires EGL 1.1 |
| |
| This extension is written against the wording of the EGL 1.2 |
| Specification. |
| |
| Overview |
| |
| This extension introduces the concept of "sync objects" into EGL. |
| Sync objects are a synchronization primitive, representing events |
| whose completion can be tested or waited upon. This extension |
| borrows heavily from the GL_ARB_sync extension, and like that |
| extension, introduces only a single type of sync object, the |
| "fence sync object." Additional types of sync objects may be |
| introduced in later extensions. |
| |
| Fence sync objects have corresponding fences, which are inserted |
| into client API command streams. A sync object can be queried |
| for a given condition, such as completion of the corresponding |
| fence. Fence completion allows applications to request a partial |
| Finish of an API command stream, wherein all commands issued in |
| a particular client API context will be forced to complete before |
| control is returned to the calling thread. |
| |
| This extension is nearly identical to NVIDIA's original proposal for the |
| EGL_KHR_sync extension, which some minor differences outlined in Issue 7 |
| below. |
| |
| New Types |
| |
| /* |
| * EGLSyncNV is an opaque handle to an EGL sync object |
| */ |
| typedef void* EGLSyncNV; |
| |
| /* |
| * EGLTimeNV is a 64-bit unsigned integer representing intervals in |
| * nanoseconds (unadjusted standard time). A type defined in the |
| * standard Khronos <KHR/khrplatform.h> header is used instead of |
| * a less-portable native C type. |
| */ |
| #include <KHR/khrplatform.h> |
| typedef khronos_utime_nanoseconds_t EGLTimeNV; |
| |
| New Procedures and Functions |
| |
| EGLSyncNV eglCreateFenceSyncNV( EGLDisplay dpy, |
| EGLenum condition, |
| const EGLint *attrib_list ); |
| |
| EGLBoolean eglDestroySyncNV( EGLSyncNV sync ); |
| |
| EGLBoolean eglFenceNV( EGLSyncNV sync ); |
| |
| EGLint eglClientWaitSyncNV( EGLSyncNV sync, |
| EGLint flags, EGLTimeNV timeout ); |
| |
| EGLBoolean eglSignalSyncNV( EGLSyncNV sync, EGLenum mode ); |
| |
| EGLBoolean eglGetSyncAttribNV( EGLSyncNV sync, EGLint attribute, |
| EGLint *value ); |
| |
| |
| New Tokens |
| |
| Accepted in the <condition> parameter of eglCreateFenceSyncNV, and |
| returned in <value> when eglGetSyncAttribNV is called with <attribute> |
| EGL_SYNC_CONDITION_NV: |
| |
| EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 |
| |
| Accepted as an attribute name in the <attrib_list> parameter of |
| eglCreateFenceSyncNV, and by the <attribute> parameter of |
| eglGetSyncAttribNV: |
| |
| EGL_SYNC_STATUS_NV 0x30E7 |
| |
| Accepted as an attribute value in the <attrib_list> parameter of |
| eglCreateFenceSyncNV for the EGL_SYNC_STATUS_NV attribute, by |
| the <mode> parameter of eglSignalSyncNV and returned in <value> |
| when eglGetSyncAttribNV is called with <attribute> |
| EGL_SYNC_STATUS_NV: |
| |
| EGL_SIGNALED_NV 0x30E8 |
| EGL_UNSIGNALED_NV 0x30E9 |
| |
| Accepted in the <flags> parameter of eglClientWaitSyncNV: |
| |
| EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001 |
| |
| Accepted in the <timeout> parameter of eglClientWaitSyncNV: |
| |
| EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull |
| |
| Returned by eglClientWaitSyncNV: |
| |
| EGL_ALREADY_SIGNALED_NV 0x30EA |
| EGL_TIMEOUT_EXPIRED_NV 0x30EB |
| EGL_CONDITION_SATISFIED_NV 0x30EC |
| |
| Accepted in the <attribute> parameter of eglGetSyncAttribNV: |
| |
| EGL_SYNC_TYPE_NV 0x30ED |
| EGL_SYNC_CONDITION_NV 0x30EE |
| |
| Returned in <value> when eglGetSyncAttribNV is called with |
| <attribute> EGL_SYNC_TYPE_NV: |
| |
| EGL_SYNC_FENCE_NV 0x30EF |
| |
| Returned by eglCreateFenceSyncNV in the event of an error: |
| |
| EGL_NO_SYNC_NV ((EGLSyncNV)0) |
| |
| |
| |
| Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) |
| |
| Add a new subsection at the end of Section 3.8, page 43 |
| (Synchronization Primitives) |
| |
| "3.8.1 Sync Objects |
| In addition to the aforementioned synchronization functions, which |
| provide an efficient means of serializing client and native API |
| operations within a thread, "Sync Objects" are provided to enable |
| synchronization of client API operations between threads and/or between |
| API contexts. Sync objects may be tested or waited upon by application |
| threads. |
| |
| Sync objects have a status with two possible states: <signaled> and |
| <unsignaled>. Events may be associated with a sync object. When an |
| event is initially associated with a sync object, the object is |
| unsignaled (its status is set to unsignaled). Once a sync object has |
| been created, EGL may be asked to wait for a sync object to become |
| signaled. Sync objects may also be signaled or unsignaled explicitly. |
| Sync objects are associated with an EGLDisplay; this association |
| is made when the sync object is created. |
| |
| Only one type of sync object is defined, the fence sync object, whose |
| associated events are triggered by fence commands which are inserted |
| into the command streams of client API contexts. Fence sync objects may |
| be used to wait for partial completion of a client API command stream, |
| as a more flexible form of glFinish / vgFinish. |
| |
| The command |
| |
| EGLSyncNV eglCreateFenceSyncNV( EGLDisplay dpy, |
| enum condition, |
| EGLint *attrib_list ); |
| |
| creates a fence sync object for the specified display <dpy> and returns |
| a handle to the new object. The sync object is assigned a type of |
| EGL_SYNC_FENCE_NV. <condition> must be |
| EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV. <attrib_list> is an attribute-value |
| list specifying other attributes of the sync object, terminated by an |
| attribute entry EGL_NONE. Attributes not specified in the list will be |
| assigned their default values. Attributes accepted by fence sync objects |
| are listed in table 3.aa |
| |
| Attribute Name Attribute Value(s) Default Value |
| --------------- ------------------------------------ -------------- |
| EGL_SYNC_STATUS_NV EGL_SIGNALED_NV, EGL_UNSIGNALED_NV EGL_SIGNALED_NV |
| |
| Table 3.aa Fence Sync Object Attributes |
| |
| * If <dpy> is not the name of a valid, initialized EGLDisplay, |
| EGL_NO_SYNC_NV is returned and an EGL_BAD_DISPLAY error is generated. |
| |
| * If <condition> is not EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV, |
| EGL_NO_SYNC_NV is returned and an EGL_BAD_PARAMETER error is generated. |
| |
| * If any attribute not appearing in table 3.?? is specified in |
| <attrib_list>, EGL_NO_SYNC_NV is returned and an EGL_BAD_ATTRIBUTE error is |
| generated. |
| |
| |
| The command |
| |
| EGLBoolean eglFenceNV( EGLSyncNV sync ); |
| |
| inserts a fence command into the command stream of the bound API's current |
| context (i.e., the context returned by eglGetCurrentContext), and |
| assoicates it with sync object <sync>. <sync> must be a sync object |
| created with eglCreateFenceSyncNV, and the display associated with <sync> |
| must match the current display (i.e., the display returned by |
| eglGetCurrentDisplay). Calling eglFenceNV unsignals <sync>. |
| |
| When the condition of <sync> is satisfied by the fence command, <sync> is |
| signaled by the associated client API context, causing any |
| eglClientWaitSyncNV commands (see below) blocking on <sync> to unblock. |
| The condition EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV is satisfied by completion |
| of the fence command corresponding to the sync object, and all preceding |
| commands in the associated client API context's command stream. <sync> |
| will not be signaled until all effects from these commands on the client |
| API's internal and framebuffer state are fully realized. No other state |
| is affected by execution of the fence command. |
| |
| Multiple fence commands may be inserted in any client API command stream |
| for a single sync object. The sync object is unsignaled every time a new |
| fence command is issued, and signaled every time a previous fence command |
| completes, so its status is indeterminate until all fence commands |
| associated with the sync object have completed. However, each time a fence |
| command completes (signaling the sync object), at least one |
| eglClientWaitSyncNV command blocking on that sync object will unblock. |
| |
| EGL_TRUE is returned upon successful insertion of the fence command. |
| |
| * If <sync> is not a valid sync object with a type of EGL_SYNC_FENCE_NV, |
| EGL_FALSE is returned and an EGL_BAD_PARAMETER error is generated. |
| |
| * If the display associated with <sync> does not match the current |
| display, EGL_FALSE is returned and an EGL_BAD_MATCH error is generated. |
| |
| * If no context is current for the bound API (i.e., eglGetCurrentContext |
| returns EGL_NO_CONTEXT), EGL_FALSE is returned and an EGL_BAD_MATCH error |
| is generated. |
| |
| The command |
| |
| EGLint eglClientWaitSyncNV( EGLSyncNV sync, uint flags, |
| EGLTimeNV timeout ); |
| |
| blocks the calling thread until the specified sync object <sync> is |
| signaled, or until a specified timeout value expires. If <sync> is |
| signaled at the time eglClientWaitSyncNV is called then eglClientWaitSyncNV |
| will not block. If <sync> is unsignaled at the time eglClientWaitSyncNV is |
| called then eglClientWaitSyncNV will wait up to <timeout> nanoseconds for |
| <sync> to become signaled. |
| |
| If the value of <timeout> is zero, then eglClientWaitSyncNV will never |
| block and simply tests the current status of <sync>. If the value of |
| <timeout> is the special value EGL_FOREVER_NV then eglClientWaitSyncNV |
| does not time out. |
| |
| eglClientWaitSyncNV returns one of three status values describing the |
| reason for returning. A return value of EGL_ALREADY_SIGNALED_NV will |
| always be returned if <sync> was signaled when eglClientWaitSyncNV was |
| called, even if <timeout> is zero. A return value of |
| EGL_TIMEOUT_EXPIRED_NV indicates that indicates that the specified |
| timeout period expired before <sync> was signaled. A return value of |
| EGL_CONDITION_SATISFIED_NV indicates that <sync> was signaled before |
| the timeout expired. |
| |
| Note that a fence sync object can be in the signaled state because one of |
| three events has occured: |
| |
| 1. A previously inserte fence has completed and has signaled the sync |
| object. |
| 2. The sync object was created. Creation of a sync object sets it in the |
| signaled state by default, unless the attribute EGL_SYNC_STATUS_NV |
| is set to EGL_UNSIGNALED_NV in the attribute list. |
| 3. The sync object was signaled by a previously issued |
| eglSignalSyncNV(sync, EGL_SIGNALED_NV) command. |
| |
| If the sync object being blocked upon will not be signaled in finite time |
| (for example, by an associated fence command issued previously, but not |
| yet flushed to the graphics pipeline), then eglClientWaitSyncNV may |
| wait forever. To help prevent this behavior (footnote1), if the |
| EGL_SYNC_FLUSH_COMMANDS_BIT_NV bit is set in <flags>, and <sync> is |
| unsignaled when eglClientWaitSyncNV is called, then the equivalent of |
| Flush() will be performed for the current API context (i.e., the context |
| returned by eglGetCurrentContext()) before blocking on <sync>. If no |
| context is current for the bound API, the EGL_SYNC_FLUSH_COMMANDS_BIT_NV |
| bit is ignored. |
| |
| (footnote 1): The simple Flush behavior defined by |
| EGL_SYNC_FLUSH_COMMANDS_BIT_NV will not help when waiting for a fence |
| command issued in a different context's command stream. Applications |
| which block on a fence sync object must take additional steps to ensure |
| that the context from which the associated fence command was issued |
| has flushed that command to the graphics pipeline. |
| |
| If a sync object is deleted when an eglClientWaitSyncNV is blocking on |
| that object, the behavior of eglClientWaitSyncNV is undefined. Some |
| possible behaviors are to return immediately, to wait for fence commands |
| associated with the deleted sync to complete, or to not return until the |
| timeout period expires. |
| |
| * If <sync> is not a valid sync object, EGL_FALSE is returned and an |
| EGL_BAD_PARAMETER error is generated. |
| |
| |
| The command |
| |
| EGLBoolean eglSignalSyncNV( EGLSyncNV sync, enum mode ); |
| |
| signals or unsignals the sync object <sync> by changing its status to |
| <mode>, which must be one of the values in table 3.bb. If, as a |
| result of calling eglSignalSyncNV, the status of <sync> transitions |
| from unsignaled to signaled, then at least one eglClientWaitSyncNV |
| commands blocking on <sync> will unblock. |
| |
| Assuming no errors are generated, EGL_TRUE is returned. |
| |
| Mode Effect |
| ------------------ ------------- |
| EGL_SIGNALED_NV Set the status of <sync> to signaled |
| EGL_UNSIGNALED_NV Set the status of <sync> to unsignaled |
| |
| Table 3.bb Modes Accepted by eglSignalSyncNV Command |
| |
| * If <sync> is not a valid sync object, EGL_FALSE is returned and an |
| EGL_BAD_PARAMETER error is generated. |
| |
| |
| The command |
| |
| EGLBoolean eglGetSyncAttribNV( EGLSyncNV sync, EGLint attribute, |
| EGLint *value ); |
| |
| is used to query attributes of the sync object <sync>. Legal values for |
| <attribute> depend on the type of sync object; these are listed in table 3.cc. |
| Assuming no errors are generated, EGL_TRUE is returned and the value of |
| the queried attribute is returned in <value>. |
| |
| Attribute Description Supported Sync Objects |
| ----------------- ----------------------- --------------------- |
| EGL_SYNC_TYPE_NV Type of the sync object All |
| EGL_SYNC_STATUS_NV Status of the sync object All |
| EGL_SYNC_CONDITION_NV Signaling condition EGL_SYNC_FENCE_NV |
| |
| * If <sync> is not a valid sync object, EGL_FALSE is returned and an |
| EGL_BAD_PARAMETER error is generated. |
| |
| The command |
| |
| EGLBoolean eglDestroySyncNV( EGLSyncNV sync ); |
| |
| is used to destroy an existing sync object. If any eglClientWaitSyncNV |
| commands are blocking on <sync> when eglDestroySyncNV is called, their |
| behavior is undefined. After calling eglDestroySyncNV, <sync> is no |
| longer a valid sync object. Assuming no errors are generated, EGL_TRUE |
| is returned. |
| |
| * If <sync> is not a valid sync object, EGL_FALSE is returned and an |
| EGL_BAD_PARAMETER error is generated. |
| |
| Issues |
| |
| 1. Explain the key choices made in this extension. |
| |
| RESPONSE: This extension has been written to enable adoption to be as wide |
| as possible, and to behave as similarly as possible to synchronization |
| primitives available in desktop OpenGL (e.g., NV_fence, ARB_sync). |
| |
| In the interest of enabling widespread adoption, this extension (following |
| the ARB_sync model) has foregone the inclusion of synchronization primitives |
| and synchronization tests which may be performed entirely inside client |
| API command streams, instead performing synchronization tests |
| (eglClientWaitSyncNV) inside the application & host CPU. |
| |
| In the interest of maintaining similarity with previous synchronization |
| primitives, this extension attempts to copy the ARB_sync specification |
| wherever possible (both functionally and stylistically), only making |
| changes where needed to operate inside EGL (rather than a client API |
| context) and match EGL naming conventions. |
| |
| 2. Why place this behavior in EGL, rather than in the client APIs? |
| |
| RESPONSE: Ultimately, synchronization between multiple asynchronous client |
| API contexts (potentially executing in different threads) is a problem |
| which affects or will affect all EGL client APIs. Rather than creating |
| separate synchronization primitives in each of the client APIs (and then |
| wrapping them in an EGL container), in the interest of developer simplicity |
| & consistency this behavior is being placed inside EGL. |
| |
| 3. What does this extension provide that can not be accomplished with the |
| existing, more efficient eglWaitClient and eglWaitNative API functions? |
| |
| RESPONSE: eglWaitClient and eglWaitNative may be implemented in extremely |
| lightweight manners, in some cases not blocking the calling thread at |
| all; however, they can not be used to synchronize between client API |
| contexts and native APIs executing in separate threads (or simply between |
| client API contexts executing in separate threads), such as between a |
| thread with an active OpenGL context and a second thread performing |
| video decode. |
| |
| 4. What does this extension provide that could not be accomplished with |
| native platform synchronization primitives and the existing client API |
| Finish commands? |
| |
| RESPONSE: This extension provides a lighter-weight mechanism for |
| synchronizing an application with client API command streams than the |
| all-or-nothing Finish commands, enabling applications to block until |
| a subset of issued client API commands have completed. |
| |
| 5. Should integration with native platform synchronization objects be |
| included in this extension, or reserved for future (platform-specific) |
| extensions? |
| |
| RESOLVED: Integration with native platform synchronization objects should |
| not be part of this extension, but can be added as future layered |
| extensions if needed. These layered extensions can be platform-specific, |
| or perhaps OpenKODE based. |
| |
| Originally, this extension included the ability to create native platform |
| synchronization objects from EGLSync objects. This feature was removed |
| for a few reasons: |
| |
| i) The proposed mechanism suggested mapping EGLSync objects to pthread |
| conditional variables on platforms with pthread support. However, |
| pthread conditional variables require an associated mutex and there |
| was no mechanism to relay this associated mutex to the application. |
| |
| ii) On certain platforms support for converting to native platform |
| synchronization objects adds great complexity to the implementation. |
| |
| iii) Now that OpenKODE is more mature, it would be better to allow |
| conversion from EGLSyncNV objects to OpenKODE synchronization |
| primitives rather than platform-specific ones. We suggest that this |
| functionality, if needed, be added as a layered extension instead of |
| being included here. This way, EGL_NV_sync remains minimal and easy |
| to implement on a variety of platforms. |
| |
| 6. Please provide a more detailed description of how ClientWaitSyncNV |
| behaves. |
| |
| RESPONSE: Issue 18 in the ARB_sync specification includes a very |
| detailed description of ClientWaitSyncARB (the ARB_sync equivalent of |
| ClientWaitSyncNV). This is provided (unmodified) below: |
| |
| Does ClientWaitSyncARB wait on an event, or on sync object |
| status? What is the meaning of sync object status? |
| |
| RESOLVED: ClientWaitSyncARB blocks until the status of the sync |
| object transitions to the signaled state. Sync object status is |
| either signaled or unsignaled. More detailed rules describing |
| signalling follow (these need to be imbedded into the actual |
| spec language): |
| |
| R1) A sync object has two possible status values: signaled or |
| unsignaled (corresponding to SYNC_STATUS_ARB values of |
| SIGNALED_ARB or UNSIGNALED_ARB, respectively). |
| |
| R2) When created, the state of the sync object is signaled by |
| default, but may be explicitly set to unsignaled. |
| |
| R3) A fence command is inserted into a command stream. A sync |
| object is not. |
| |
| R4) When a fence command is inserted into a command stream using |
| FenceARB(), the status of the sync object associated with |
| that fence command is set to the unsignaled state. |
| |
| R5) Multiple fence commands can be associated with the same sync |
| object. |
| |
| R6) A fence command, once its condition has been met, will set |
| its associated sync object to the signaled state. The only |
| condition currently supported is |
| SYNC_PRIOR_COMMANDS_COMPLETE_ARB. |
| |
| R7) A wait function, such as ClientWaitSyncARB, waits on a sync |
| object, not on a fence. |
| |
| R8) A wait function, such as ClientWaitSyncARB, called on a sync |
| object in the unsignaled state will block. It unblocks |
| (note, not "returns to the application") when the sync |
| object transitions to the signaled state. |
| |
| Some of the behaviors resulting from these rules are: |
| |
| B1) Calling ClientWaitSyncARB with a timeout of 0 will return |
| TRUE if the sync object is in the signaled state. Note that |
| calling ClientWaitSyncARB with a timeout of 0 in a loop can |
| miss state transitions. |
| B2) Stacking fences is allowed. Each fence, once its condition |
| has been met, will set its associated sync object to the |
| signaled state. If the sync object is already in the |
| signaled state, it stays in that state. |
| B3) ClientWaitSyncARB could take a timeout parameter and return |
| a boolean. If the timeout period has expired, |
| ClientWaitSyncARB will unblock and return FALSE to the |
| caller. If ClientWaitSyncARB unblocks because the sync |
| object it was waiting on is in the signaled state, it will |
| return TRUE. |
| B4) We could define a FinishMultipleSync() command that will |
| unblock once all (or any) of the sync objects passed to it |
| are in the signaled state (also see issue 12). |
| B5) We could define a set/resetSyncObject function to manually |
| set the sync object in the signaled or unsignaled state. |
| This makes it easy for apps to reuse a sync object in the |
| multi-context case, so the sync object can be blocked upon |
| before a fence command is associated with it in the command |
| stream. |
| B6) We could define an API to convert a sync object into an OS |
| specific synchronization primitive (Events on Windows, file |
| descriptors or X-events or semaphores on Unix?) |
| |
| 7) How does this extension differ from (relate to) EGL_KHR_sync: |
| |
| RESPONSE: |
| As of the time of writing this, the EGL_KHR_sync specification has not |
| been finalized by Khronos and continues to undergo revision. However, |
| NVIDIA has the functionality outlined in this specification implemented |
| and has decided to make it available to developers immediately. |
| |
| For the most part, EGL_KHR_sync is identical to revision 5 of EGL_KHR_sync |
| with the following changes: |
| |
| a) Enum values are different |
| b) EGLTimeNV is unsigned long long instead of uint64_t. |
| c) Behaviour when there are multiple waiting threads is undefined. |
| |
| Revision History |
| |
| #7 (Jon Leech, July 27, 2010) |
| - Redefine EGLTimeNV type to use a typedef from the standard |
| Khronos headers instead of a native C type, for portability. |
| #6 (Greg Prisament, May 28, 2009) |
| - Branch spec & turn it into an _NV extension. |
| #5 (Greg Prisament, July 22, 2008) |
| - Removed NativeSyncKHR, CreateNativeSyncKHR, and corresponding wording. |
| - Correct EGLuint to EGLint (EGLuint doesn't exist). |
| #4 (Jon Leech, November 20, 2007) |
| - Corrected 'enum' to 'EGLenum' in prototypes. |
| #3 (Jon Leech, April 5, 2007) |
| - Added draft Status and TBD Number |
| #2 (November 27, 2006) |
| - Changed OES token to KHR |
| |