Jump to content
  • Advertisement
Sign in to follow this  

Why DirectX doesn't implement triple buffering?

This topic is 1667 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Is there any particular reason DirectX doesn't implement correct triple buffering?

It would solve screen tearing issue without introducing any additional latency (compared to double buffering)  and without dropping FPS like V-Sync with double buffering does.

 

The implementation I am talking about (page flipping method) is described here: http://www.anandtech.com/show/2794/4

 

 

Microsoft doesn't implement triple buffering in DirectX, they implement render ahead (from 0 to 8 frames with 3 being the default)...(aka a flip queue)

 

It would be a cheaper solution compared to Nvidia G-Sync. (G-Sync reduces lag even further compared to double buffering, but it requires monitor upgrade.)

 

So the question is why didn't MS implement this in DirectX as it seems that it would be a really simple thing to do, or am I missing something?

Share this post


Link to post
Share on other sites
Advertisement

It does; the Anandtech article is basically bogus misinformation.

 

For D3D9 look at the BackBufferCount member of D3DPRESENT_PARAMETERS.

For D3D10+ look at the BufferCount member of DXGI_SWAP_CHAIN_DESC.

 

The render-ahead method that Anandtech are talking about is something completely different and is controlled by IDirect3DDevice9Ex::SetMaximumFrameLatency or IDXGIDevice1::SetMaximumFrameLatency - that's the API for the 0 to 8 frame render-ahead; the number of back buffers used is not the same thing.

 

It's more appropriate to ask "why are Anandtech spreading misinformation?" here.

Share this post


Link to post
Share on other sites

In addition to that:

 

From the article: "The major difference in the technique we've described here is the ability to drop frames when they are outdated."

 

You can do this in D3D11 by using the DXGI_PRESENT_RESTART flag when calling IDXGISwapChain::Present. And for some reason I can't remember, you also have to use DXGI_SWAP_EFFECT_SEQUENTIAL for the swap chain, or you will get lag.

 

And you can't get tearing-free rendering simply by using triple-buffering. The only way to get rid of tearing is to use VSYNC, but the article doesn't mention if they use VSYNC in their triple-buffering method.

 

I just tested these flags, with BufferCount 3 and no VSYNC - it still tears.

Edited by tonemgub

Share this post


Link to post
Share on other sites

So why don't DirectX games use triple buffering when v-sync is enabled?

 

If i understand correctly circular pattern of switching buffers in chain described on MSDN, circular flipping process introduces additional latency, which is not the method of bouncing between two back buffers (while front buffer is sent to monitor) that Anandtech described.

 

 

When a flipping chain contains a front buffer and more than one back buffer, the pointers are switched in a circular pattern, as shown in the following diagram.

IC511449.png

http://msdn.microsoft.com/en-us/library/windows/desktop/bb173393%28v=vs.85%29.aspx

http://msdn.microsoft.com/en-us/library/windows/hardware/ff570099%28v=vs.85%29.aspx

EDIT: v-sync should be enabled with triple buffering to prevent tearing

here is what I think are combinations:
- double buffering & no v-sync = screen tearing as front buffer and back buffer can be switched before monitor has finished displaying front buffer

- double buffering & v-sync = no tearing, drop in FPS as GPU has to wait for monitor to finish displaying

