5
\$\begingroup\$

I know XNA is long dead, but I need it to update an old project. (I would have ported to MonoGame, but can't get multi-monitor support in it.)

My game does the following:

  1. Wait for some objects which I get from server (in another thread)
  2. I have some components which represent queue (about 5)
  3. When the objects arrive, I generate texture based on the unique information, get a sprite from pool, apply the textures and add it on queue.
  4. The game animates the queues from left to right (when one object is added to queue)

So you see lots of unique textures moving on the screen (the update is pretty fast).

Now I need to run two instance of the game to multiple monitors, and there is lag. The frame rate keeps dropping low and clearly the animation is not smooth.

  • Is running two games on two threads for two monitors a good idea? What could I do instead (running them on seperate processes)?
  • Could some one suggest a rendering optimization like skipping frames or something like that or how can i synchronize between the two instance ?
  • Or, even better, how can I draw on two screens from same game instance?
\$\endgroup\$
4
  • \$\begingroup\$ To be fair, a lot of games run on a single core only and they're fine. Most computers have multiple cores, so performance shouldn't be much of an issue in terms of CPU usage, at all. However, can the GPU handle 2x the load form your game? \$\endgroup\$
    – Lucien
    Nov 18, 2015 at 15:54
  • \$\begingroup\$ Last I checked (2014) one manufacturer had horrible performance issues rendering to multiple windows regardless of the window size on both Linux & Windows (OSX untested). Other manufacturer drivers were fine but it seems that one gave an aggressive rendering priority to the foreground window's buffer swap operation crippling the other windows even if they are part of the same thread/process. Even with tiny windows the rendering went from 60fps to ~5. This is probably to make sure games using a single window weren't slowed down by other windows. Try with many brands if you can. \$\endgroup\$ Jan 17, 2016 at 18:28
  • \$\begingroup\$ "it seems that one gave an aggressive rendering priority to the foreground window's buffer swap operation crippling the other windows" -- seemed to be the case for me. Thanks for the heads up sir. \$\endgroup\$ Jan 18, 2016 at 4:46
  • \$\begingroup\$ Could it be a full screen application with two viewports targeting each monitor? \$\endgroup\$
    – lozzajp
    Jun 17, 2016 at 10:27

2 Answers 2

1
\$\begingroup\$

I can't give you exact implementation details for XNA, but the general idea is to completely forget the "fullscreen mode" - it is old and outdated, and at least Windows will not perform any faster with it, as Winodws changed to a DirectX desktop with Vista (or was it Win7?).

Instead, you create an "extended desktop", ie. right-click at desktop / select resolution / see & arrange the blue monitor(s). Set the center monitor as "primary" if you have 3 screens. And perhaps the left one if 2 screens.

Then you output the graphics in windowed mode, to the hwnd/hdc of a single borderless and captionless form with dimension(s) exactly as total resolution of all screens together.

Ie. if you want a wide screen render with a large camera FOV, covering all 3 screens completely, just create a 6000 px wide window and place it at correct location, like (-2000,0). It will extend over all monitors. I'm sure XNA provides tools to address specific render areas (viewports) inside the single window, such that an area exactly matches a particular monitor.

System.Windows.Forms provides the Screen class that gives you all needed data to find resolutions, offsets, bounds, whatnot.

You can equally well have two separate processes, each one addressing a window in a separate monitor, the other one just uses screen coordinates like (0,0,2000,1000) and the other one (2000,0,4000,1000). Ofc you may have to slow down the main loop in order to give CPU/GPU time to the othe process, but modern GPU drivers will handle multiple apps gracefully, at least on DirectX.


Edit: Also to note: Each time a DirectX window is resized, your video memory will be totally reset. It's a hard device reset. So get ready to re-paint any render surfaces etc. when it happens.

\$\endgroup\$
7
  • \$\begingroup\$ From a performance perspective it is extremely bad advice to paint a single window that spans multiple displays. DWM runs an independent surface for each display, which will refresh at the refresh rate of each display. If you render a window that is the same size as a single display, it can be quickly flipped on to the front buffer at the correct refresh rate. Otherwise, your application will be limited to the refresh rate of the slowest monitor, and additional copying is needed - possibly even a copy to a different graphics device. You should always create a separate window for each display. \$\endgroup\$
    – caesay
    Jan 28, 2022 at 11:26
  • \$\begingroup\$ @caesay, could you elaborate a bit? How would you render in the game loop? Say you want to render a car that spans 3 monitors. \$\endgroup\$
    – Stormwind
    Jan 29, 2022 at 14:02
  • \$\begingroup\$ With two GPU's and two monitors, rendering a single window spanning both monitors means that the DWM will need to copy your buffer two or more times on the primary GPU (compose to back buffer, then flip to front, meaning high latency), and then copy it to the second GPU (slow) and copy it 2+ more times too. Alternatively, if the buffer is correctly sized (to match the display), and already on the correct output device, your swap chain can enter Hardware Independent Flip - meaning the DWM will just swap your buffer directly onto the display front buffer. This is extremely fast and low latency. \$\endgroup\$
    – caesay
    Jan 30, 2022 at 9:55
  • \$\begingroup\$ Also, as I mentioned before, with a single window, your refresh rate will also be limited to the interval of the slowest monitor, and since only one copy can be happening on your buffer at a time, this can add even more latency to present times on both monitors. If your scene is easy enough to compute, it is better to render it twice, once for each display (with appropriate viewport/translations of course). Or render it once before copying it to two separate swap chains that are sized correctly to each display (so the DWM will take a back seat) \$\endgroup\$
    – caesay
    Jan 30, 2022 at 9:58
  • 1
    \$\begingroup\$ You can have a look at the excellent tool PresentMon which can provide you with diagnostic data around how your application is being rendered, and the current latency. If your swap chain enters Hardware Independent Flip, you should expect to see latency that is less than the refresh interval. If DWM is unable to enter this mode (wrongly sized buffer, overlapping windows, etc) it would be normal to see 30-60ms of added present latency. Also see devblogs.microsoft.com/directx/dxgi-flip-model \$\endgroup\$
    – caesay
    Jan 30, 2022 at 10:03
0
\$\begingroup\$

To draw to multiple screens via the graphics devices, you'll need to create your own additional GraphicsDevice to draw to. See the constructor:

public GraphicsDevice (
     GraphicsAdapter adapter,
     GraphicsProfile graphicsProfile,
     PresentationParameters presentationParameters
)

https://msdn.microsoft.com/en-us/library/ff433790.aspx

You can find what graphics adapters there are in your system like this:

 foreach (GraphicsAdapter e inGraphicsAdapter.Adapters)
 {
   Console.WriteLine(e.DeviceName);
 }

For more info about the adapter information read the MSDN article: https://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.graphicsadapter.adapters.aspx

De sure to set the resolution to be within the SupportedDisplayModes or the graphicsdevice.

If your videocard has multiple outputs with monitors connected they should come up as separate adapters. You can use the GraphicsAdapter.IsDefaultAdapter to find the one that XNA defaults to (and is marked by the Windows as the 'default' desktop adapter).

I've not yet tested to output to two screens simultaneously; I did a small test project once to redirect output to a adapter of my choice.

\$\endgroup\$
5
  • \$\begingroup\$ but can I make them all full screen this way ? \$\endgroup\$ Oct 21, 2015 at 4:07
  • \$\begingroup\$ I'm not sure. I've read somewhere that you can have only one fullscreen app at the same time. But a trick around this is to maximize the window and remove the border. \$\endgroup\$
    – Felsir
    Oct 21, 2015 at 8:16
  • \$\begingroup\$ that could be a trick, but wont that make my rendering slower ? anyway i will give that a try and let you know. \$\endgroup\$ Oct 21, 2015 at 8:51
  • \$\begingroup\$ @dumb_terminal it used to be that DirectX applications were faster in exclusive mode (full screen). But I don't think that is true anymore. \$\endgroup\$
    – Roy T.
    May 17, 2016 at 18:38
  • \$\begingroup\$ As long as your borderless window is precisely the same size as a display, in modern versions of windows the DWM will allow your application to enter "Hardware Independent Flip" mode, which will perform similarly to the legacy "Exclusive Full Screen". You may see performance dips if another application renders something on top of your window, because the DWM will revert to Composed Flip, which is the standard desktop composition mode. \$\endgroup\$
    – caesay
    Jan 28, 2022 at 11:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .