PDA

View Full Version : Assigning to a secondary GPU --and other issues



Josh S
10-07-2009, 02:54 PM
I'm having a problem where I've been unable get any OpenGL application to take advantage of the second GPU on my system.

I have two Quadro FX 4800 cards, no SLI, Win7 x64 and, as far as I can tell, all the latest drivers. I somehow got it into my head that I could do the following: open a window entirely within a display attached to my secondary graphics adapter, create a context for that window, and then all subsequent OpenGL calls would be routed to that GPU, leaving the primary GPU largely untouched, and available for near-exclusive use by another process. (I understand that OSX works something like that.) This has not turned out to be the case.

I cannot get my app to run on the second GPU. I call CreateWindowEx() with parameters to open the window [and then keep it] entirely on one of these secondary monitors. No luck. I've tried disabling Windows Aero... still no luck.

I should mention that I'm using the RivaTuner monitor to determine which GPU is active at any given time, using the Voltage Regulator Current readout for each GPU.

The only partial success I've had is by using wglCreateAffinityDCNV() with a mask to permit activity only on the secondary GPU. Then, my app does seem to run [mostly] on the secondary GPU! (The primary is busy doing... something.) But I can no longer draw to the window because Affinity-DCs cannot be bound to a window. I think. This extension is NOT well-documented, and I have found no examples of its use. I've not looked at the source for Equalizer, as I suspect it's just using affinity-DCs for rendering to FBOs, not to an actual window. Maybe it would still be useful?

The whole point of this exercise is to draw at 60fps to all 4 graphics outputs on the machine. As it is, I can create a single window that spans my 3840x2160 quad 1920x1080 desktop and get a solid 30 fps with VSync on. This would actually be fine for my application, except for one problem: Even though I see 30fps, OpenGL reports that it's drawing 60fps. I'm calling SwapBuffers() 60 times per second, but only every-other frame is visible on screen. I can't tell programmatically WHICH frames are visible, which means that later on, I'll have trouble frame-syncing my application across machines.

Now, when I first execute my application in a window stretched across two monitors, both attached to the primary adapter, I get a smooth 60fps. Even with a window stretched across the two displays on the secondary adapter, I get a smooth 60 for a second or two before it falls to 30. (Currently, I'm just rendering a few rectangles, so it's not that my scene is overly complex.) It would be acceptable to run two entirely separate instances of the application, one for each GPU... if I could be sure that the second instance would run on the second GPU, and I'm hoping: thus run at 60fps.

Anyway, anybody have any ideas? Hopefully there's something simple that I'm overlooking, but I've searched around for days now to no avail.

Also - I've been holding off on posting about this issue anywhere because there seem to be so many different facets to the problem... Would I be more likely to get assistance by breaking down my problems into smaller posts?

Thanks for treading to the end. Any help would be REALLY appreciated!

_________
Josh

yooyo
10-07-2009, 03:42 PM
Have you tried to change hardware acceleration settings in driver control panel. There is a few options.. single-primary, multi-perormance, multi-compatibility, ...

eile
10-08-2009, 01:44 AM
This gives the answer: http://www.equalizergraphics.com/

Especially: http://www.equalizergraphics.com/documentation/parallelOpenGLFAQ.html

eile
10-08-2009, 01:47 AM
Reading your full post again....



The only partial success I've had is by using wglCreateAffinityDCNV() with a mask to permit activity only on the secondary GPU. Then, my app does seem to run [mostly] on the secondary GPU! (The primary is busy doing... something.) But I can no longer draw to the window because Affinity-DCs cannot be bound to a window. I think.


They can be bound to a window. Try the Equalizer example applications.



This extension is NOT well-documented, and I have found no examples of its use. I've not looked at the source for Equalizer, as I suspect it's just using affinity-DCs for rendering to FBOs, not to an actual window. Maybe it would still be useful?


Wrong. Eq can use affinity with all drawable types (window, PBuffer, FBO).