- triple buffering & v-sync (DirectX's circular flipping) = no tearing, introduces lag as GPU can complete draw on to both back buffers (and then wait), but buffers are send to monitor in fixed order (in that case old frame is displayed when there is already a completed new frame waiting)

- triple buffering & v-sync (with bouncing back buffers as Anandtech describes) = no tearing, no additional lag (if GPU completes drawing on both back buffers, it starts drawing new frame instantly & overrides older back buffer. So there is always only latest frame waiting to be send to monitor (flipped to front buffer))

 

From what I am reading on MSDN, DirectX does not implement last option or it is only DX11 that does (and why it has taken them so long to implement this)?

Edited by zz2

Share this post


Link to post
Share on other sites

So why don't DirectX games use triple buffering when v-sync is enabled?

 

If i understand correctly circular pattern of switching buffers in chain described on MSDN, circular flipping process introduces additional latency, which is not the method of bouncing between two back buffers (while front buffer is sent to monitor) that Anandtech described.

 

 

When a flipping chain contains a front buffer and more than one back buffer, the pointers are switched in a circular pattern, as shown in the following diagram.

IC511449.png

http://msdn.microsoft.com/en-us/library/windows/desktop/bb173393%28v=vs.85%29.aspx

http://msdn.microsoft.com/en-us/library/windows/hardware/ff570099%28v=vs.85%29.aspx

EDIT: v-sync should be enabled with triple buffering to prevent tearing

here is what I think are combinations:
- double buffering & no v-sync = screen tearing as front buffer and back buffer can be switched before monitor has finished displaying front buffer

- double buffering & v-sync = no tearing, drop in FPS as GPU has to wait for monitor to finish displaying

- triple buffering & v-sync (DirectX's circular flipping) = no tearing, introduces lag as GPU can complete draw on to both back buffers (and then wait), but buffers are send to monitor in fixed order (in that case old frame is displayed when there is already a completed new frame waiting)

- triple buffering & v-sync (with bouncing back buffers as Anandtech describes) = no tearing, no additional lag (if GPU completes drawing on both back buffers, it starts drawing new frame instantly & overrides older back buffer. So there is always only latest frame waiting to be send to monitor (flipped to front buffer))

 

From what I am reading on MSDN, DirectX does not implement last option.

 

What you're describing here is D3DSWAPEFFECT_FLIP and that's not the only swap effect available; D3D does expose other ways of handling the buffer swap operation, such as discard or copy.  Flip is described as follows in the documentation:

 

 

The swap chain might include multiple back buffers and is best envisaged as a circular queue that includes the front buffer. Within this queue, the back buffers are always numbered sequentially from 0 to (n - 1), where n is the number of back buffers, so that 0 denotes the least recently presented buffer. When Present is invoked, the queue is "rotated" so that the front buffer becomes back buffer (n - 1), while the back buffer 0 becomes the new front buffer.

 

And if you read further down the page you're referencing (in your first link), you'll see the following note: "The discussion above applies to the commonly used case of a full-screen swap chain created with D3DSWAPEFFECT_FLIP."  You can't really extrapolate this to a general behaviour as it's explicitly documented as only applying in one particular case.

 

Your second link refers to DirectDraw surfaces and as such is seriously out-dated information; DirectDraw surfaces used for buffer swapping haven't been relevant since D3D7.

 

At this point I'm really not sure what you're getting at.  You want to know why Microsoft made a decision (which they didn't actually make) - ask Microsoft.  You want to know why some games implement things a certain way - ask the developers of those games.  Otherwise your posts are reading to me as "a rant disguised as a question" I'm afraid.

Share this post


Link to post
Share on other sites

I don't know of any games that disable triple buffering when VSYNC is used.

 

I didn't cath on to that part of the article, but I don't see how "bouncing" two back buffers onto a third back buffer is any diffferent from sequencing two or three back buffers when it comes to performance. Buffering is just that: buffering. It has nothing to do with the way hardware presents frames to the screen.

 

So I second mhagain's opinion that the article is mostly bogus.

 

If GPU lag is your concern, then use DXGI_SWAP_EFFECT_SEQUENTIAL and DXGI_PRESENT_RESTART - it eliminates the GPU wait when a new frame needs to be presented and the frame queue is full. In this case, you don't even need three buffers - one is sufficient.

 

As for flipping (in contrast to blitting) backbuffers onto the screen - it was available in D3D9, then it was disabled in D3D10&11 and it was only brought back in D3D11.1. Only MS knows why. So the only latency that a D3D10/11 swapchain has is from the fact that they use blitting instead of flipping.

Share this post


Link to post
Share on other sites

I am sorry about outdated link, I didn't check category. It was actually in top two results on MSDN when I searched for triple buffering and at the end of the document it said "Build date: 10/14/2013" so I thought article is current.

 

I am still learning on the subject. And there is a lot of contradicting information and scarce official resources that would go into detailed comparisons between techniques. I am asking this from two perspectives: as an user and as a indie developer.

 

As an user I am trying to understand why so many games have problem, that with v-sync enabled framerate will be halved when fps is below monitors refresh rate. What is the reason they don't use triple buffering? Why do technology such as Adaptive V-Sync even exist then if there is triple buffering (is it purely a marketing gimmick)?

 

As I developer, I would first like to learn about this (pros and cons), why it is so challenging to get it right, before tying to implement it.

 

If GPU lag is your concern, then use DXGI_SWAP_EFFECT_SEQUENTIAL and DXGI_PRESENT_RESTART - it eliminates the GPU wait when a new frame needs to be presented and the frame queue is full. In this case, you don't even need three buffers - one is sufficient.

I though minimum of two buffers are needed. One front buffer and one back buffer. How would only one buffer work?

 

You want to know why Microsoft made a decision (which they didn't actually make) - ask Microsoft. You want to know why some games implement things a certain way - ask the developers of those games.

Considering I don't know anyone at Microsoft or any of those game developers is it wrong to ask for your insight on this topic on this forum? Yes I made some wrong assumptions and I am sorry about that. I don't know what else to say.

 

Can anyone explain in a little more detail how triple buffering is correctly and set up in DirectX (with v-sync and without additional lag) (preferably in DirectX 9 if possible). DXGI_PRESENT_RESTART is it then, but only for DX11?

Edited by zz2

Share this post


Link to post
Share on other sites

I don't see how "bouncing" two back buffers onto a third back buffer is any diffferent from sequencing two or three back buffers when it comes to performance. Buffering is just that: buffering. It has nothing to do with the way hardware presents frames to the screen.


The difference comes from synchronization timings I think. First buffer in sequence is front buffer. That means that buffer sequence cannot be flipped in circular fashion if monitor has not finished presenting front buffer. So rendering has to be halted in case when both back buffers are completed before monitor refresh is completed. With bouncing, only the two back buffers can be flipped, without affecting front buffer (same cannot be done when flipping all three buffers at once in circular fashion).
This is how I think it works. I may be wrong. Many users report increased mouse lag when using triple buffering in some games, I guess this circular flipping is the reason? Edited by zz2

Share this post


Link to post
Share on other sites
Triple buffering exists for two reasons:
  • To avoid the FPS drop when VSync is enabled (unless both GPU & CPU take less than 16ms to render).
  • To let the CPU return immediately in case one frame was taking too long for the GPU to process.
In both cases, turning off VSync makes the triple buffering irrelevant:
  • When VSync is off and CPU/GPU took more than 16ms; the buffers are still flipped and tearing appears (unless the rendering time was a multiple of 16ms).
  • When VSync is off, the CPU still returns immediately from submitting the commands to the GPU; the screen is flipped and tearing happens.
Triple Buffer + No Vsync makes no sense (you can try it, but it won't change much); Triple Buffer + VSync should deliver similar performance to Double Buffer + No VSync; except there is no tearing but trading off a frame of latency. There is no way to avoid the additional frame lag.
 
What Anandtech is saying with its "alternative" is basically just a form of frame-skipping: When the CPU is too fast (or the GPU is too slow); the CPU may be issuing 4 frames, but the GPU is still presenting the front buffer, the 1st backbuffer is waiting to be presented, and the 2nd backbuffer is also waiting; and the CPU wants a 4th one.
So, instead of using quadruple buffering or waiting, the Anandtech suggest the method of dropping the contents of the 2nd backbuffer and replace it with the contents of that 4th frame.
So the monitor will end up showing frames 1, 2, 4; instead of showing 1, 2, 3 ... wait ... 4.
Forcing frame 4 come after 2 leads to stuttering.
 
This is a terrible technique, it only works for the cases when the 5th frame will be very CPU intensive thus dispatching the 4th now instead of waiting gives a lot of time to process that heavy 5th frame.
But it is pointless anyway because if you have such bad fps micro-spikes you have a bigger issue; and besides it means the CPU is sending frames faster than the monitor's refresh rate; which is pointless and only leads to stutter.
The other extreme is when the GPU is taking too long. But if the GPU takes too long all the time, then triple buffer won't help much; and you should be thinking of plain old frame skipping (regardless of buffer counts).
 
Another issue with the technique is that if the 4th frame is too GPU heavy, it won't be ready by the time it should be presented (that is, after frame 2), however had they waited, it could make it in time because there is one frame more in the queue (frame 3 comes after 2, then comes the 4th). Like I said, a terrible technique.
 
 
The Anandtech article says their technique is the real Triple Buffer; while DX implements a fake render ahead queue that shouldn't be called Triple Buffering. Well, the article is wrong. Their technique is not "Triple Buffer"; it's a form of useless frame-skipping that introduces stutter, increases CPU power consumption, but is still able to avoid tearing and has as much visible lag as the "render ahead" method. Edited by Matias Goldberg

Share this post


Link to post
Share on other sites

Something that I forgot to mention, is that if we read the 2nd page of the article he achieves an internal render loop of 3.3ms per frame with his frame-skipping triple-buffer; thus minimizing latency (what the author wanted to achieve), no tearing (because of the VSync), but sacrificing stuttering (something the author forgets to mention).

 

The author compares the double buffering with the best case of his frame-skipping triple-buffer (when each frame takes exactly 3.33ms; which is a multiple of 16.66ms thus no stuttering will happen; also a frame time of 3.33ms is very hard to achieve in real games) without even comparing render-ahead triple-buffer.

 

The real way to achieve low latency input is to detach the logic & physics loop from graphics and put them in another thread. Thus input, logic & physics can run at 3.3ms while rendering happens at 16.66ms.

The method in the article just forces the GPU to internally draw at 3.33ms to achieve a similar effect.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!