Advertisement

SwapChain in DX12

Started by April 08, 2019 07:14 AM
2 comments, last by Obliique 5 years, 10 months ago


Hi. I have been programming dx12 for nearly 6 months now and I think I still have a misuderstanding on swapchain flags and how they affect presentation. please correct me if I am wrong. My understanding is the following:

- DX12 only supports two swap effect flags with the flip model. ie DXGI_SWAP_EFFECT_FLIP_DISCARD and DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL . My understanding is that both these flags don't need a redirection surface hence the contents of backbuffers are displayed to the screen directly from app. The DXGI_SWAP_EFFECT_FLIP_DISCARD flag allows for an option were if the presentation queue is full and the call to IDXGISwapChain::Present() is made, whatever is at the end of this queue is discarded without ever making it to the screen, is this correct? The DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL inserts the frame to be presented at the end of the queue. does this mean that the queue can only contain one buffer at a time?

- Both DXGI_SWAP_EFFECT_FLIP_DISCARD and DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL dont support multisampling. So i have had to set my sample count to 1 and sample quality to 0 for my swapchain desc structure. My question is how would we add support for multisampling like 4xMSAA if these are the only flags supported in dx12. I have seen some usages were these were set to sample count > 1 and quality level queried which leaves me confused. I still have'nt tested multisampling as I don't use them in my experimental engine.

- The waitable Swapchain options blocks present thread from the calling application until the specified time to wait on elapses. But why would we explicilly specify wait time on swapchain?

- tearing support is included by the GPU vendor. So this allows for options like freesync and gsync to be utilized. I am using an intel gpu and I don't really know how to test this.

- It isn't a requirement for apps to toggle vsync-on on a windowed app. This is also confusing. Won't screen tearing happen anyway if my app is not synchronized with my next screen vertical blank?

1. FLIP_SEQUENTIAL simply means that every buffer in your swapchain is guaranteed to maintain its contents after present. Therefore it is valid to use previous buffers as input to the current frame (e.g. a fully-rendered buffer 0 can be used as input to buffer 1). FLIP_DISCARD means that after present, the surface doesn't need to maintain its contents, which can enable some optimizations. Always prefer this unless you need the SEQUENTIAL semantics. Your description of queueing is based on the sync interval: 1 ensures that every frame will be on-screen for a VSync, while 0 enables frames to be discarded if newer frames are available. 0 with the ALLOW_TEARING flags enables frames to switched in the middle of a VSync.

Regarding your comments around a redirection surface: back in the olden days before DWM (i.e. Windows XP, or Win7 with Aero Basic theme), an app without a redirection surface would copy their contents straight into the on-screen surface by calling present. An app with a redirection surface would copy it to that surface instead, which would be 'composed' into the screen. These days, a blt-model swapchain always has a redirection surface with DWM enabled. A flip model swapchain does not, and instead takes advantage of the fact that DWM is always present, and simply tells DWM to use its back buffers as window contents directly, instead of copying them into the window surface - this removes a copy. But more interestingly, there are additional optimizations, where the DWM can skip composition and just display that app's surface directly, enabling lower latency and higher performance, up to identical performance with fullscreen exclusive modes, but with seamless fallback to composition.

2. To do multisampling, you can use a multisampled intermediate render target, and use ResolveSubresource to get the contents into the back buffer.

3. Normally, the swapchain blocks in the Present call when there are 3 frames currently outstanding. It's possible that the app might block sooner than that on fences depending on desired queuing and memory management. The waitable object swapchain enables the app to block at a different point in the frame (e.g. at the beginning before polling for input), to control how many frames can be queued with SetMaximumFrameLatency, and to poll for frames rather than waiting by using a timeout of 0.

4. Tearing support is based on OS version. If you're running an up-to-date OS, you probably have support for it. If you use the ALLOW_TEARING flags, and are on a system with GSync/FreeSync (generically variable refresh rate, or VRR) then it will be able to be used.

5. Like I described above, when your app calls present, it simply notifies the OS that new contents are ready. Depending on the mode of the swapchain, your window position, etc, you may end up either notifying the DWM, queueing your frame to be flipped, or performing a tearing update of your window on the screen -- even if your window is only covering a small portion of the screen on systems with multiplane overlay support.

Advertisement

Thank you so much for taking the time to respond . This has cleared things up for me . I read carefully and will consider these options when I refactor my code. 

This topic is closed to new replies.

Advertisement