The whole point of this exercise is to draw at 60fps to all 4 graphics outputs on the machine. As it is, I can create a single window that spans my 3840x2160 quad 1920x1080 desktop and get a solid 30 fps with VSync on. This would actually be fine for my application, except for one problem: Even though I see 30fps, OpenGL reports that it's drawing 60fps. I'm calling SwapBuffers() 60 times per second, but only every-other frame is visible on screen. I can't tell programmatically WHICH frames are visible, which means that later on, I'll have trouble frame-syncing my application across machines.


Just use Equalizer, unless you want to figure out all the problems yourself.

Josh S
10-08-2009, 06:29 AM
eile,

Your enthusiasm gives me much-needed new hope! I'm off to try it, and will report back...

Josh S
10-08-2009, 01:34 PM
Well, I've spent most of the day at this, and haven't gotten far. Right now, I'm just trying to get the Equalizer HelloWorld example to run the way I'd like. I was able to run it out-of-the-box in four windows, and I've been able to run it with the config file "1-window.nonthreaded.eqc" --but when I try to use the "device" setting for the one window in that config file, (to force the thing to run on the second GPU,) I get a failure at application startup. It seems that the call to wglMakeCurrent fails when I use the "device" parameter, as it means I'm using an affinityDC incorrectly... somehow.

I still can't find any examples of what I'm trying to do-- for Equalizer or anything else. One Device Context. One Render Context. One Window. One Render Thread. One [non-primary] GPU.

Incidentally, affinityCheck reports the following:

GPU 0: NVIDIA Quadro FX 4800 used on [1920 0 1920 1200]
GPU 1: NVIDIA Quadro FX 4800 used on [3840 0 1920 1200]

(I have two 1920x1200 screen plugged into each of these adapters, so... these viewports seem strange to me.)

eile, would it make sense to move this discussion over to the Equalizer forum instead?

Josh S
10-08-2009, 02:09 PM
OK, the affinitycheck issue is fixed - my nVidia drivers were unhappy, but now seem to be better:

GPU 0: NVIDIA Quadro FX 4800 used on [0 0 1920 1200]
GPU 1: NVIDIA Quadro FX 4800 used on [3840 0 1920 1200]

...strange, though: What happened to my second and fourth displays? Should be viewports [1920 0 1920 1200] and
[5760 0 1920 1200]...

Still no luck with the device parameter.

Josh S
10-08-2009, 02:21 PM
It seems that when I set "device 0" in the config file, it actually does work. I can step through the pipe creation code and I can see the application create the affinityDC, wglMakeCurrent() returns true and the graphics are drawn correctly in the window. Of course, I'm still rendering on the primary GPU instead of the secondary, but at least I can see that the affinity masking is somewhat functional.

Josh S
10-08-2009, 02:38 PM
Just for now, I've turned off the second and forth displays, so...

GPU 0: NVIDIA Quadro FX 4800 used on [0 0 1920 1200]
GPU 1: NVIDIA Quadro FX 4800 used on [1920 0 1920 1200]

...just to make sure there was nothing funny going on with these other displays.

eile
10-08-2009, 11:57 PM
I just run ./build/vs2005/win32/release/eqPly.exe -- --eq-config examples/configs/2-pipe.2D.eqc successfully using the 182.65 drivers.

What error do you get? If you move over to eq-dev, you're likely to get a faster response.


HTH,

Stefan.

Josh S
10-09-2009, 10:25 AM
I tried to run "./build/vs2005/win32/release/eqPly.exe -- --eq-config examples/configs/2-pipe.2D.eqc", and I even rolled back to the 182.65 drivers. Same error. Which OS are you using?

When it crashes, here's the top of the stack:

WGLWindow::configInit() line 260: makeCurrent();
WGLWindow::makeCurrent() line 98: wglMakeCurrent( _wglDC, _wglContext )) returns FALSE, so EQCHECK/assert fails. GetLastError() return DWORD 0xc00720d0.

I've started a new thread on eq-dev, but I'm not sure it went through.

Josh S
10-09-2009, 08:24 PM
I've enlisted Microsoft to find out why their wglMakeCurrent() is failing with such a mysterious GetLastError code. Will report back...