Skip to main content
GameDev.net gamedev.net
🔒 Locked

Swap chain->Present() performance

Started by ScottLacey Dec 30, 2002 at 6:29 PM 0 replies 4.9k views
Original Post
ScottLacey
ScottLacey
Hi, I am working on an MFC app that has multiple windows in them kinda like a 3d modeling program. I first started with just one window to see if i could do it. I used the MFCFog example in the SDK as a guide. I got it, it worked fine and i was getting about 1500 fps. So i added another window, I did this by creating an aditional swapchain (Actually i created 2 swap chains one for each render target, I dont know if this is right or not because when i created the device i passed it the HWND to my first render target m_hwndRendTarg1 for example, then i created an additional swap chain and passed the m_hwndRendTarg1 again, and created an additional swap chain and passed it the next render target to it m_hwndRendTarg2 for example). Now when i did this it worked the way it was supposed to each window was rendering the right stuff but my framerate dropped to 50 fps. 50 fps isn''t bad but if there was that much performance drop by just adding one extra render target thats a problem. The scene is not very complex at all its just drawing a grid of about 200 vertices. I tracked down the slow down using the profiler to the SwapChains->Present() method. I am using DX9. Below is the code if anyone knows what the problem is or if there is a better way to do this please comment, Thank you.
  
void CGraphView::OnInitialUpdate()
{
// this is my MFC View class OnInitialUpdate()


// Get the handle to the 1st render target.

m_hwndRenderWindow = GetDlgItem(IDC_RENDER_FRAME)->GetSafeHwnd();

// Get the handle to the 2nd render target.

m_hwndRenderWindow2 = GetDlgItem(IDC_RENDER_FRAME2)->GetSafeHwnd();

// Create the device using the Example Framework class

// CD3DApplication

CD3DApplication::m_hWnd = m_hwndRenderWindow;

// Create the device passing it the HINSTANCE handle

// of our main app.

CD3DApplication::Create( AfxGetInstanceHandle() );

// The seperate D3DPRESENT_PARAMETERS for each swap chain.

ZeroMemory(&m_d3dppSwapChain, sizeof(D3DPRESENT_PARAMETERS) );
ZeroMemory(&m_d3dppSwapChain2, sizeof(D3DPRESENT_PARAMETERS) );
	
// Get the current display mode for the desktop.

D3DDISPLAYMODE mode;
m_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);

// Setup the presentation paramaters for the first swapchain.

m_d3dppSwapChain.Windowed = TRUE;
m_d3dppSwapChain.SwapEffect = D3DSWAPEFFECT_COPY;
m_d3dppSwapChain.BackBufferFormat = mode.Format;
m_d3dppSwapChain.hDeviceWindow	= m_hwndRenderWindow;

// Create the first swapchain	

m_pd3dDevice->CreateAdditionalSwapChain(&m_d3dppSwapChain, &m_pSwapChain);

// Setup the presentation parameters for second swapchain.

m_d3dppSwapChain2.Windowed = TRUE;
m_d3dppSwapChain2.SwapEffect = D3DSWAPEFFECT_COPY;
m_d3dppSwapChain2.BackBufferFormat = mode.Format;
m_d3dppSwapChain.hDeviceWindow	= m_hwndRenderWindow2;

// Create the 2nd swap chain

m_pd3dDevice->CreateAdditionalSwapChain(&m_d3dppSwapChain2, &m_pSwapChain2);
}

// The main render function called from the main apps

// OnIdle() function.

HRESULT CGraphView::Render()
{
    // Create a temporary surface to hold the returned

    // suface from GetBackBuffer()

    LPDIRECT3DSURFACE9 pSurface = NULL;
    
    if( SUCCEEDED( m_pd3dDevice->BeginScene() ))
    {
        // Render the 1st viewport

        m_pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface);
	m_pd3dDevice->SetRenderTarget(0, pSurface);
			
	m_pd3dDevice->Clear( 0, NULL,D3DCLEAR_TARGET            |D3DCLEAR_ZBUFFER, D3DCOLOR(0x000000), 1.0f, 0L);
	
        // Reset the world matrix

	D3DXMATRIXA16 matWorld;
	D3DXMatrixIdentity(&matWorld);
	m_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);
	
	// Draw the grid

	m_pd3dDevice->SetFVF( D3DFVF_GRIDVERTEX );
	m_pd3dDevice->SetStreamSource( 0, m_pGridVB, 0, sizeof(GRIDVERTEX) );
	m_pd3dDevice->DrawPrimitive( D3DPT_LINELIST, 0, m_dwNumGridVerts/2 );

        pSurface->Release();

        // Render the 2nd viewport, For the purposes of this

        // example i am rendering the same scene as the other

        m_pSwapChain2->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface);
	m_pd3dDevice->SetRenderTarget(0, pSurface);
			
	m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 
			D3DCOLOR(0x000000), 1.0f, 0L);
	// Reset the world matrix

	D3DXMATRIXA16 matWorld;
	D3DXMatrixIdentity(&matWorld);
	m_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);
	
	// Draw the grid

	m_pd3dDevice->SetFVF( D3DFVF_GRIDVERTEX );
	m_pd3dDevice->SetStreamSource( 0, m_pGridVB, 0, sizeof(GRIDVERTEX) );
	m_pd3dDevice->DrawPrimitive( D3DPT_LINELIST, 0, m_dwNumGridVerts/2 );
        pSurface->Release();

	m_pd3dDevice->EndScene();
    }

    m_pSwapChain->Present(NULL,NULL,NULL,NULL,NULL);
    m_pSwapChain2->Present(NULL,NULL,NULL,NULL,NULL);
	
    return S_OK;
}
  
I tried remarking out the second render window and still only got 50 fps. I moved the one call to m_pSwapChain->Present() to a seperate function and ran the profiler on it and found Function Time takes 9395.278. Anyone have any ideas? Sorry this post was so long.
ScottLacey
ScottLacey
Ok nevermind I figured it out. I will explain just in case someone else has this problem.

I thought that the PresentationInterval in the D3DPRESENT_PARAMETERS struct wouldn''t matter because I was running in a window. As it turns out though it does matter. When i added

m_d3dppSwapChain.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

to both of my D3DPRESENT_PARAMETERS structures associated with my swapchains my framerate went up to 1300 fps.

There was some changes in DX9 where they removed the
D3DSWAPEFFECT_COPY_VSYNC and D3DPRESENT_RATE_UNLIMITED.

and added the D3DPRESENT_INTERVAL_IMMEDIATE member of D3DPRESENT_PARAMETERS.

they alse renamed D3DPRESENT_PARAMETERS.FullScreen_PresentationInterval to PresentationIntervals.

Topic Locked

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

Sign in to reply to this topic.