• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    APPLE_sync
4
5Name Strings
6
7    GL_APPLE_sync
8
9Contributors
10
11    Contributors to ARB_sync desktop OpenGL extension from which this
12    extension borrows heavily
13
14Contact
15
16    Benj Lipchak (lipchak 'at' apple 'dot' com)
17
18Status
19
20    Complete
21
22Version
23
24    Last Modified Date: July 10, 2012
25    Author Revision: 3
26
27Number
28
29    OpenGL ES Extension #124
30
31Dependencies
32
33    OpenGL ES 1.1 or OpenGL ES 2.0 is required.
34
35    This specification is written against the OpenGL ES 2.0.25 specification.
36
37    EXT_debug_label affects the definition of this extension.
38
39Overview
40
41    This extension introduces the concept of "sync objects". Sync
42    objects are a synchronization primitive - a representation of events
43    whose completion status can be tested or waited upon. One specific
44    type of sync object, the "fence sync object", is supported in this
45    extension, and additional types can easily be added in the future.
46
47    Fence sync objects have corresponding fences, which are inserted
48    into the OpenGL command stream at the time the sync object is
49    created. A sync object can be queried for a given condition. The
50    only condition supported for fence sync objects is completion of the
51    corresponding fence command. Fence completion allows applications to
52    request a partial Finish, wherein all commands prior to the fence
53    will be forced to complete before control is returned to the calling
54    process.
55
56    These new mechanisms allow for synchronization between the host CPU
57    and the GPU, which may be accessing the same resources (typically
58    memory), as well as between multiple GL contexts bound to multiple
59    threads in the host CPU.
60
61New Types
62
63    (Implementer's Note: GLint64 and GLuint64 are defined as appropriate
64    for an ISO C 99 compiler. Other language bindings, or non-ISO
65    compilers, may need to use a different approach).
66
67    #include <inttypes.h>
68    typedef int64_t GLint64;
69    typedef uint64_t GLuint64;
70    typedef struct __GLsync *GLsync;
71
72New Procedures and Functions
73
74    sync FenceSyncAPPLE(enum condition, bitfield flags);
75    boolean IsSyncAPPLE(sync sync);
76    void DeleteSyncAPPLE(sync sync);
77
78    enum ClientWaitSyncAPPLE(sync sync, bitfield flags, uint64 timeout);
79    void WaitSyncAPPLE(sync sync, bitfield flags, uint64 timeout);
80
81    void GetInteger64vAPPLE(enum pname, int64 *params);
82    void GetSyncivAPPLE(sync sync, enum pname, sizei bufSize, sizei *length,
83        int *values);
84
85New Tokens
86
87    Accepted as the <pname> parameter of GetInteger64vAPPLE:
88
89        MAX_SERVER_WAIT_TIMEOUT_APPLE        0x9111
90
91    Accepted as the <pname> parameter of GetSyncivAPPLE:
92
93        OBJECT_TYPE_APPLE                    0x9112
94        SYNC_CONDITION_APPLE                 0x9113
95        SYNC_STATUS_APPLE                    0x9114
96        SYNC_FLAGS_APPLE                     0x9115
97
98    Returned in <values> for GetSynciv <pname> OBJECT_TYPE_APPLE:
99
100        SYNC_FENCE_APPLE                     0x9116
101
102    Returned in <values> for GetSyncivAPPLE <pname> SYNC_CONDITION_APPLE:
103
104        SYNC_GPU_COMMANDS_COMPLETE_APPLE     0x9117
105
106    Returned in <values> for GetSyncivAPPLE <pname> SYNC_STATUS_APPLE:
107
108        UNSIGNALED_APPLE                     0x9118
109        SIGNALED_APPLE                       0x9119
110
111    Accepted in the <flags> parameter of ClientWaitSyncAPPLE:
112
113        SYNC_FLUSH_COMMANDS_BIT_APPLE        0x00000001
114
115    Accepted in the <timeout> parameter of WaitSyncAPPLE:
116
117        TIMEOUT_IGNORED_APPLE                0xFFFFFFFFFFFFFFFFull
118
119    Returned by ClientWaitSyncAPPLE:
120
121        ALREADY_SIGNALED_APPLE               0x911A
122        TIMEOUT_EXPIRED_APPLE                0x911B
123        CONDITION_SATISFIED_APPLE            0x911C
124        WAIT_FAILED_APPLE                    0x911D
125
126    Accepted by the <type> parameter of LabelObjectEXT and
127    GetObjectLabelEXT:
128
129        SYNC_OBJECT_APPLE                    0x8A53
130
131
132Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)
133
134    Add to Table 2.2, GL data types:
135
136   "GL Type  Minimum    Description
137             Bit Width
138    -------  ---------  ----------------------------------------------
139    int64    64         Signed 2's complement binary integer
140    uint64   64         Unsigned binary integer
141    sync     <ptrbits>  Sync object handle (see section 5.2)"
142
143
144Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
145
146    Insert a new section following "Flush and Finish" (Section 5.1)
147    describing sync objects and fence operation. Renumber existing
148    section 5.2 "Hints" and all following 5.* sections.
149
150   "5.2 Sync Objects and Fences
151    ---------------------------
152
153    Sync objects act as a <synchronization primitive> - a representation
154    of events whose completion status can be tested or waited upon. Sync
155    objects may be used for synchronization with operations occuring in
156    the GL state machine or in the graphics pipeline, and for
157    synchronizing between multiple graphics contexts, among other
158    purposes.
159
160    Sync objects have a status value with two possible states:
161    <signaled> and <unsignaled>. Events are associated with a sync
162    object. When a sync object is created, its status is set to
163    unsignaled. When the associated event occurs, the sync object is
164    signaled (its status is set to signaled). The GL may be asked to
165    wait for a sync object to become signaled.
166
167    Initially, only one specific type of sync object is defined: the
168    fence sync object, whose associated event is triggered by a fence
169    command placed in the GL command stream. Fence sync objects are used
170    to wait for partial completion of the GL command stream, as a more
171    flexible form of Finish.
172
173    The command
174
175    sync FenceSyncAPPLE(enum condition, bitfield flags);
176
177    creates a new fence sync object, inserts a fence command in the GL
178    command stream and associates it with that sync object, and returns
179    a non-zero name corresponding to the sync object.
180
181    When the specified <condition> of the sync object is satisfied by
182    the fence command, the sync object is signaled by the GL, causing
183    any ClientWaitSyncAPPLE or WaitSyncAPPLE commands (see below) blocking
184    on <sync> to <unblock>. No other state is affected by FenceSyncAPPLE
185    or by execution of the associated fence command.
186
187    <condition> must be SYNC_GPU_COMMANDS_COMPLETE_APPLE. This condition
188    is satisfied by completion of the fence command corresponding to the
189    sync object and all preceding commands in the same command stream.
190    The sync object will not be signaled until all effects from these
191    commands on GL client and server state and the framebuffer are fully
192    realized. Note that completion of the fence command occurs once the
193    state of the corresponding sync object has been changed, but
194    commands waiting on that sync object may not be unblocked until
195    some time after the fence command completes.
196
197    <flags> must be 0[fn1].
198       [fn1: <flags> is a placeholder for anticipated future extensions
199    of fence sync object capabilities.]
200
201    Each sync object contains a number of <properties> which determine
202    the state of the object and the behavior of any commands associated
203    with it. Each property has a <property name> and <property value>.
204    The initial property values for a sync object created by FenceSyncAPPLE
205    are shown in table 5.props:
206
207    Property Name         Property Value
208    --------------------  ----------------
209    OBJECT_TYPE_APPLE     SYNC_FENCE_APPLE
210    SYNC_CONDITION_APPLE  <condition>
211    SYNC_STATUS_APPLE     UNSIGNALED_APPLE
212    SYNC_FLAGS_APPLE      <flags>
213    --------------------------------------
214    Table 5.props: Initial properties of a
215    sync object created with FenceSyncAPPLE.
216
217    Properties of a sync object may be queried with GetSyncivAPPLE (see
218    section 6.1.6). The SYNC_STATUS_APPLE property will be changed to
219    SIGNALED_APPLE when <condition> is satisfied.
220
221    If FenceSyncAPPLE fails to create a sync object, zero will be returned
222    and a GL error will be generated as described. An INVALID_ENUM error
223    is generated if <condition> is not SYNC_GPU_COMMANDS_COMPLETE_APPLE. If
224    <flags> is not zero, an INVALID_VALUE error is generated.
225
226    A sync object can be deleted by passing its name to the command
227
228    void DeleteSyncAPPLE(sync sync);
229
230    If the fence command corresponding to the specified sync object has
231    completed, or if no ClientWaitSyncAPPLE or WaitSyncAPPLE commands are
232    blocking on <sync>, the object is deleted immediately. Otherwise, <sync>
233    is flagged for deletion and will be deleted when it is no longer
234    associated with any fence command and is no longer blocking any
235    ClientWaitSyncAPPLE or WaitSyncAPPLE command. In either case, after
236    returning from DeleteSyncAPPLE the <sync> name is invalid and can no
237    longer be used to refer to the sync object.
238
239    DeleteSyncAPPLE will silently ignore a <sync> value of zero. An
240    INVALID_VALUE error is generated if <sync> is neither zero nor the
241    name of a sync object.
242
243
244    5.2.1 Waiting for Sync Objects
245    ------------------------------
246
247    The command
248
249    enum ClientWaitSyncAPPLE(sync sync, bitfield flags, uint64 timeout);
250
251    causes the GL to block, and will not return until the sync object
252    <sync> is signaled, or until the specified <timeout> period expires.
253    <timeout> is in units of nanoseconds. <timeout> is adjusted to the
254    closest value allowed by the implementation-dependent timeout
255    accuracy, which may be substantially longer than one nanosecond, and
256    may be longer than the requested period.
257
258    If <sync> is signaled at the time ClientWaitSyncAPPLE is called
259    then ClientWaitSyncAPPLE returns immediately. If <sync> is unsignaled
260    at the time ClientWaitSyncAPPLE is called then ClientWaitSyncAPPLE will
261    block and will wait up to <timeout> nanoseconds for <sync> to become
262    signaled. <flags> controls command flushing behavior, and may be
263    SYNC_FLUSH_COMMANDS_BIT_APPLE, as discussed in section 5.2.2.
264
265    ClientWaitSyncAPPLE returns one of four status values. A return value of
266    ALREADY_SIGNALED_APPLE indicates that <sync> was signaled at the time
267    ClientWaitSyncAPPLE was called. ALREADY_SIGNALED_APPLE will always be
268    returned if <sync> was signaled, even if the value of <timeout> is zero.
269    A return value of TIMEOUT_EXPIRED_APPLE indicates that the specified
270    timeout period expired before <sync> was signaled. A return value of
271    CONDITION_SATISFIED_APPLE indicates that <sync> was signaled before the
272    timeout expired. Finally, if an error occurs, in addition to
273    generating a GL error as specified below, ClientWaitSyncAPPLE immediately
274    returns WAIT_FAILED_APPLE without blocking.
275
276    If the value of <timeout> is zero, then ClientWaitSyncAPPLE does not
277    block, but simply tests the current state of <sync>.
278    TIMEOUT_EXPIRED_APPLE will be returned in this case if <sync> is not
279    signaled, even though no actual wait was performed.
280
281    If <sync> is not the name of a sync object, an INVALID_VALUE error
282    is generated. If <flags> contains any bits other than
283    SYNC_FLUSH_COMMANDS_BIT_APPLE, an INVALID_VALUE error is generated.
284
285    The command
286
287    void WaitSyncAPPLE(sync sync, bitfield flags, uint64 timeout);
288
289    is similar to ClientWaitSyncAPPLE, but instead of blocking and not
290    returning to the application until <sync> is signaled, WaitSyncAPPLE
291    returns immediately, instead causing the GL server [fn2] to block
292    until <sync> is signaled [fn3].
293       [fn2 - the GL server may choose to wait either in the CPU
294    executing server-side code, or in the GPU hardware if it
295    supports this operation.]
296       [fn3 - WaitSyncAPPLE allows applications to continue to queue commands
297    from the client in anticipation of the sync being signalled,
298    increasing client-server parallelism.]
299
300    <sync> has the same meaning as for ClientWaitSyncAPPLE.
301
302    <timeout> must currently be the special value TIMEOUT_IGNORED_APPLE, and
303    is not used. Instead, WaitSyncAPPLE will always wait no longer than an
304    implementation-dependent timeout. The duration of this timeout in
305    nanoseconds may be queried by calling GetInteger64vAPPLE with <value>
306    MAX_SERVER_WAIT_TIMEOUT_APPLE. There is currently no way to determine
307    whether WaitSyncAPPLE unblocked because the timeout expired or because
308    the sync object being waited on was signaled.
309
310    <flags> must be 0.
311
312    If an error occurs, WaitSyncAPPLE generates a GL error as specified
313    below, and does not cause the GL server to block.
314
315    If <sync> is not the name of a sync object, an INVALID_VALUE error
316    is generated. If <timeout> is not TIMEOUT_IGNORED_APPLE, or <flags>
317    is not zero, an INVALID_VALUE error is generated [fn4].
318       [fn4 - <flags> and <timeout> are placeholders for anticipated future
319    extensions of sync object capabilities. They must have these reserved
320    values in order that existing code calling WaitSyncAPPLE operate properly
321    in the presence of such extensions.]
322
323    Multiple Waiters
324    ----------------
325
326    It is possible for both the GL client to be blocked on a sync object
327    in a ClientWaitSyncAPPLE command, the GL server to be blocked as the
328    result of a previous WaitSyncAPPLE command, and for additional
329    WaitSyncAPPLE commands to be queued in the GL server, all for a single
330    sync object. When such a sync object is signaled in this situation, the
331    client will be unblocked, the server will be unblocked, and all such
332    queued WaitSyncAPPLE commands will continue immediately when they are
333    reached.
334
335    See appendix C.2 for more information about blocking on a sync
336    object in multiple GL contexts.
337
338    5.2.2 Signalling
339    ----------------
340
341    A fence sync object can be in the signaled state only once the
342    corresponding fence command has completed and signaled the sync
343    object.
344
345    If the sync object being blocked upon will not be signaled in finite
346    time (for example, by an associated fence command issued previously,
347    but not yet flushed to the graphics pipeline), then ClientWaitSyncAPPLE
348    may hang forever. To help prevent this behavior [fn5], if the
349    SYNC_FLUSH_COMMANDS_BIT_APPLE bit is set in <flags>, and <sync> is
350    unsignaled when ClientWaitSyncAPPLE is called, then the equivalent of
351    Flush will be performed before blocking on <sync>.
352       [fn5 - The simple flushing behavior defined by
353    SYNC_FLUSH_COMMANDS_BIT_APPLE will not help when waiting for a fence
354    command issued in another context's command stream to complete.
355    Applications which block on a fence sync object must take
356    additional steps to assure that the context from which the
357    corresponding fence command was issued has flushed that command
358    to the graphics pipeline.]
359
360    If a sync object is marked for deletion while a client is blocking
361    on that object in a ClientWaitSyncAPPLE command, or a GL server is
362    blocking on that object as a result of a prior WaitSyncAPPLE command,
363    deletion is deferred until the sync object is signaled and all
364    blocked GL clients and servers are unblocked.
365
366    Additional constraints on the use of sync objects are discussed in
367    appendix C.
368
369    State must be maintained to indicate which sync object names are
370    currently in use. The state require for each sync object in use is
371    an integer for the specific type, an integer for the condition, an
372    integer for the flags, and a bit indicating whether the object is
373    signaled or unsignaled. The initial values of sync object state are
374    defined as specified by FenceSyncAPPLE."
375
376    Update the Debug Labels section's last sentence to include
377    SYNC_OBJECT_APPLE as a value supported for the <type> passed to
378    LabelObjectEXT.
379
380Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
381Requests)
382
383    Add GetInteger64vAPPLE to the first list of commands in section 6.1.1
384    "Simple Queries", and change the next sentence to mention the query:
385
386   "There are four commands for obtaining simple state variables:
387
388       ...
389       void GetInteger64vAPPLE(enum value, int64 *data);
390       ...
391
392    The commands obtain boolean, integer, 64-bit integer, or
393    floating-point..."
394
395    Modify the third sentence of section 6.1.2 "Data Conversions":
396
397   "If any of the other simple queries are called, a boolean value of
398    TRUE or FALSE is interpreted as 1 or 0, respectively. If GetIntegerv
399    or GetInteger64vAPPLE are called, a floating-point value is rounded to
400    the nearest integer, unless the value is an RGBA color component..."
401
402    Insert a new subsection following "String Queries" (subsection
403    6.1.5) describing sync object queries. Renumber existing subsection
404    6.1.6 "Buffer Object Queries" and all following 6.1.* subsections.
405
406   "6.1.6 Sync Object Queries
407
408    Properties of sync objects may be queried using the command
409
410    void GetSyncivAPPLE(sync sync, enum pname, sizei bufSize,
411        sizei *length, int *values);
412
413    The value or values being queried are returned in the parameters
414    <length> and <values>.
415
416    On success, GetSyncivAPPLE replaces up to <bufSize> integers in <values>
417    with the corresponding property values of the object being queried.
418    The actual number of integers replaced is returned in *<length>. If
419    <length> is NULL, no length is returned.
420
421    If <pname> is OBJECT_TYPE_APPLE, a single value representing the specific
422    type of the sync object is placed in <values>. The only type
423    supported is SYNC_FENCE_APPLE.
424
425    If <pname> is SYNC_STATUS_APPLE, a single value representing the status of
426    the sync object (SIGNALED_APPLE or UNSIGNALED_APPLE) is placed in <values>.
427
428    If <pname> is SYNC_CONDITION_APPLE, a single value representing the
429    condition of the sync object is placed in <values>. The only
430    condition supported is SYNC_GPU_COMMANDS_COMPLETE_APPLE.
431
432    If <pname> is SYNC_FLAGS_APPLE, a single value representing the flags with
433    which the sync object was created is placed in <values>. No flags
434    are currently supported.
435
436    If <sync> is not the name of a sync object, an INVALID_VALUE error
437    is generated. If <pname> is not one of the values described above,
438    an INVALID_ENUM error is generated. If an error occurs,
439    nothing will be written to <values> or <length>.
440
441    The command
442
443    boolean IsSyncAPPLE(sync sync);
444
445    returns TRUE if <sync> is the name of a sync object. If <sync> is
446    not the name of a sync object, or if an error condition occurs,
447    IsSyncAPPLE returns FALSE (note that zero is not the name of a sync
448    object).
449
450    Sync object names immediately become invalid after calling
451    DeleteSyncAPPLE, as discussed in sections 5.2 and D.2, but the underlying
452    sync object will not be deleted until it is no longer associated
453    with any fence command and no longer blocking any *WaitSyncAPPLE command."
454
455    Update the Debug Labels section's last sentence to include
456    SYNC_OBJECT_APPLE as a value supported for the <type> passed to
457    GetObjectLabelEXT.
458
459
460Additions to Appendix C (Shared Objects and Multiple Contexts)
461
462    In the third paragraph of the appendix, add "sync objects" to the
463    list of shared state.
464
465    Add "sync objects" to the list of objects in the first sentence of
466    C.1.3.  Append the following to the first paragraph of C.1.3:
467
468   "A sync object is in use while there is a corresponding fence command
469    which has not yet completed and signaled the sync object, or while
470    there are any GL clients and/or servers blocked on the sync object as
471    a result of ClientWaitSyncAPPLE or WaitSyncAPPLE commands."
472
473   "C.1.3 Deleted Object and Object Name Lifetimes
474
475    Insert a new section following "Object Deletion Behavior" (section
476    C.1) describing sync object multicontext behavior. Renumber existing
477    section C.2 "Propagating State Changes..." and all following C.*
478    sections.
479
480   "C.2 Sync Objects and Multiple Contexts
481    --------------------------------------
482
483    When multiple GL clients and/or servers are blocked on a single sync
484    object and that sync object is signalled, all such blocks are released.
485    The order in which blocks are released is implementation-dependent."
486
487    Edit the former C.2.1 to read as follows:
488
489   "C.3.1 Determining Completion of Changes to an object
490    ----------------------------------------------------
491
492    The contents of an object T are considered to have been changed once
493    a command such as described in section C.2 has completed. Completion
494    of a command [fn6] may be determined either by calling Finish, or by
495    calling FenceSyncAPPLE and executing a WaitSyncAPPLE command on the
496    associated sync object. The second method does not require a round trip
497    to the GL server and may be more efficient, particularly when changes to
498    T in one context must be known to have completed before executing
499    commands dependent on those changes in another context.
500        [fn6: The GL already specifies that a single context processes
501    commands in the order they are received. This means that a change to
502    an object in a context at time <t> must be completed by the time a
503    command issued in the same context at time <t+1> uses the result of that
504    change.]"
505
506Dependencies on EXT_debug_label
507
508    If EXT_debug_label is not available, omit the updates to Debug label
509    sections of chapters 5 and 6, and omit SYNC_OBJECT_APPLE from Table 6.X.
510
511Errors
512
513    INVALID_VALUE is generated if the <sync> parameter of
514    ClientWaitSyncAPPLE, WaitSyncAPPLE, or GetSyncivAPPLE is not the name
515    of a sync object.
516
517    INVALID_VALUE is generated if the <sync> parameter of DeleteSyncAPPLE
518    is neither zero nor the name of a sync object.
519
520    INVALID_ENUM is generated if the <condition> parameter of FenceSyncAPPLE
521    is not SYNC_GPU_COMMANDS_COMPLETE_APPLE.
522
523    INVALID_VALUE is generated if the <flags> parameter of
524    ClientWaitSyncAPPLE contains bits other than SYNC_FLUSH_COMMANDS_BIT_APPLE,
525    or if the <flags> parameter of WaitSyncAPPLE is nonzero.
526
527    INVALID_ENUM is generated if the <pname> parameter of GetSyncivAPPLE is
528    neither OBJECT_TYPE_APPLE, SYNC_CONDITION_APPLE, SYNC_FLAGS_APPLE, nor
529    SYNC_STATUS_APPLE.
530
531New State
532
533Table 6.X.  Sync Objects.
534
535Get value             Type  Get command        Initial value                     Description            Section
536--------------------  ----  -----------------  --------------------------------  ---------------------  -------
537OBJECT_TYPE_APPLE     Z_1   GetSyncivAPPLE     SYNC_FENCE_APPLE                  Type of sync object    5.2
538SYNC_STATUS_APPLE     Z_2   GetSyncivAPPLE     UNSIGNALED_APPLE                  Sync object status     5.2
539SYNC_CONDITION_APPLE  Z_1   GetSyncivAPPLE     SYNC_GPU_COMMANDS_COMPLETE_APPLE  Sync object condition  5.2
540SYNC_FLAGS_APPLE      Z     GetSyncivAPPLE     SYNC_FLAGS_APPLE                  Sync object flags      5.2
541SYNC_OBJECT_APPLE     0*xc  GetObjectLabelEXT  empty                             Debug label            5.X
542
543New Implementation Dependent State
544
545Table 40. Implementation Dependent Values (cont.)
546
547Get value           Type  Get command    Min. value  Description       Section
548------------------  ----  -------------  ----------  ----------------  -------
549MAX_SERVER_WAIT_    Z^+   GetInteger64v  0           Maximum WaitSync  5.2
550TIMEOUT_APPLE                                         timeout interval
551
552Sample Code
553
554    ... kick off a lengthy GL operation
555    /* Place a fence and associate a fence sync object */
556    GLsyncAPPLE sync = glFenceSyncAPPLE(GLSYNC_GPU_COMMANDS_COMPLETE_APPLE, 0);
557
558    /* Elsewhere, wait for the sync to be signaled */
559
560    /* To wait a specified amount of time (possibly clamped), do
561     * this to convert a time in seconds into nanoseconds:
562     */
563    GLuint64APPLE timeout = num_seconds * ((GLuint64)1000 * 1000 * 1000);
564    glWaitSyncAPPLE(sync, 0, timeout);
565
566    /* Or to determine the maximum possible wait interval and wait
567     * that long, do this instead:
568     */
569    GLuint64APPLE max_timeout;
570    glGetInteger64vAPPLE(GL_MAX_SERVER_WAIT_TIMEOUT_APPLE, &max_timeout);
571    glWaitSyncAPPLE(sync, 0, max_timeout);
572
573Issues
574
575    See ARB_sync issues list: http://www.opengl.org/registry/specs/ARB/sync.txt
576
577Revision History
578
579    Version 3, 2012/07/10 - Add support for debug label extension.
580    Version 2, 2012/06/18 - Correct spec to indicate ES 1.1 may also be okay.
581    Version 1, 2012/06/01 - Conversion from ARB_sync to APPLE_sync for ES.
582