blob: 0bf007754cc7b1921e41fc296a00be0f6065f54a [file] [log] [blame]
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