Can anyone explain fences and resource barriers to me in the simplest fashion possible? I am not used to such constructs and want to be sure I get it right.
[D3D12] Barriers and Fences
Fences - a marker in a command stream. Allows you to know when the GPU, or CPU, has finished doing some work so they can be synchronised.
Example; GPU command queue/list contains a fence which can be set by the CPU - this prevents the GPU from executing more commands until the CPU signals it is done. So, for example, if you have a command which reads from a buffer on the GPU and the CPU needs to fill that buffer, you'd insert a fence in to the GPU commands which tell it to wait until the CPU has signalled that the copy has completed.
Going the other way, you can use a fence the GPU has set to know where the GPU has got to executing. A good example of this added a fence command at the end of the frame, so the CPU knows when the GPU is done with the last frame's worth of data/buffers.
Thank you, but that was a bit too simple. Basically some pseudo-code demonstrating each would be greatly appreciated. Thanks again for trying.
Thank you, but that was a bit too simple. Basically some pseudo-code demonstrating each would be greatly appreciated. Thanks again for trying.
Fences and barriers aren't exclusive to D3D12 programming, but rather to any kind of multithreaded programming. If the D3D12 examples aren't good enough for you, you can try the closest OpenGL equivalent in apitest examples.
In OpenGL, fences are the equivalent of glFenceSync & glWaitSync (CPU waits for GPU to finish until the barrier point is hit) and barriers are roughly the equivalent of glFlushMappedBufferRange (in GL with non-coherent persistent mapping you need to explicitly tell which regions of the mapped memory you have updated so GPU caches can be invalidated and flushed) & glMemoryBarrier (Compute Shaders that write to resource A are executed before compute shaders that use that resource A for reading, otherwise they may be executed in any random order regardless of the order you issued the calls from CPU).
Barriers (AKA transitions) are new to Mantle/Vulkan/D3D12.
Some example pseudo-code for a traditional blur effect:
1) Bind Texture A as a render-target, draw models to it
2) Bind Texture B as a render-target, draw a quad to it, which reads from Texture A and does a horizontal blur
3) Bind Texture A as a render-target, draw a quad to it, which reads from Texture B and does a vertical blur
In these modern APIs with resource barriers, this becomes (steps 1/2/3 are unchanged -- barriers inserted between them):
1) Bind Texture A as a render-target, draw models to it
1.1) Issue a resource barrier, transitioning A from "color target" state to "readable texture" state.
2) Bind Texture B as a render-target, draw a quad to it which reads from Texture A and does a horizontal blur
3) Bind Texture A as a render-target, draw a quad to it which reads from Texture B and does a vertical blur
Resource barrier are a way to tell the GPU that you are switching the resource state. You see on the GPU a Resource is just that a resource. It can be in many different states. So resource barrier just let you set the resource state you want it to be before modifying that state.
Thanks guys, Hodgman's answer cleared up my doubt in regards to resource barriers. Anyone wanna pseudo code an example for fences for me? Greatly appreciated.
//On Init:
FenceEvent* fences[FRAMES];
int counter = 0;
for( int i=0; i!=FRAMES; i++ )
fences[i] = gpu.CreateFenceEvent();
//On End/Begin frame:
gpu.Submit(commandBuffer);
gpu.Present(backbuffer);
gpu.GpuSignalEvent(fences[counter]); //the GPU will signal the fence later, once all of the above had been completed
// what's the oldest fence in that array
int oldestCounter = counter + 1;
if(oldestCounter?FRAMES) oldestCounter = 0;
// If the GPU hasn't signalled the oldest fence, have the CPU block here until it does.
gpu.CpuWaitEvent(fences[oldestCounter]);
counter++;
if(counter?FRAMES) counter = 0;n.b. this has been common practice since d3d9, but is mandatory now in d3d12.
Thank you Hodgman that clears it up for the most part, I was confused because I was misreading something in the docs. Upon closer inspection I realized my mistake after I read your post which prompted the closer inspection.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.