locked
swapChain->Present(0, 0) blocking

    Question

  • <EDIT>

    I'm basically just looking for a way to not have Present block until vsync.  What can I do to my swap chain or elsewhere to do this?

    </EDIT>

    With the default direct3d metro app template in VS Express 2012, swapChain->Present(0, 0) is blocking for vsync.  (I put a timer on it, and it is taking 1/60th of a second for every call.)

    A little bit of research seems to indicate that this might be because the swap chain is using flip sequential for the swap effect:

    // Create a descriptor for the swap chain.
            DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
            swapChainDesc.Width = 0;                                     // use automatic sizing
            swapChainDesc.Height = 0;
            swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;           // this is the most common swapchain format
            swapChainDesc.Stereo = false; 
            swapChainDesc.SampleDesc.Count = 1;                          // don't use multi-sampling
            swapChainDesc.SampleDesc.Quality = 0;
            swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
            swapChainDesc.BufferCount = 2;                               // use two buffers to enable flip effect
            swapChainDesc.Scaling = DXGI_SCALING_NONE;
            swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // we recommend using this swap effect for all applications
            swapChainDesc.Flags = 0;

    I basically don't want Present to block until vsync, but just throw away any queued(?) backbuffers and update it with the most recent version and then return.  (If I'm totally misunderstanding how it works, a link to a good tutorial/overview would be very helpful to me--I come from a c#/xna background.)

    Thanks!

     
    • Edited by Mike Muir Wednesday, August 01, 2012 6:03 PM clarified the question
    Tuesday, July 31, 2012 2:10 PM

