multi screen help

Started by
3 comments, last by 8up tuotlo 10 years, 1 month ago

Hi
I'm really new to direct3d and have done lots of googling and have made some progress, but I'm now totally stuck with something and after lots more googling I can't find how this works. I posted this on Xbox live, but as I'm writing for a windows PC I think that was the wrong place

I'm using direct3d9 to render some animations to screen - they are nothing fancy, just geometric shapes and text, however, they do have to be rendered as the screen refresh rate and they need to avoid tearing which is why I'm using direct3d. The other thing is that I need to render to two screens each with different refresh rates and render at their particular refresh rate independently. My test case is my laptop with it's screen at 60 Hz, plus an external monitor at 75 Hz.

My progress so far is that I have created a single IDirect3d9 interface and two frames (one for each screen), I've enumerated the displays and created two IDirect3d9Devices from my interface and associated one with each display. However, if I use D3DPRESENT_INTERVAL_ONE, then both displays get rendered at 60 Hz.

So I went back a step and just created a single device and tested it on either monitor. In this case I get either 60 or 75 Hz on the two screens. After some playing I also discovered that I could directy check where in the refresh cycle my monitors are so I found if set D3DPRESENT_INTERVAL_IMMEDIATE then use something like

D3DRASTER_STATUS rStatus;

m_deviceD3D9->GetRasterStatus(0, &rStatus);

while (rStatus.InVBlank)

{

m_deviceD3D9->GetRasterStatus(0, &rStatus);

}

while (!rStatus.InVBlank)

{

m_deviceD3D9->GetRasterStatus(0, &rStatus);

}

before my present call. Then I get the native resolution for each monitor when used on their own. However again I hit problems when running on two screens. Now I only get between 45 and 55 fps, presumably because my code spends so long in the while loops.

I wondered if I could triple buffer and write to the third buffer while in the while loops in another thread, but I don't see how to get and write to the third buffer, i.e. what code do I actually need to call?

Any help much appreciated

Phil

Advertisement

Okay, well I worked out how to render to a different back buffer

IDirect3DSwapChain9 *swapChain;

m_deviceD3D9->GetSwapChain(0,&swapChain);

IDirect3DSurface9 *backBuffer;

swapChain->GetBackBuffer( m_bufferToRender,

D3DBACKBUFFER_TYPE_MONO, &backBuffer );

m_deviceD3D9->SetRenderTarget( 0, backBuffer );

I then increment m_bufferToRender after each render, and decrement it after each present. Unfortunately this doesn't help. Using the InVBlank method above still gives much less than the native screen speeds. I guess this is because I have 2 threads - one per device - and probably when the OS swaps between threads VSynchs are missed.

I guess I need to return to D3DPRESENT_INTERVAL_ONE. Does anyone know why I would be getting 60 FPS using this setting when one monitor is 75 Hz and the other is 60 Hz?

I don't have an answer, but some things that might have an impact --
Which OS are you using, and are you using an IDirect3DDevice9 or an IDirect3DDevice9Ex?

Thanks for the interest Hodgman

I got things working as I needed, but I'm not sure it was the most efficient method.

In the end I set up a single rendering thread that dealt with both windows - one on each screen, then set up a while loop which repeatedly checked the rendering state through a call to get RasterStatus. Then when a screen had just finished rastering I rendered the image for that screen and presented it using D3DPRESENT_INTERVAL_IMMEDIATE.

Having both windows being dealt with in one thread was a bit more complex in the coding than having a thread each, but this gave me the 60 and 75 FPS on the respective screens. Luckily the rendering is not complex so just using immediate presenting with no timing code I was able to do 200 fps on each screen, so I can be fairly certain that I won't miss a screen refresh - or that I will miss very few.

Just for interest I'm running on Windows 8 (but need it to work on Windows 7 too) using Direct3DDevice9.

See Multi Windows example in Microsoft directX SDK

This topic is closed to new replies.

Advertisement