Sync Object in OpenGL (about GPU Fence)

Sync Object

SyncObject
     
Core in version 4.4
Core since version 3.2
Core ARB extension ARB_sync
Vendor extension NV_fence

Sync Objects are objects that are used to synchronize the activity between the GPU andthe application. glFinish is a start tosynchronization, but sync objects allow for much finer grainedcontrol.

Contents

SyncObject Conventions

Sync objects do not follow the standard OpenGL Object model. Regular OpenGL objects useGLuint​ names; sync objects aredefined as a pointer to an opaque type. This is defined as:

 typedef struct __GLsync *GLsync;

Sync objects have a type. Each sync object type has its ownunique object creation function, though they all create GLsyncobjects. Thus, these objects are not created with the usual pair ofglGen*/glDelete*​ functions. There isa generic glDeleteSync function to deleteany kind of sync object.

Sync objects are never bound to the context, nor do theyencapsulate state the way normal GL objects do. These arenot OpenGL objects.

Synchronization

The purpose of sync objects is to synchronize the CPU with theGPU's actions. To do this, sync objects have the concept of acurrent status. The status of a sync object can be signaled orunsignaled; this state represents some condition of the GPU,depending on the particular type of sync object and how it wasused. This is similar to how mutual exclusives are used tosynchronize behavior between threads; when a mutex becomessignaled, it allows other threads that are waiting on it toactivate.

To block all CPU operations until a sync object is signaled, youcall this function:

enum glClientWaitSync(GLsyncsync, GLbitfield flags, GLuint64timeout)

This function will not return until one of two things happens:the sync​ object parameter becomessignaled, or a number of nanoseconds greater than or equal to thetimeout​ parameter passes. Iftimeout​ is zero, the function willsimply check to see if the sync object is signaled and returnimmediately. Note that the fact that timeout​ is in nanoseconds does not implythat this function has true nanosecond granularity in its timeout;you are only guaranteed that at least that much time willpass.

The return value explains why glClientWaitSync returned. Ifit returns GL_ALREADY_SIGNALED​, thenthe sync object was signaled before the function was called. If itreturns GL_TIMEOUT_EXPIRED​, then thesync object did not signal within the given timeout period. IfGL_CONDITION_SATISFIED​ is returned,then the sync object was signaled within the given timeout period.If an OpenGL Error occurred, then GL_WAIT_FAILED​ will be returned in addition toraising an error.

The flags​ parameter controls howOpenGL's command queue is flushed. If you pass GL_SYNC_FLUSH_COMMANDS_BIT​, then the equivalentof a glFlush will be issued before blockingon the sync object. This is done to prevent a certain kind ofinfinite loop due to the GPU's command queue being currently toofull to accept the sync object. You only need to pass the flag thefirst time.

There is another function for waiting on sync objects:

void glWaitSync(GLsync sync,GLbitfield flags, GLuint64 timeout)

Recall the discussion in the article on Synchronization about the difference betweenthe GPU's command queue and the driver's internal command buffer.What glWaitSync does is prevent thedriver from adding any commands to the GPU's command queueuntil this sync object is signaled. This function does not wait forthis to happen.

The driver will still put commands in its internal buffer. Butnone of them will be seen by the GPU until this sync object issignaled.

You need to perform a glFlush before calling this, to ensurethat the sync object is in the GPU's command queue. If you don't,then you may create an infinite loop. Since glWaitSync prevents the driverfrom adding any commands to the GPU command queue, thiswould include the sync object itself if it has not yet beenadded to the queue. This function does not take the GL_SYNC_FLUSH_COMMANDS_BIT​, so you have to do itmanually.

Sync ObjectTypes

As previously mentioned, sync objects have a specific type,which defines their signaling behavior. Currently, there is onlyone type: fences.

Fence

A fence is a sync object that is added to the OpenGL commandstream. It starts unsignaled, and becomes signaled when the GPUexecutes and completes the fence. Because OpenGL must execute andcomplete commands in order, when a fence becomes signaled, you canbe certain that the GPU has completed all OpenGL commandsissued before the fence was created.

A fence is created with this function:

GLsync glFenceSync(GLenumcondition, GLbitfield flags)

This function not only creates a fence, but it adds it tothe command stream. So only call it in the location you want toplace the fence.

The only available value for condition​ is GL_SYNC_GPU_COMMANDS_COMPLETE​. This causes thefence to be signaled when the GPU has completed all previouslyissued commands. Currently, the flags​ field has no possible parameters; itshould be 0. The field exists in case of future extensions to thisfunctionality.

The fact that fences are signaled after the commands havecompleted, not just are started, means that it allows you toknow when the GPU has finished using certain resources. Forexample, if you want to access a buffer object, but do not want toblock the CPU until the GPU has finished using it, then you can seta fence after the last command that used the buffer object. It isalso useful for knowing when a pixel buffer orfeedback buffer has the data yourequested.

LegacySync

NVIDIA hardware has had the NV_fenceextension for a long time, since the GeForce 256 days. Thisextension provides the effect of fence sync objects, though with adifferent API.

Reference

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章