Forcing Triple Buffering in DX12 Games

The DWM’s triple buffering is amazing, extremely useful, especially in gaming. Often I specifically use borderless to force triple buffering. However, I have noticed that it doesn’t actually work in DX12 mode. Every DX11 game I have played has had triple buffering forced when in windowed, but not one DX12 game. This is often an extreme problem with a fluctuating framerate where traditional double buffered V-Sync isn’t the best solution. Is there any way to force triple buffering in DX12 games? Using Special K or otherwise?

Unfortunately, no… you have discovered the hard way that D3D12 works differently.

In D3D12 (and Vulkan), the engine itself is responsible for batching commands on each and every one of its backbuffers. In D3D11, the driver does this implicitly every time you finish a frame it starts batching commands for the next buffer in the queue, but D3D12 and Vulkan leave the implementation of this up to the engine.

There is very little I can do, I pulled off a miracle IMO with Horizon: Zero Dawn. The engine should really be working with at least 3 backbuffers instead of 2; many engines work with 5 or more.

Technically, all D3D12 games are triple-buffered; the DWM owns one buffer, and then at minimum D3D12 requires a swapchain with 2 backbuffers. It’s a completely different kind of triple-buffering though, and will behave like plain old double-buffered VSYNC without careful frame pacing.

I used a waitable swapchain in Horizon: Zero Dawn to schedule frames more efficiently, but that’s as far as these kind of hacks will go with D3D12. Vulkan’s even worse.

1 Like

Well that is extremely unfortunate. Thanks for the response. So that means there is no solution for games without a stable framerate? (not counting G-Sync)

Throw more money and hardware at the problem until it goes away, basically :stuck_out_tongue_closed_eyes: That is all that is left to do with these low-level APIs if the game is not performing to your standards.

1 Like

No vsync at all could be the way to go, and use scanline capping to control the image tear to be at the very top or bottom of the screen so you don’t notice it.

Was trying scanline sync, but it didn’t work for me. What value do you use?

I don’t use it myself, I use gsync. There are guides floating around the internet, try at blur busters.