Skip to main content
gamedev.net
🔒 Locked

Using multiple back buffers

Started by napis 0 replies 1k views
Original Post
napis
napis
This is my problem: In order to avoid tearing, PresentationInterval in D3DPRESENT_PARAMETERS should be set to D3DPRESENT_INTERVAL_ONE instead of D3DPRESENT_INTERVAL_IMMEDIATE causing the Present(...) command to wait for vertical sync. However, this makes the thread calling Present to wait idle for vertical sync. This time, of course, could be spent to something more useful. Computers need no rest! There are two ways I come up with to solve this problem. The first one is to estimate the vsync time based on the video refresh rate, interrupt rendering the next frame and call Present just before vsync. The second one is to create a separate thread that calls Present allowing the main thread to continue rendering the next frame on another buffer. This, of course, assumes there is a surface independent of Present(...) call where the rendering could be done. I find the first solution more appealing. It is ridiculously easy to add multiple back buffers to the D3D device default swap chain - you only have to specify BackBufferCount = 2 or 3 in the D3DPRESENT_PARAMETERS structure when creating a surface. However, I found out that a call to Present actually changes the back buffers received with devices GetBackBuffer command. After Present(..), the pointer referencing to the back buffer will change to refer to the *current* second back buffer, instead of pointing to the *previous* (current first) back buffer (Present(..) shows the first back buffer to screen and makes the second back buffer to first). This, of course, means that if a thread calls to Present in the middle of everything, rendering might be done to two different surfaces, which of course is not good. Neither do I know about the thread safety of direct3D. I wonder if there is any standard or less ugly solution to this problem?
Staffan E
Staffan E
Set PresentationInterval in D3DPRESENT_PARAMETERS to D3DPRESENT_INTERVAL_IMMEDIATE and then use a loop that checks the following:

D3DRASTER_STATUS d3drs;

g_pD3DDevice->GetRasterStatus(&d3drs);
if (d3drs.InVBlank)
{
Present();
}
else
{
//Render some to the next BB
}

Then you will control the presentation interval manually. And there is no risk that presentation causes pointers to change during rendering.

Generally I have only bad experience of using multithread in rendering. Ofttimes I lost more performace on switching between threads than I gained from effective rendering.
Hack my projects! Oh Yeah! Use an SVN client to check them out.BlockStacker

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.