Crash on fullscreen at lower res

Problems building or running the engine, queries about how to use features etc.
Post Reply
User avatar
cowtung
Gnoblar
Posts: 17
Joined: Wed Dec 16, 2015 10:28 pm

Crash on fullscreen at lower res

Post by cowtung »

My application won't be using SDL, and it appears that all of the examples I've found use SDL. Trying to take SDL out of an example works until I try fullscreen at a different resolution. Here is my code...

Code: Select all

void GraphicsSystem::initialize( const Ogre::String &windowTitle )
{
	Ogre::String pluginsPath;
	// only use plugins.cfg if not static
#ifndef OGRE_STATIC_LIB
#if OGRE_DEBUG_MODE
	pluginsPath = mResourcePath + "plugins_d.cfg";
#else
	pluginsPath = mResourcePath + "plugins.cfg";
#endif
#endif

	mRoot = OGRE_NEW Ogre::Root( "", "", mResourcePath + "Ogre.log" );

#if OGRE_DEBUG_MODE
	mRoot->loadPlugin( "RenderSystem_Direct3D11_d" );
	mRoot->loadPlugin( "Plugin_ParticleFX_d" );
#else
	mRoot->loadPlugin( "RenderSystem_Direct3D11" );
	mRoot->loadPlugin( "Plugin_ParticleFX" );
#endif

	Ogre::RenderSystem* rs = mRoot->getRenderSystemByName( "Direct3D11 Rendering Subsystem" );
	if (!rs)
	{
		// Unrecognised render system
		return;
	}

	bool fullscreen = true;
	
	rs->setConfigOption( "Allow NVPerfHUD", "No" );
	rs->setConfigOption( "Backbuffer Count", "Auto" );
	rs->setConfigOption( "Driver type", "Hardware" );
	rs->setConfigOption( "FSAA", "4" );
	rs->setConfigOption( "Floating-point mode", "Fastest" );
	rs->setConfigOption( "Full Screen", fullscreen ? "Yes" : "No" );
	rs->setConfigOption( "Information Queue Exceptions Bottom Level", "Info (exception on any message)" );
	rs->setConfigOption( "Max Requested Feature Levels", "11.0" );
	rs->setConfigOption( "Min Requested Feature Levels", "9.1" );
	rs->setConfigOption( "Rendering Device", "NVIDIA GeForce GT 640" );
	rs->setConfigOption( "VSync", "Yes" );
	rs->setConfigOption( "VSync Interval", "1" );
	rs->setConfigOption( "Video Mode", "800 x 600 32-bit colour" );
	rs->setConfigOption( "sRGB Gamma Conversion", "Yes" );
	
	Ogre::String err = rs->validateConfigOptions();
	if (err.length() > 0)
	{
		return;
	}

	mRoot->setRenderSystem( rs );
	
	mRoot->initialise( false );

	Ogre::ConfigOptionMap& cfgOpts = mRoot->getRenderSystem()->getConfigOptions();

	Ogre::NameValuePairList miscParams;
	miscParams["colourDepth"] = Ogre::StringConverter::toString( 32 );  //videoMode ? videoMode->getColourDepth()
	miscParams["FSAA"] = cfgOpts["FSAA"].currentValue;
	miscParams["useNVPerfHUD"] = Ogre::StringConverter::toString( false );
	miscParams["gamma"] = Ogre::StringConverter::toString( true );
	miscParams["vsync"] = Ogre::StringConverter::toString( true );
	miscParams["vsyncInterval"] = Ogre::StringConverter::toString( 1 );
	mRenderWindow = Ogre::Root::getSingleton().createRenderWindow( windowTitle, 800, 600, fullscreen, &miscParams );   // FAILURE HERE

	mOverlaySystem = OGRE_NEW Ogre::v1::OverlaySystem();

	setupResources();
	loadResources();
	chooseSceneManager();
	createCamera();
	mWorkspace = setupCompositor();

	BaseSystem::initialize();
}
This fails in D3D11RenderWindowSwapChainBased::_resizeSwapChainBuffers() at the call to mpSwapChain->ResizeBuffers() because mpSwapChain hasn't been initialized yet. This happens because the window's resize event is triggered early for some reason. When I step through one of the tutorials with SDL, I can see that SDL is adjusting the screen's resolution when it creates its own parent window. Maybe Ogre isn't adjusting the screen's resolution when asked to create its own window the way SDL does? I'll keep plugging away at it, but it seems like a bug in Ogre, unless I'm just not understanding something.

