blob: c48173445af7033b58ec4475805d62930a639663 [file] [log] [blame]
Name
NV_fence
Name Strings
GL_NV_fence
Contact
John Spitzer, NVIDIA Corporation (jspitzer 'at' nvidia.com)
Mark Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com)
Contributors
John Spitzer
Mark Kilgard
Acorn Pooley
Notice
Copyright NVIDIA Corporation, 2000, 2001.
IP Status
NVIDIA Proprietary.
Status
Shipping as of June 8, 2000 (version 1.0)
Shipping as of November, 2003 (version 1.1)
Version 1.2 adds ES support and clarification; otherwise identical to 1.1.
Version
December 17, 2008 (version 1.2)
Number
OpenGL Extension #222
OpenGL ES Extension #52
Dependencies
This extension is written against the OpenGL 1.2.1 Specification.
It can also be used with OpenGL ES (see the section, "Dependencies on
OpenGL ES," below).
Overview
The goal of this extension is provide a finer granularity of
synchronizing GL command completion than offered by standard OpenGL,
which offers only two mechanisms for synchronization: Flush and Finish.
Since Flush merely assures the user that the commands complete in a
finite (though undetermined) amount of time, it is, thus, of only
modest utility. Finish, on the other hand, stalls CPU execution
until all pending GL commands have completed. This extension offers
a middle ground - the ability to "finish" a subset of the command
stream, and the ability to determine whether a given command has
completed or not.
This extension introduces the concept of a "fence" to the OpenGL
command stream. Once the fence is inserted into the command stream, it
can be queried for a given condition - typically, its completion.
Moreover, the application may also request a partial Finish -- that is,
all commands prior to the fence will be forced to complete until control
is returned to the calling process. These new mechanisms allow for
synchronization between the host CPU and the GPU, which may be accessing
the same resources (typically memory).
This extension is useful in conjunction with NV_vertex_array_range
to determine when vertex information has been pulled from the
vertex array range. Once a fence has been tested TRUE or finished,
all vertex indices issued before the fence must have been pulled.
This ensures that the vertex data memory corresponding to the issued
vertex indices can be safely modified (assuming no other outstanding
vertex indices are issued subsequent to the fence).
Issues
Do we need an IsFenceNV command?
RESOLUTION: Yes. Not sure who would use this, but it's in there.
Semantics currently follow the texture object definition --
that is, calling IsFenceNV before SetFenceNV will return FALSE.
Are the fences sharable between multiple contexts?
RESOLUTION: No.
Potentially this could change with a subsequent extension.
What other conditions will be supported?
Only ALL_COMPLETED_NV will be supported initially. Future extensions
may wish to implement additional fence conditions.
What is the relative performance of the calls?
Execution of a SetFenceNV is not free, but will not trigger a
Flush or Finish.
Is the TestFenceNV call really necessary? How often would this be used
compared to the FinishFenceNV call (which also flushes to ensure this
happens in finite time)?
It is conceivable that a user may use TestFenceNV to decide
which portion of memory should be used next without stalling
the CPU. An example of this would be a scenario where a single
AGP buffer is used for both static (unchanged for multiple frames)
and dynamic (changed every frame) data. If the user has written
dynamic data to all banks dedicated to dynamic data, and still
has more dynamic objects to write, the user would first want to
check if the first dynamic object has completed, before writing
into the buffer. If the object has not completed, instead of
stalling the CPU with a FinishFenceNV call, it would possibly
be better to start overwriting static objects instead.
What should happen if TestFenceNV is called for a name before SetFenceNV
is called?
We generate an INVALID_OPERATION error, and return TRUE.
This follows the semantics for texture object names before
they are bound, in that they acquire their state upon binding.
We will arbitrarily return TRUE for consistency.
What should happen if FinishFenceNV is called for a name before
SetFenceNV is called?
RESOLUTION: Generate an INVALID_OPERATION error because the
fence id does not exist yet. SetFenceNV must be called to create
a fence.
Do we need a mechanism to query which condition a given fence was
set with?
RESOLUTION: Yes, use glGetFenceivNV with FENCE_CONDITION_NV.
Should we allow these commands to be compiled within display list?
Which ones? How about within Begin/End pairs?
RESOLUTION: DeleteFencesNV, FinishFenceNV, GenFencesNV,
TestFenceNV, and IsFenceNV are executed immediately while
SetFenceNV is compiled. Do not allow any of these commands
within Begin/End pairs.
Can fences be used as a form of performance monitoring?
Yes, with some caveats. By setting and testing or finishing
fences, developers can measure the GPU latency for completing
GL operations. For example, developers might do the following:
start = getCurrentTime();
updateTextures();
glSetFenceNV(TEXTURE_LOAD_FENCE, GL_ALL_COMPLETED_NV);
drawBackground();
glSetFenceNV(DRAW_BACKGROUND_FENCE, GL_ALL_COMPLETED_NV);
drawCharacters();
glSetFenceNV(DRAW_CHARACTERS_FENCE, GL_ALL_COMPLETED_NV);
glFinishFenceNV(TEXTURE_LOAD_FENCE);
textureLoadEnd = getCurrentTime();
glFinishFenceNV(DRAW_BACKGROUND_FENCE);
drawBackgroundEnd = getCurrentTime();
glFinishFenceNV(DRAW_CHARACTERS_FENCE);
drawCharactersEnd = getCurrentTime();
printf("texture load time = %d\n", textureLoadEnd - start);
printf("draw background time = %d\n", drawBackgroundEnd - textureLoadEnd);
printf("draw characters time = %d\n", drawCharacters - drawBackgroundEnd);
Note that there is a small amount of overhead associated with
inserting each fence into the GL command stream. Each fence
causes the GL command stream to momentarily idle (idling the
entire GPU pipeline). The significance of this idling should
be small if there are a small number of fences and large amount
of intervening commands.
If the time between two fences is zero or very near zero,
it probably means that a GPU-CPU synchronization such as a
glFinish probably occurred. A glFinish is an explicit GPU-CPU
synchronization, but sometimes implicit GPU-CPU synchronizations
are performed by the driver.
What happens if you set the same fence object twice?
The second SetFenceNV clobbers whatever status the fence object
previously had by forcing the object's status to GL_TRUE.
The completion of the first SetFenceNV's fence command placed
in the command stream is ignored (its completion does NOT
update the fence object's status). The second SetFenceNV sets a
new fence command in the GL command stream. This second fence
command will update the fence object's status (assuming it is
not ignored by a subsequent SetFenceNV to the same fence object).
What happens to a fence command that is still pending execution
when its fence object is deleted?
The fence command completion is ignored.
What happens if you use an arbitrary number for the SetFenceNV() <fence>
parameter instead of obtaining the name from GenFences()?
This works fine (just as with texture objects).
New Procedures and Functions
void GenFencesNV(sizei n, uint *fences);
void DeleteFencesNV(sizei n, const uint *fences);
void SetFenceNV(uint fence, enum condition);
boolean TestFenceNV(uint fence);
void FinishFenceNV(uint fence);
boolean IsFenceNV(uint fence);
void GetFenceivNV(uint fence, enum pname, int *params);
New Tokens
Accepted by the <condition> parameter of SetFenceNV:
ALL_COMPLETED_NV 0x84F2
Accepted by the <pname> parameter of GetFenceivNV:
FENCE_STATUS_NV 0x84F3
FENCE_CONDITION_NV 0x84F4
Additions to Chapter 5 of the OpenGL 1.2.1 Specification (Special Functions)
Add to the end of Section 5.4 "Display Lists"
"DeleteFencesNV, FinishFenceNV, GenFencesNV, GetFenceivNV,
TestFenceNV, and IsFenceNV are not complied into display lists but
are executed immediately."
After the discussion of Flush and Finish (Section 5.5) add a
description of the fence operations:
"5.X Fences
The command
void SetFenceNV(uint fence, enum condition);
creates a fence object named <fence> if one does not already exist
and sets a fence command within the GL command stream. If the named
fence object already exists, a new fence command is set within the GL
command stream (and any previous pending fence command corresponding
to the fence object is ignored). Whether or not a new fence object is
created, SetFenceNV assigns the named fence object a status of FALSE
and a condition as set by the condition argument. The condition
argument must be ALL_COMPLETED_NV. Once the fence's condition is
satisfied within the command stream, the corresponding fence object's
state is changed to TRUE. For a condition of ALL_COMPLETED_NV,
this is completion of the fence command and all preceding commands.
No other state is affected by execution of the fence command. The name
<fence> may be one returned by GenFencesNV() but that is not required.
A fence's state can be queried by calling the command
boolean TestFenceNV(uint fence);
The command
void FinishFenceNV(uint fence);
forces all GL commands prior to the fence to satisfy the condition
set within SetFenceNV, which, in this spec, is always completion.
FinishFenceNV does not return until all effects from these commands
on GL client and server state and the framebuffer are fully realized.
The command
void GenFencesNV(sizei n, uint *fences);
returns n previously unused fence names in fences. These names
are marked as used, for the purposes of GenFencesNV only, but
corresponding fence objects do not exist (have no state) until created
with SetFenceNV().
Fences are deleted by calling
void DeleteFencesNV(sizei n, const uint *fences);
fences contains n names of fences to be deleted. After a fence is
deleted, it has no state, and its name is again unused. Unused names
in fences are silently ignored.
If the fence passed to TestFenceNV or FinishFenceNV is not the name of an
existing fence, the error INVALID_OPERATION is generated. In this case,
TestFenceNV will return TRUE, for the sake of consistency.
State must be maintained to indicate which fence integers are
currently used or set. In the initial state, no indices are in use.
When a fence integer is set, the condition and status of the fence
are also maintained. The status is a boolean. The condition is
the value last set as the condition by SetFenceNV.
Once the status of a fence has been finished (via FinishFenceNV)
or tested and the returned status is TRUE (via either TestFenceNV
or GetFenceivNV querying the FENCE_STATUS_NV), the status remains
TRUE until the next SetFenceNV of the fence."
Additions to Chapter 6 of the OpenGL 1.2.1 Specification (State and State Requests)
Insert new section after Section 6.1.10 "Minmax Query"
"6.1.11 Fence Query
The command
boolean IsFenceNV(uint fence);
return TRUE if <fence> is the name of an existing fence. If <fence> is
not the name of an existing fence, or if an error condition occurs,
IsFenceNV returns FALSE. A name returned by GenFencesNV, but not yet set
via SetFenceNV, is not the name of an existing fence.
The command
void GetFenceivNV(uint fence, enum pname, int *params)
obtains the indicated fence state for the specified fence in the array
params. pname must be either FENCE_STATUS_NV or FENCE_CONDITION_NV.
The INVALID_OPERATION error is generated if the named fence does
not exist."
Additions to the GLX Specification
None
GLX Protocol
Seven new GL commands are added.
The following rendering command is sent to the sever as part of a
glXRender request:
SetFenceNV
2 12 rendering command length
2 4143 rendering command opcode
4 CARD32 fence
4 CARD32 condition
The remaining five commands are non-rendering commands. These
commands are sent separately (i.e., not as part of a glXRender or
glXRenderLarge request), using the glXVendorPrivateWithReply request:
DeleteFencesNV
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 4+n request length
4 1276 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 INT32 n
n*4 LISTofCARD32 fences
GenFencesNV
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 4 request length
4 1277 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 INT32 n
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 n reply length
24 unused
n*4 LISTofCARD322 fences
IsFenceNV
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 4 request length
4 1278 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 INT32 n
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 0 reply length
4 BOOL32 return value
20 unused
TestFenceNV
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 4 request length
4 1279 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 INT32 fence
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 0 reply length
4 BOOL32 return value
20 unused
GetFenceivNV
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 5 request length
4 1280 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 INT32 fence
4 CARD32 pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m=(n==1?0:n)
4 unused
4 CARD32 n
if (n=1) this follows:
4 INT32 params
12 unused
otherwise this follows:
16 unused
n*4 LISTofINT32 params
FinishFenceNV
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 4 request length
4 1312 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 INT32 fence
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 0 reply length
24 unused
Errors
INVALID_VALUE is generated if GenFencesNV or DeleteFencesNV parameter <n>
is negative.
INVALID_OPERATION is generated if the fence used in TestFenceNV,
FinishFenceNV or GetFenceivNV is not the name of an existing fence.
INVALID_ENUM is generated if the condition used in SetFenceNV
is not ALL_COMPLETED_NV.
INVALID_OPERATION is generated if any of the commands defined in
this extension is executed between the execution of Begin and the
corresponding execution of End.
New State
Table 6.X. Fence Objects.
Get value Type Get command Initial value Description Section Attribute
------------------ ---- ------------ ---------------------------- --------------- ------- ---------
FENCE_STATUS_NV B GetFenceivNV determined by 1st SetFenceNV Fence status 5.X -
FENCE_CONDITION_NV Z1 GetFenceivNV determined by 1st SetFenceNV Fence condition 5.X -
New Implementation Dependent State
None
Dependencies on OpenGL ES
If implemented for OpenGL ES, NV_fence acts as described in this spec,
except:
* Ignore all references to display lists and immediate mode, including
changes to section 5.4 "Display Lists".
* Ignore all references to GLX and GLX protocol.
GeForce Implementation Details
This section describes implementation-defined limits for GeForce:
SetFenceNV calls are not free. They should be used prudently,
and a "good number" of commands should be sent between calls to
SetFenceNV. Each fence insertion will cause the GPU's command
processing to go momentarily idle. Testing or finishing a fence
may require an one or more somewhat expensive uncached reads.
Do not leave a fence untested or unfinished for an extremely large
interval of intervening fences. If more than approximately 2
billion (specifically 2^31-1) intervening fences are inserted into
the GL command stream before a fence is tested or finished, said
fence may indicate an incorrect status. Note that certain GL
operations involving display lists, compiled vertex arrays, and
textures may insert fences implicitly for internal driver use.
In practice, this limitation is unlikely to be a practical
limitation if fences are finished or tested within a few frames
of their insertion into the GL command stream.
Revision History
November 13, 2000 - GLX enumerant values assigned
October 3, 2003 - Changed version to 1.1. glFinishFenceNV should
not be compiled into display lists but rather executed immediately
when called during display list construction. Version 1.0 allowed
this though it should not have been allowed. Changed GLX protocol
so that FinishFenceNV is a non-render request with a reply now.
Thanks to Bob Beretta for noticing this issue.
Also fix a typo in the GLX protocol specification for IsFenceNV so
the reply is 32 (not 33) bytes.
December 17. 2008 - Add "Dependencies on OpenGL ES" section. Clarify
generation of fence name vs creation of the fence itself.