Yesterday I've been playing with the DX9 render system for fixing some bugs when using multiple monitors (so, multiple d3d9 devices) and multiple render windows (editor-like app). I'm opening a new thread here instead of simply creating a pull-request / JIRA ticket since this "fix" works fine for me but maybe not for others (although I think all apps with multiple render windows -so potentially using a dummy render window- would benefit from this).
Problem + solution:
In Paradise Sandbox, I use a dummy render window to be used as primary render window (holding all resources, ...) and avoid device resets when resizing (and others) the render windows.
Well, that works very well when there is only one device (1 monitor), but it was not working that fine when there were two devices (2 monitors).
The problem was that if the app was in one monitor (placing the app window in one screen) all worked fine, but when the app was dragged to the other monitor, the dummy render window didn't seem to work: resizing render windows (the first one to be created, so it was acting as primary render window) leads to device resets. Moreover these device resets were "weird": if Hydrax was enabled then I got the classical "Cannot reset device!" (Which was very weird because in Hydrax I'm not using anything fancy: manual mesh + some RTTs, nothing which I haven't used in other parts of Paradise Sandbox).
My solution: forcing the DX9 RS to change the device of ALL render windows when one of them was changed to another device. This way, all render windows will be attached to the "second" device and the dummy render window will continue to act as primary render window, avoiding these annoying device resets when resizing, removing/adding render windows, etc.
I guess it's "safe" to assume that usually a multi render window application (editors) will belong always on the same "monitor", but maybe some apps will have multiple render windows in different UI windows and each one will be placed in one monitor. But even if that's the case, I very doubt Windows will allow the same app to be on "different monitors", so I guess internally all render windows of the same app will belong to the same device even if the app has multiple UI windows each one in a different monitor with an Ogre render window. (I haven't looked into this, anyone?).
Here is my "fix": OgreD3D9DeviceManager.cpp - ::selectDevice(...), add the else statement between >>> & <<<:
Code: Select all
if (validateAllDevices)
{
for (uint i = 0; i < mRenderDevices.size(); ++i)
mRenderDevices[i]->validateFocusWindow();
}
}
}
}
// ----------------------------------------->>>
else // No multi-head
{
// Move all existing render windows to the new device (or, alternatively, we could just move the dummy render window assumed it's the first one if multiple render windows are present)
D3D9RenderWindowList& renderWindows = renderSystem->mRenderWindows;
D3D9RenderWindow* rw;
for(Ogre::uint32 k = 0; k < renderWindows.size(); k++)
{
rw = renderWindows.at(k);
if (rw != renderWindow)
{
if (rw->getDevice())
{
rw->getDevice()->detachRenderWindow(rw);
}
renderWindowsGroup.push_back(rw);
}
}
}
// ------------------------------------- <<<
}
// Do we want to preserve the FPU mode? Might be useful for scientific apps
ConfigOptionMap& options = renderSystem->getConfigOptions();
ConfigOptionMap::iterator opti = options.find("Floating-point mode");
if (opti != options.end() && opti->second.currentValue == "Consistent")
extraFlags |= D3DCREATE_FPU_PRESERVE;
I hope it will be of help for anyone else having this problem.
Xavier