XNA Creators Club Online
Page 1 of 1 (8 items)
Sort Posts: Previous Next

DXGI SwapChain buffer management

Last post 1/8/2010 8:04 AM by Nazarov. 7 replies.
  • 11/12/2009 12:01 PM

    DXGI SwapChain buffer management

    Hello,

    Being new to D3D I'm trying to understand the internal logic of the DXGI SwapChain buffer management (have already read the SDK docs but to no avail). I'm writing a video CG application that uses GPU acceleration and I'm trying to achieve the following: A render thread fills (renders to) the back buffers asynchronously as fast as it can and the graphics hardware presents and swaps the buffers locked to the screen refresh rate. In that scenario the hardware imposes the frame rate right?. Also how should I go about presenting 25 FPS PAL video to a 60Hz SwapChain? If I fill the back buffers asynchronously, how can i distinguish between buffers that have already been presented and those that haven't? Alternatively, if the only way to swap the chain is to call SwapChain.Present() from a user thread, how can I make sure that the thread receives a timeslot from the kernel on time, so that no frame drops occur?

    That's a lot of questions, but I hope someone knowledgeable may share some insight.

    Thanks in advance!
    --
    Vassil Nazarov
  • 12/9/2009 1:14 AM In reply to

    Re: DXGI SwapChain buffer management

    In the simplest case, you can just render as fast as you can and call IDXGISwapChain::Present with SyncInterval equal to 1. That way each frame will stay on the screen for one vsync (or more, if app cannot render on time) and Present will throttle execution when there are too much GPU work already scheduled, so GPU speed and vsync will impose frame rate.

    To do frame conversion from 25Hz to 60Hz you can issue some presents with DXGI_PRESENT_DO_NOT_SEQUENCE flag which will make same frame to show on the screen for one extra vsync. That way you can make some frames be on screen for 2 or 3 vsyncs, thus making picture change 25 times per second without extra rendering work.

    Now, there's no perfect solution yet for checking whether frames reach the screen on time (IDXGISwapChain::GetPresentStatistics doesn't support windowed presentation), so you've got to just check on the CPU whether rendering is not too late and mitigate that somehow (skip some frames, do less work, increase thread priority, etc).


  • 12/11/2009 1:01 PM In reply to

    Re: DXGI SwapChain buffer management

    Simon Kozlov:
    In the simplest case, you can just render as fast as you can and call IDXGISwapChain::Present with SyncInterval equal to 1. That way each frame will stay on the screen for one vsync (or more, if app cannot render on time) and Present will throttle execution when there are too much GPU work already scheduled, so GPU speed and vsync will impose frame rate.


    That's exactly what I want to avoid. I need a separate presentation thread with a steady presentation rate and a separate rendering thread. So that I may have a heavily fluctuating rendering rate but a steady presentation rate of 60 Hz. The question is how do I manage the backbuffers? I want my rendering thread to render a number of buffers ahead of presentation and wait for an event that a next buffer is available for filling. Thus I may have a SwapChain of 16 buffers and if all of them are prefilled, I only need to call Present 16 times to present them. The problem is that when the system is heavily loaded with other tasks, the presenting thread isn't guaranteed to receive a timeslot from the kernel to call Present() on time and a frame-drop may occur.
  • 12/18/2009 11:04 PM In reply to

    Re: DXGI SwapChain buffer management

    Right, that's exactly why presentation is handled by DXGI and OS in general. In fact, it gets even more complicated due to asynchronous nature of GPU work - app does't know when GPU completed the work, making buffer available for presentation.

    Let me clarify how exactly current presentation model works (assuming you use SyncInverval = 1).
    When you Present frames, these frames go into present queue. Every vsync, OS takes one frame from the queue and displays it on a screen until next vsync. If the queue is empty, only then previous content stays on the screen for extra vsync. This way, app has some flexibility in how fast it adds data to the queue - as long as queue is not empty, presentation is smooth (empty queue usually means application cannot process frames fast enough even with buffer). Since presentation is handled by OS, app doesn't need to worry about getting timeslot in the good time, etc.

    Note that on both Vista and Win7 there is limitation on effective queue length in windowed mode when SyncInterval > 0.
  • 12/21/2009 9:01 AM In reply to

    Re: DXGI SwapChain buffer management

    Simon Kozlov:
    Let me clarify how exactly current presentation model works (assuming you use SyncInverval = 1).
    When you Present frames, these frames go into present queue. Every vsync, OS takes one frame from the queue and displays it on a screen until next vsync. If the queue is empty, only then previous content stays on the screen for extra vsync. This way, app has some flexibility in how fast it adds data to the queue - as long as queue is not empty, presentation is smooth (empty queue usually means application cannot process frames fast enough even with buffer). Since presentation is handled by OS, app doesn't need to worry about getting timeslot in the good time, etc.


    This all sounds very nice indeed and that's exactly what I was hoping to achieve but unfortunately I observe very different behavior. When I call Present with SyncInverval=1, it doesn't return until the next VSync. The thread blocks for 16 ms. just waiting for the Present function to return. If it were returning asynchronously, I'd have the chance to fill some more backbuffers during these 16 ms. Alternatively, If I needed to fill the backbuffers asynchronously from another thread, how do I keep track of which buffers have already been presented and thus available for filling and which are still waiting in the queue to be presented? And how would I add a backbuffer to the presentation queue without calling Present, because it would block the calling thread?

    What am I missing here?
  • 12/23/2009 7:47 AM In reply to

    Re: DXGI SwapChain buffer management

    Simon Kozlov:
    Note that on both Vista and Win7 there is limitation on effective queue length in windowed mode when SyncInterval > 0.


    Simon,

    Aha, that's what I've been missing. This limitation seems to be 1 or 2 buffers (on Windows 7, DX 10.1, Radeon HD 3400 and 5800). Indeed in fullscreen mode the swapchain behaves as you describe. How can the same behavior be achieved in windowed mode with at least 3 or 4 buffers? Any hints?

    Thanks for your help Simon, it's been very useful!
  • 1/6/2010 8:53 PM In reply to

    Re: DXGI SwapChain buffer management

    Right, current limitation is no more than 2 frames could be in flight in windowed mode with SyncInterval > 0.

    D3D9Ex in Win7 supports new way of windowed presentation called Flip Model which allows buffering more frames and has better performance characteristics in general (more details at http://msdn.microsoft.com/en-us/library/ee890072(VS.85).aspx ), but it's not available for DXGI and D3D10+.

    This is something we're looking to improve in the future.
  • 1/8/2010 8:04 AM In reply to

    Re: DXGI SwapChain buffer management

    Simon Kozlov:
    D3D9Ex in Win7 supports new way of windowed presentation called Flip Model which allows buffering more frames and has better performance characteristics in general (more details at http://msdn.microsoft.com/en-us/library/ee890072(VS.85).aspx ), but it's not available for DXGI and D3D10+.


    Thanks again Simon!

    This info comes just at the right time as a life saver for another major project of ours that's based on D3D9. We have a digital signage product that's driving 6 displays on 3 adapters in a single machine. So fare this arrangement has been working satisfactory (more or less) in fullscreen mode under XP. Windowed mode has never been an option with D3D9 because of the lack of buffering. However, Vista and Win7 introduced a limitation that doesn't allow more than 1 fullscreen display in a machine with multiple adapters while still lacking performance in windowed mode D3D9. This has been a no go situation for us so fare, so hopefully now D3D9Ex may provide the solution with a performant windowed mode.
Page 1 of 1 (8 items) Previous Next