Proposed swapChain->Present(0, 0) blocking

  • Tuesday, July 31, 2012 2:10 PM
     
      Has Code

    <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
    •  

All Replies

  • Wednesday, August 01, 2012 8:25 PM
     
     

    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:36 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
    •  
  • Monday, August 13, 2012 2:52 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.

  • Wednesday, August 15, 2012 12:13 AM
    Moderator
     
     Proposed

    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/

  • Thursday, August 16, 2012 10:25 AM
     
      Has Code

    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 11:14 PM
    Moderator
     
     

    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/

  • Saturday, August 18, 2012 11:57 AM
     
      Has Code

    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); } }

    }




  • Monday, August 20, 2012 7:27 PM
     
     

    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 10:27 PM
    Moderator
     
     

    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/