<p>In your first example, the call to <code>WaitForSingleObject</code> <em>blocks</em> the thread. This puts it into a waiting state, which takes it off the run queue and allows other threads to run on this CPU core. If no threads can run, the CPU will idle. When the <code>fenceEvent</code> completes, it wakes up this thread.</p>

<p>Your proposed replacement is called a <em>spinlock</em>. The thread keeps running, using 100% of a core until the fence's completed flag changes. No other code can run on this core, so there's no interleaving of CPU and GPU work. Worse yet, this code has to read from memory to check the flag every time around the loop, so it'll slow down any threads on other cores that are also accessing memory. Finally, because it's keeping the core and the memory bus active, it'll burn more power and generate more heat.</p>

<p>This is why fence events are needed: to enable the CPU to wait efficiently.</p>

CC BY-SA 3.0
2018-02-05T10:26:23.547Z
Ok, that makes sense, I guess that if you know the amount of time its going to be idling you could also do some work there :)
Nacho
CC BY-SA 3.0
2018-02-05T10:30:54.590Z
@Nacho you can also put the fenceEvent in a list so you can use WaitForMulitpleObjects and also wait on (for example) Async File IO to complete on the same thread.
ratchet freak
CC BY-SA 3.0
2018-02-05T19:02:56.293Z
@Nacho The idea is that you shouldn't block on the fence until you have to, because the next thing you're going to do on the CPU depends on prior GPU commands having finished. For example, you might have a thread that composites frames generated from another thread, and the producer thread sends a fence along with other per-frame data, to keep the data and the frames in sync.
Dan Hulme
CC BY-SA 3.0
2018-02-05T09:37:04.103Z
2018-02-05T11:43:05.400Z
2018-02-05T11:43:05.400Z
Dan Hulme
<p>One of the hardest things for me with the modern closer to the metal graphics APIs is understanding synchronization. I usually try to simplify things in order to understand the concept better.</p>

<p>In Directx12, we can use a set of "x" fences (x being the number of back buffers) to allow the CPU to work ahead of the GPU. This could be the code we use to wait for a previous fence (<a href="https://www.braynzarsoft.net" rel="nofollow noreferrer">https://www.braynzarsoft.net</a>):</p>

<pre><code>if (fence[frameIndex]-&gt;GetCompletedValue() &lt; fenceValue[frameIndex])
{
    hr = fence[frameIndex]-&gt;SetEventOnCompletion(fenceValue[frameIndex], fenceEvent);
    if (FAILED(hr))
    {
        Running = false;
    }
    WaitForSingleObject(fenceEvent, INFINITE);
} 
</code></pre>

<p>Is there a reason why we can´t just:</p>

<pre><code>while(fence[frameIndex]-&gt;GetCompletedValue() &lt; fenceValue[frameIndex])
{
}
</code></pre>

<p>Thanks!</p>

<directx12><synchronization>
Do we really need a fence event?
Nacho
# Do we really need a fence event?

(Asked by: username_0 on 2018-02-04)

One of the hardest things for me with the modern closer to the metal graphics APIs is understanding synchronization. I usually try to simplify things in order to understand the concept better.

In Directx12, we can use a set of "x" fences (x being the number of back buffers) to allow the CPU to work ahead of the GPU. This could be the code we use to wait for a previous fence (<https://www.braynzarsoft.net>):

```
if (fence[frameIndex]->GetCompletedValue() < fenceValue[frameIndex])
{
    hr = fence[frameIndex]->SetEventOnCompletion(fenceValue[frameIndex], fenceEvent);
    if (FAILED(hr))
    {
        Running = false;
    }
    WaitForSingleObject(fenceEvent, INFINITE);
} 

```

Is there a reason why we can´t just:

```
while(fence[frameIndex]->GetCompletedValue() < fenceValue[frameIndex])
{
}

```

Thanks!

**Tags:** directx12, synchronization


---

## 1 answers

### Answer by username_1 on 2018-02-05. Score: 4 | Accepted answer

In your first example, the call to `WaitForSingleObject` *blocks* the thread. This puts it into a waiting state, which takes it off the run queue and allows other threads to run on this CPU core. If no threads can run, the CPU will idle. When the `fenceEvent` completes, it wakes up this thread.

Your proposed replacement is called a *spinlock*. The thread keeps running, using 100% of a core until the fence's completed flag changes. No other code can run on this core, so there's no interleaving of CPU and GPU work. Worse yet, this code has to read from memory to check the flag every time around the loop, so it'll slow down any threads on other cores that are also accessing memory. Finally, because it's keeping the core and the memory bus active, it'll burn more power and generate more heat.

This is why fence events are needed: to enable the CPU to wait efficiently.

> **Comments:**
> **username_0**: Ok, that makes sense, I guess that if you know the amount of time its going to be idling you could also do some work there :)  
> **username_2**: @username_0 you can also put the fenceEvent in a list so you can use WaitForMulitpleObjects and also wait on (for example) Async File IO to complete on the same thread.  
> **username_1**: @username_0 The idea is that you shouldn't block on the fence until you have to, because the next thing you're going to do on the CPU depends on prior GPU commands having finished. For example, you might have a thread that composites frames generated from another thread, and the producer thread sends a fence along with other per-frame data, to keep the data and the frames in sync.  

---

