Sign in to follow this  
ciel123

Glitches with flip model swap chain

Recommended Posts

I have a program where I used a bitblt model swap chain (DXGI_SWAP_EFFECT_DISCARD, the default used by most samples), and it worked fine.

 

But now I want to use a flip model swap chain (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL), and I'm getting some glitches. Basically, it keeps rendering a pair (2) of old frames over and over, and the two frames only get updated at random times. (Unfortunately, posting a screenshot wouldn't help because it only shows a normal frame.)

 

I've tried just about every relevant combination of the two parameters for IDXGISwapChain::Present, particularly with the flags DXGI_PRESENT_RESTART and DXGI_PRESENT_DO_NOT_SEQUENCE, but nothing changes.

 

If it matters, the program also uses Direct2D. I did see this MSDN page ( https://msdn.microsoft.com/en-us/library/windows/desktop/hh706346(v=vs.85).aspx ), which says "Use flip model in an HWND that is not also targeted by other APIs, including DXGI bitblt presentation model, other versions of Direct3D, or GDI." But it doesn't mention Direct2D, so I'm not sure if this could be the problem.

 

A couple of other points:

 

- I create the swap chain with two buffers, as the debug layer told me to.

- Direct3D 11.1, Windows 8.1, Visual Studio 2013

Share this post


Link to post
Share on other sites

I did read about that but, how do I rebind them? The back buffers are not being used with an ID3D11RenderTargetView, but with an ID2D1RenderTarget, so I can't use ID3D11DeviceContext::OMSetRenderTargets to bind it. Sorry if it's a silly question, I'm still learning.

Share this post


Link to post
Share on other sites

Well I'm using D2D to do all the drawing but I do create a D3D device and swap chain (for now just to set fullscreen mode). The D2D render target is created with ID2D1Factory::CreateDxgiSurfaceRenderTarget, which indeed binds it to the swap chain's back buffer. But I can't find any method to rebind it like you can with D3D render target views and OMSetRenderTargets.

 

About the EndDraw call, yes I call it. My render method looks basically like this:

void Render()
{
    m_pRenderTarget->BeginDraw();
    m_pRenderTarget->Clear(m_backgroundColor);

    // ... draw calls here ...

    HRESULT hr = m_pRenderTarget->EndDraw();
    ThrowIfFailed(hr);

    hr = m_pSwapChain->Present(0, 0);
    ThrowIfFailed(hr);
}

Share this post


Link to post
Share on other sites

I think I solved it. Apparently the glitch was caused because sometimes I only drew part of the window. If I always draw the entire window (starting with a ID2D1RenderTarget::Clear call), it works fine. I guess with a flip model swap chain, I always have to draw the entire window?

 

There's still another issue. The program has a menu bar, but any coordinates I pass to D2D draw calls are being treated as relative to the window's client area (as if the window didn't have a menu bar). It doesn't draw on top of the menu bar, but rather, the menu bar obstructs whatever is drawn below it. This doesn't happen with the DXGI_SWAP_EFFECT_DISCARD swap chain.

 

The easy solution is to create the swap chain with the height of the window's client area (not including the height of the menu bar), and position it below the menu bar. Is there a way to do the latter (reposition the swap chain, or the swap chain's back buffers)?

Share this post


Link to post
Share on other sites

For your first problem, you'd have that issue anytime you have multiple buffers in your swapchain, such as a regular SEQUENTIAL swapchain with 2 buffers or a fullscreen DISCARD swapchain. Additionally, you can't rely on a DISCARD swapchain preserving its contents - the DISCARD implies they may have been discarded.

 

As an alternative workaround for that, you can use partial presentation. See this article on DXGI_PRESENT_PARAMETERS.

 

For the menu bar issue, this is a difference between the blt models (DISCARD/SEQUENTIAL) and flip model swapchains. WIth blt, the menu bar and DX contents end up in the same surface. With flip, you provide the window contents, and the compositor adds the menu later. There is no way to reposition the swapchain buffers - they replace the entire window contents.

 

Can you describe how the coordinates were treated with DISCARD? This might be a difference I'm not sure we've really payed attention to.

Share this post


Link to post
Share on other sites

With DISCARD, the coordinates are treated how you'd expect them to: with the top left coordinate (0, 0) starting just after the menu bar.

 

Another thing I noticed with FLIP_SEQUENTIAL is, sometimes when I resize the window (manually while the app is running), it will sometimes render correctly, as it does with DISCARD. But as soon as it's rendered for any other reason, it goes back to drawing below the menu bar.

 

Anyway, thanks for your continued support. I feel like I'm becoming annoying at this point, but these APIs just have so many quirks, I wish they'd just work out of the box...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this