All replies

  • Metro apps can only use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL.  With this model, if you pass a syncInterval of 0 to Present() it will automatically discard frames if a newer frame is queued.  This should be essentially the same as the behavior you'd previously get with D3DSWAPEFFECT_FLIPEX + D3DPRESENT_FORCEIMMEDIATE, which sounds like what you're looking for if I'm understanding correctly.  You can still render at arbitrary frequency, but it in general it's not useful to present at a higher frequency than the hardware supports since a) the display can only update that fast anyway, and b) it would unnecessarily increases power consumption and decrease battery life on mobile devices.

    There's some further info here:

    http://msdn.microsoft.com/en-us/library/windows/desktop/hh446797(v=vs.85).aspx

    Wednesday, August 01, 2012 8:25 PM
  • I actually am passing a syncInverval of 0 to Present(), but it still takes 1/60th of a second, so I can only assume it's waiting for vsync.

    I only use this behavior in my debug/development environment to see the impact of changes to the framerate.  If there's a better approach than this, I'm definitely open to suggestions.

    Thanks!


    • Edited by Mike Muir Wednesday, August 01, 2012 8:40 PM more info
    Wednesday, August 01, 2012 8:36 PM
  • Hi,
    Same problem here...

    I use swapChain->Present(0, 0) but the renderer still waits for VSync (fps : 60).

    Like Mike Muir I find very useful to disable VSyn in debug mode to check performance.

    Any solution ?

    Thanks.

    Monday, August 13, 2012 2:52 PM
  • Hello,

    Try calling Present1 with a zero (0) in the first parameter.

    IDXGISwapChain1::Present1
    http://msdn.microsoft.com/en-us/library/windows/desktop/hh446797(v=vs.85).aspx

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Wednesday, August 15, 2012 12:13 AM
    Moderator
  • Hi James,

    I've tried the following code (using IDXGISwapChain1::Present1), however the renderer still waits VSync. Am I doing something wrong ?

    Thanks

    DXGI_PRESENT_PARAMETERS PresentDesc;
    ZeroMemory(&PresentDesc, sizeof(PresentDesc));
    HRESULT hr =  D3D_swapChain->Present1(0, 0, &PresentDesc);



    Thursday, August 16, 2012 10:25 AM
  • Hello,

    You can use "DXGI_PRESENT_DO_NOT_WAIT" to determine if a previous call is still blocking.

    -James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Thursday, August 16, 2012 11:14 PM
    Moderator
  • Hello again,

    Tell me if I'm wrong but it seems impossible to present frames faster than VSync in Metro Apps.
    Actually Metro style apps MUST use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL for the swap chain.
    When using DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL the SyncInterval parameter of Present1 meens :
    - 0 : Cancel the remaining time on the previously presented frame and discard this frame if a newer frame is queued.
    - n > 0 : Synchronize presentation for at least n vertical blanks.

    Using 0 is useful for discarding previously queued frames but does not permit to present frames to DWM faster then VSync

    DXGI flip model : http://msdn.microsoft.com/en-us/library/windows/desktop/hh706346.aspx
    DXGI_SWAP_EFFECT enumeration : http://msdn.microsoft.com/en-us/library/windows/desktop/bb173077.aspx
    IDXGISwapChain1::Present1 method : http://msdn.microsoft.com/en-us/library/windows/desktop/hh446797.aspx

    To avoid "Present blocking" we can change the Run() function of the Metro Direct3D projet template.
    This is much better for some games because it does not delay input or network response.
    To reduce power consumption move Render() just before Present().

    void Direct3DApp1::Run() { BasicTimer^ timer = ref new BasicTimer(); LARGE_INTEGER Freq; LARGE_INTEGER Time1; LARGE_INTEGER Time2; float PresentDelay = 1.0f / 60.0f; // Must be set close to Vsync interval QueryPerformanceFrequency(&Freq); QueryPerformanceCounter(&Time1); while (!m_windowClosed) { timer->Update(); CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); m_renderer->Update(timer->Total, timer->Delta); // -> Count Render Rate (FPS) here m_renderer->Render(); QueryPerformanceCounter(&Time2); float d = static_cast<float>(static_cast<double>(Time2.QuadPart - Time1.QuadPart) / static_cast<double>(Freq.QuadPart)); if (d >= PresentDelay) { // -> Count Present Rate here m_renderer->Present(); // This call is synchronized to the display frame rate QueryPerformanceCounter(&Time1); } }

    }




    Saturday, August 18, 2012 11:57 AM
  • As it turns out, this is actually discussed in Developing Metro Style Games on the Full Range of Windows 8 Devices from GDC 2012.

    Check out the slide on Calibrating Render Performance.  Basically you are locked to the framerate with present, but you can use deviceContext->Flush() to simulate the present and then check your timing characteristics with an event query.


    Monday, August 20, 2012 7:27 PM
  • Hey guys,

    I think Mike is likely correct but I've unmarked the answers for the time being. I want to make sure there is no confusion. I am checking with the DX architects to verify the expected behavior and any possible workarounds. I'll let you know once I hear back. Keep in mind that these guys are super busy and it may take a few days to hear back.

    Thanks for your patience,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Monday, August 20, 2012 10:27 PM
    Moderator
  • Any response from the DX Architects ? I'd really like to have common code between a desktop app and windows 8 app and have Present work the same for both APIs.


    http://www.facebook.com/relativegames

    Sunday, November 17, 2013 4:27 PM
  • Note that the SwapChain model is one of the areas of difference in a Win32 desktop app vs. a Windows Store app, so Present is definitely an area that is expected to diverge somewhat.

    See Dual-use Coding Techniques for Games

    Have you looked at the newlatency swap chain presentation DXGI 1.3 feature for Windows 8.1?

    Sunday, November 17, 2013 11:48 PM
  • Ok, so is there any way to disable VSync in a Windows 8.0 Metro App ?

    So far the best thing I've been able to get is with this code :

    dxgiDevice->SetMaximumFrameLatency(1) //0 turns the default 3 on
    UINT Flags = DXGI_PRESENT_DO_NOT_WAIT;    
    HRESULT hr = m_swapChain->Present1( 0, Flags, &parameters);

    and using a CoreWindow. I can now get to a max of 120 FPS compared to 60 previously. An improvement for sure, but even in this scenario Present still "waits" even though I passed not wait flag. It's kind of weird to ignore flags like that... I'll look over the 8.1 stuff but I would've wanted more of answer like, is it now possible in 8.1 to disable vsync for real ?


    http://www.facebook.com/relativegames


    Tuesday, November 19, 2013 8:05 PM