| 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. |