Call stack.
  • RenderSystem_Direct3D11.dll!Ogre::D3D11RenderWindowSwapChainBased::_resizeSwapChainBuffers(unsigned int width, unsigned int height) Line 515 + 0x39 bytes C++
  • RenderSystem_Direct3D11.dll!Ogre::D3D11RenderWindowHwnd::updateWindowRect() Line 1216 C++
  • RenderSystem_Direct3D11.dll!Ogre::D3D11RenderWindowHwnd::windowMovedOrResized() Line 1025 C++
  • OgreMain.dll!Ogre::WindowEventUtilities::_WndProc(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam) Line 228 C++
  • user32.dll!7577ef73()
  • [Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]
  • user32.dll!757605c6()
  • user32.dll!7575f788()
  • user32.dll!7575e3e5()
  • user32.dll!7577d6fc()
  • uxtheme.dll!_ThemeDefWindowProc() + 0x5a6 bytes
  • uxtheme.dll!_ThemeDefWindowProcA@16() + 0x18 bytes
  • user32.dll!7575df71()
  • OgreMain.dll!Ogre::WindowEventUtilities::_WndProc(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam) Line 254 + 0x11 bytes C++
  • user32.dll!7577ef73()
  • user32.dll!757605c6()
  • user32.dll!757601c0()
  • user32.dll!75766541()
  • ntdll.dll!_NtCallbackReturn@12() + 0xc bytes
  • user32.dll!75762f51()
  • ntdll.dll!_KiUserCallbackDispatcher@12() + 0x36 bytes
  • user32.dll!7577f5cc()
  • dxgi.dll!CDXGI2Display::GetDesc() + 0x11805 bytes
  • RenderSystem_Direct3D11.dll!Ogre::D3D11RenderWindowHwnd::_createSwapChainImpl(IDXGIDevice1 * pDXGIDevice) Line 964 C++
  • RenderSystem_Direct3D11.dll!Ogre::D3D11RenderWindowSwapChainBased::_createSwapChain() Line 413 + 0xd bytes C++
  • RenderSystem_Direct3D11.dll!Ogre::D3D11RenderWindowHwnd::create(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & name, unsigned int width, unsigned int height, bool fullScreen, const std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,Ogre::STLAllocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,Ogre::CategorisedAllocPolicy<0> > > * miscParams) Line 889 C++
  • RenderSystem_Direct3D11.dll!Ogre::D3D11RenderSystem::_createRenderWindow(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & name, unsigned int width, unsigned int height, bool fullScreen, const std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,Ogre::STLAllocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,Ogre::CategorisedAllocPolicy<0> > > * miscParams) Line 1070 C++
  • OgreMain.dll!Ogre::Root::createRenderWindow(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & name, unsigned int width, unsigned int height, bool fullScreen, const std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,Ogre::STLAllocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,Ogre::CategorisedAllocPolicy<0> > > * miscParams) Line 1298 C++
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Crash on fullscreen at lower res

Post by dark_sylinc »

I'll take a look.

Edit: Does this happen in commit 3b17381f0d35533710d488985f4292e404a2d468 ?
Because commit d72ed622fea63617c2d70b78f360b4bb6203a3df recently introduced a change to D3D11RenderWindow which may have broken your code.
User avatar
cowtung
Gnoblar
Posts: 17
Joined: Wed Dec 16, 2015 10:28 pm

Re: Crash on fullscreen at lower res

Post by cowtung »

It breaks with or without those changes. Those were my changes. I am Mark Hechim.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Crash on fullscreen at lower res

Post by dark_sylinc »

Oh! Nice to meet you :)

I'll be taking a look tomorrow. Hopefully that's ok.
User avatar
cowtung
Gnoblar
Posts: 17
Joined: Wed Dec 16, 2015 10:28 pm

Re: Crash on fullscreen at lower res

Post by cowtung »

Nice to meet you too! :) Tomorrow is fine. I just want to make sure that Ogre is supposed to be able to change screen resolution without SDL. Is that the case? I'll see if I can figure out exactly what SDL is doing (having trouble tracing into it at the moment for some reason) and see if I can just replicate that for now. But it seems like if you ask Ogre to create the window fullscreen, it should be doing the resolution switch, possibly before creating the window, to avoid the resize window message and/or properly handling resize-before-init.
User avatar
cowtung
Gnoblar
Posts: 17
Joined: Wed Dec 16, 2015 10:28 pm

Re: Crash on fullscreen at lower res

Post by cowtung »

So, it looks like RenderSystem_Direct3D11 doesn't call ChangeDisplaySettingsEx() where SDL (and incidentally RenderSystem_GL3Plus) does. I think RenderSystem_Direct3D11 is assuming that the display is already going to be the target resolution and tries to resize the window too early. A fix might be to use ChangeDisplaySettingsEx() for fullscreen windows early in the process. One thing SDL does is create the window as hidden, then in the ShowWindow handler it calls ChangeDisplaySettingsEx() before showing the window. If we add that, then we'll have to call it again when the window is destroyed to set the resolution back (like SDL does).

