To know when an OpenGL command has been executed on the GPU, you can create a fence after it has signaled.
```cs
// Perform any OpenGL command
Gl.DrawArrays(...);
// Create a fence
var fence = new FenceObject();
...
// Later on, check if it's signaled
if (fence.CheckSignal())
{
// Command is done!
}
```
You can also wait until the fence is complete, if you'd like to sync your CPU and GPU together:
```cs
// Halt the CPU until the GPU has issued the above command
fence.Wait();
// CPU and GPU are now in sync - the GPU now has nothing to do
```
Creating and checking many fences is expensive, so you can use a shared fence that will signal when the entire frame is complete:
```cs
// Perform any OpenGL command
Gl.DrawArrays(...);
// Get the shared fence
var fence = FenceManager.GetCurrentFence();
...
// Later on, check if it's signaled
if (fence.CheckSignal())
{
// Entire frame has completed!
}
```
## Usages
Fences are used often with UI rendering, as a UI element that updates each frame will have many textures in-flight. A fence is created after each texture is rendered, which means we can check which textures are still being rendered, and which can be disposed/recycled.
They are also useful when double-buffering vertex buffers, similar to textures. If you try to modify the data inside a vertex buffer that's still being rendered, your CPU will halt and wait for the GPU to finish rendering the buffer. This will cause your game to stutter. Instead, create a fence after rendering each vertex buffer, and only update the ones that's fences have signaled. If all buffers are still rendering or are yet to be rendered (multiple frames in flight), you'll need to create a new buffer and set the data in that instead.