Skip to main content
GameDev.net gamedev.net
🔒 Locked

[D3D12] Barriers and Fences

Started by Infinisearch Sep 12, 2015 at 7:54 PM 7 replies 20.5k views
Original Post
Infinisearch
Infinisearch

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.

-potential energy is easily made kinetic-
_the_phantom_
_the_phantom_
Resource barriers - adds commands to convert a resource (or resources) from one type to another (such as a render target to a texture), prevents further command execution until the GPU has finished doing any work needed to convert the resources as requested.

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

Thank you, but that was a bit too simple. Basically some pseudo-code demonstrating each would be greatly appreciated. Thanks again for trying.

-potential energy is easily made kinetic-
Matias Goldberg
Matias Goldberg

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

Hodgman
Hodgman

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):

0) Issue a resource barrier, transitioning A and B from "uninitialized" state to "color target" state.

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

2.1) Issue a resource barrier, transitioning B from "color target" state to "readable texture" state.
2.2) Issue a resource barrier, transitioning A from "readable texture" state to "color target" state.

3) Bind Texture A as a render-target, draw a quad to it which reads from Texture B and does a vertical blur

Basically, before you use a resource in any particular way, you need to issue a barrier command that tells that API to prepare the resource for this type of usage. e.g. as above, we're switching between texture resources being used as writable render-targets and readable textures (shader resources).
BornToCode
BornToCode

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.

Infinisearch
Infinisearch

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.

-potential energy is easily made kinetic-
Hodgman
Hodgman
To ensure you've only got FRAMES frames in flight at once:
//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.
Infinisearch
Infinisearch

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.

-potential energy is easily made kinetic-

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.