This brings me to the question of whether I should be attempting to use Ogre3D 2.1 in a released product which is not a video game using SDL. It seems like the expectation is that SDL will be used, as I haven't found any examples where it isn't. I don't know anything about SDL, but I was thinking one less component would reduce complexity. We already handle device input (many devices) and don't need SDL for keyboard and mouse input. But if Ogre fails at window creation / handling without using the SDL window stuff, then I might not have a choice but to use it. If that's the case, then I only hope I can disable any SDL keyboard and mouse stuff and/or it doesn't interfere with our own handling of that stuff.

Any insights you can offer would be most appreciated. Thank you.
User avatar
cowtung
Gnoblar
Posts: 17
Joined: Wed Dec 16, 2015 10:28 pm

Re: Crash on fullscreen at lower res

Post by cowtung »

Just as a quick test, I put ChangeDisplaySettingsEx() in D3D11RenderWindowHwnd::create() right before CreateWindowEx() and it worked.

Code: Select all

...
MONITORINFOEX monitorInfo;  //was MONITORINFO
...
memset(&monitorInfo, 0, sizeof(monitorInfo));
monitorInfo.cbSize = sizeof(monitorInfo);
...
mIsExternal = false;
if (fullScreen)
{
	DEVMODE devmode = { 0 };
	EnumDisplaySettings( monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &devmode );
	devmode.dmPelsWidth = winWidth;
	devmode.dmPelsHeight = winHeight;
	ChangeDisplaySettingsEx( monitorInfo.szDevice, &devmode, NULL, CDS_FULLSCREEN, NULL);
}
mHWnd = CreateWindowEx(dwStyleEx, OGRE_D3D11_WIN_CLASS_NAME, title.c_str(), getWindowStyle(fullScreen), mLeft, mTop, winWidth, winHeight, parentHWnd, 0, hInst, this);
WindowEventUtilities::_addRenderWindow(this);
This code is incomplete in that it doesn't set the display mode back when the window is destroyed, but Windows seems to set it back automatically anyway (I don't know if you can count on that). This is just a working test. I'm not sure I'm qualified to implement this patch for real without introducing some potential bug, given my unfamiliarity with Ogre. Also, you might just want to fix it by hiding the window and not maximizing it until after initialization and then showing it (not sure if that works). Calling ChangeDisplaySettingsEx() might have been left out of RenderSystem_Direct3D11 for a good reason.
Last edited by cowtung on Tue Feb 02, 2016 12:00 am, edited 1 time in total.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Crash on fullscreen at lower res

Post by dark_sylinc »

I took a look. Found and fixed.

There are two ways of handling fullscreen with D3D11:
  • Do it manually, via ChangeDisplaySettingsEx & Co.
  • Let DXGI manage it. This has the advantage that fullscreen has a higher chance of achieving "exclusive fullscreen", which is a superior method for presenting without tearing, without frameskips, and with all GPU resources at our disposals (and plays nice with SLI & Crossfire). This is not always desirable as it makes Alt+Tab work weirdly, and makes multi-monitor almost useless (i.e. app on one monitor, Notepad in another monitor). This is ideal for gaming. But if those are a problem non-exclusive is not the best either, and borderless fullscreen is recommended (borderless fullscreen is just a window in borderless mode covering the whole screen). We were letting DXGI managing it. But without DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH, we were crippling it.
So I just fixed the DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH.
cowtung wrote:This brings me to the question of whether I should be attempting to use Ogre3D 2.1 in a released product which is not a video game using SDL. It seems like the expectation is that SDL will be used, as I haven't found any examples where it isn't.
It is true that the SDL path is more thoroughly tested. However our dependency on SDL is superficial. Ironically it was added mostly to deal with Linux where handling window management is much, much more difficult (and buggy). We can deal with Linux on our own, but many users were unhappy with how we handled it, and always recommended SDL; which is why we took that route.
As for D3D11, you happened to cross a bug that appears to be a remnant from 1.10 that went unnoticed for a long time. Our D3D11 RenderSystem was in a very dire state when I took it in, and sadly 1.10 never got D3D11 right, even today.

Thanks for the report.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Crash on fullscreen at lower res

Post by dark_sylinc »

As a side note, even games should aim to support the 3 types. Some folks prefer exclusive fullscreen for the performance improvements and lower latency. Others prefer borderless fullscreen because they want to do other stuff too (I.e. Skype, managing livestream software, writing notes, reading walkthroughs) and finally there's people who like moving around the window and resizing it.
User avatar
cowtung
Gnoblar
Posts: 17
Joined: Wed Dec 16, 2015 10:28 pm

Re: Crash on fullscreen at lower res

Post by cowtung »

dark_sylinc wrote:I took a look. Found and fixed.
...
Thanks for the report.
You rock, man. Thank you for fixing this so quickly. I had a feeling a mpSwapChain pointer check somewhere would fix it, but I just didn't know the right spot.
Post Reply