Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Direct3D 11 Swap-Chain Madness


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
22 replies to this topic

#1 L. Spiro   Crossbones+   -  Reputation: 20909

Like
1Likes
Like

Posted 23 June 2014 - 09:41 AM

Hi I am L. Spiro, long-time lurker first-time poster.
So one day I was walking along and Direct3D 11 jumped out and bitch-slapped me, then it stepped on my hair, and it told me I was fat.

I am trying to swap between windowed and full-screen and “for reasons” I am not going the standard route by calling IDXGISwapChain->SetFullscreenState() etc. My way is to destroy the window, make a new one, and make a new swap chain for it. I have reasons relating to my engine’s tools and also complicity with the way my other targeted platforms work. Simply put, it is necessary for me to be able to create and destroy multiple windows. And my system works fine except for 1 very strange bug.

If I start in windowed mode, I get an unhandled exception when I go to full-screen.
If I start in full-screen, I can switch to windowed, then if I switch back to full-screen I get an unhandled exception.
I normally get it here:
	LSE_INLINE LSVOID LSE_FCALL CDirectX11::Clear( LSG_RENDER_TARGET * _prtRenderTarget ) {
		GetDirectX11Context()->ClearRenderTargetView( _prtRenderTarget, m_rsCurRenderState.fClearColor );
	}
_prtRenderTarget will be the address of the newly created color buffer. The address is valid and the buffer does exist. Also, the Direct3D context is untouched and valid throughout.
The error is this:
First-chance exception at 0x000007fefd1e940d in LSTest.exe: 0x0000087A: 0x87a.
 
You want to say, “Are you sure all the involved pointers/objects are valid?”.
I am glad you asked that.  Let me show you.


When the window mode changes, 4 objects are destroyed and then recreated with the new window:
/** Our swap chain. */
IDXGISwapChain *		m_pscSwapChain;

/** View to the back color buffer. */
ID3D11RenderTargetView *	m_prtvRenderTargetView;

/** The depth-stencil texture. */
ID3D11Texture2D *		m_pt2dDepthStencilBuffer;

/** View to the back depth/stencil buffer. */
ID3D11DepthStencilView *	m_pdsvDepthStencilView;
(_prtRenderTarget matches m_prtvRenderTargetView when the exception happens.)

So I logged the creation and deletion of m_prtvRenderTargetView since that is the object being passed to Clear().
 
RELEASED 00000000
CREATED 0BD66A88
RELEASED 0BD66A88
RELEASED 00000000
CREATED 0BD63708
First-chance exception at 0x000007fefd1e940d in LSTest.exe: 0x0000087A: 0x87a.
* Debugger shows _prtRenderTarget = 0x0BD63708 inside Clear().
 
 
 
Now let me show you why this is strange.
I changed my code to this:
	LSE_INLINE LSVOID LSE_FCALL CDirectX11::Clear( LSG_RENDER_TARGET * _prtRenderTarget ) {
		static LSBOOL bFailedLast = false;
		try {
			if ( bFailedLast ) {
				LSCHAR szBuffer[43];
				CStd::SPrintF( szBuffer, 43, "PASS 2 %.8X\r\n", _prtRenderTarget );
				CStd::DebugPrintA( szBuffer );
			}
			GetDirectX11Context()->ClearRenderTargetView( _prtRenderTarget, m_rsCurRenderState.fClearColor );
			bFailedLast = false;
		}
		catch ( ... ) {
			bFailedLast = true;
			LSCHAR szBuffer[43];
			CStd::SPrintF( szBuffer, 43, "DIE %.8X\r\n", _prtRenderTarget );
			CStd::DebugPrintA( szBuffer );
		}
	}
This basically means if it fails I will print “DIE” and then on the next call I will print “PASS 2”.
Here is the log now:
RELEASED 00000000
CREATED 000F5588
RELEASED 000F5588
RELEASED 00000000
CREATED 0BD669C8
RELEASED 0BD669C8
RELEASED 00000000
CREATED 0BD63708
First-chance exception at 0x000007fefd1e940d in LSTest.exe: 0x0000087A: 0x87a.
DIE 0BD63708
PASS 2 0BD63708
RELEASED 0BD63708
RELEASED 00000000
CREATED 0BDBA808
RELEASED 0BDBA808
RELEASED 00000000
CREATED 0BDBA808
RELEASED 0BDBA808
RELEASED 00000000
CREATED 0BEB9908
RELEASED 0BEB9908
RELEASED 00000000
CREATED 0BEBB508
RELEASED 0BEBB508
RELEASED 00000000
CREATED 0BD67748
RELEASED 0BD67748
RELEASED 00000000
CREATED 0BEB9248
RELEASED 0BEB9248
RELEASED 00000000
CREATED 0BEB9248
RELEASED 0BEB9248
RELEASED 00000000
CREATED 0DD4F7C8
RELEASED 0DD4F7C8
RELEASED 00000000
CREATED 0BD66688
RELEASED 0BD66688
RELEASED 00000000
CREATED 0BDBA808
RELEASED 0BDBA808
RELEASED 00000000
CREATED 0DD47708
RELEASED 0DD47708
RELEASED 00000000
CREATED 0DD47708
RELEASED 0DD47708
RELEASED 00000000
CREATED 0DD56A88
RELEASED 0DD56A88
RELEASED 00000000
CREATED 0BD66688
RELEASED 0BD66688
RELEASED 00000000
CREATED 0BD67748
RELEASED 0BD67748
RELEASED 00000000
CREATED 0BD98888
RELEASED 0BD98888
RELEASED 00000000
CREATED 0DD47708
RELEASED 0DD47708
RELEASED 00000000
CREATED 0BD59EC8
Changing state.
*==
RELEASED 0BD59EC8
RELEASED 00000000
RELEASED 00000000
 
Go home Direct3D 11, you’re drunk.

Start in full-screen:
RELEASED 00000000
CREATED 000F5588

Full-screen to windowed:
RELEASED 000F5588
RELEASED 00000000
CREATED 0BD669C8

Windowed to full-screen:
RELEASED 0BD669C8
RELEASED 00000000
CREATED 0BD63708
First-chance exception at 0x000007fefd1e940d in LSTest.exe: 0x0000087A: 0x87a.
DIE 0BD63708
PASS 2 0BD63708

* Draws fine for a while, no bugs. *
Full-screen to windowed:
RELEASED 0BD63708
RELEASED 00000000
CREATED 0BDBA808

* Draws fine, many mode switches follow, never throws the exception again. *
 
 
So, yes, I am positive that all objects are valid.
It creates object 0BD63708, fails to clear it once, but then has no problem clearing it after that.
After it throws 1 (one) exception it can not only continue working with the exact object that caused the exception but the exception never happens again no matter how many times I destroy the window and swap chain and recreate them both.
 
 
 
Here is the code for destroying and recreating the swap chain and back buffers (minus the debug prints) with a new window:
	LSE_INLINE LSVOID LSE_CALL CDirectX11::SetWindowParms( LSBOOL _bWindowed, HWND _hWnd ) {
		// Get the width and height of the window.
		RECT rClient;
		::GetClientRect( _hWnd, &rClient );
		m_dscdSwapChainDesc.BufferDesc.Width	= rClient.right - rClient.left;
		m_dscdSwapChainDesc.BufferDesc.Height	= rClient.bottom - rClient.top;
		m_dscdSwapChainDesc.OutputWindow	= _hWnd;
		m_dscdSwapChainDesc.Windowed		= _bWindowed;

		ReleaseBackBuffers();
		SafeRelease( m_pscSwapChain );
		IDXGIFactory * pfFactory;
		if ( SUCCEEDED( ::CreateDXGIFactory( __uuidof( IDXGIFactory ), reinterpret_cast<void **>(&pfFactory) ) ) ) {
			pfFactory->CreateSwapChain( m_pdDevice, &m_dscdSwapChainDesc,
				&m_pscSwapChain );
			SafeRelease( pfFactory );
		}
		CreateSwapChainBackBuffers( _hWnd );
	}

	LSVOID LSE_CALL CDirectX11::ReleaseBackBuffers() {
		SafeRelease( m_pdsvDepthStencilView );
		SafeRelease( m_pt2dDepthStencilBuffer );
		SafeRelease( m_prtvRenderTargetView );
	}

	LSBOOL LSE_CALL CDirectX11::CreateSwapChainBackBuffers( HWND /*_hWnd*/ ) {
		ReleaseBackBuffers();


		// Create the color buffer.
		ID3D11Texture2D * ptBuffer = NULL;
		if ( FAILED( m_pscSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ),
			reinterpret_cast<void **>(&ptBuffer) ) ) ) {
			CStd::DebugPrintA( "Failed to access front buffer.\r\n" );
			ReleaseBackBuffers();
			return false;
		}
		if ( FAILED( m_pdDevice->CreateRenderTargetView( ptBuffer, NULL, &m_prtvRenderTargetView ) ) ) {
			CStd::DebugPrintA( "Failed to create the main render target.\r\n" );
			ReleaseBackBuffers();
			SafeRelease( ptBuffer );
			return false;
		}
		SafeRelease( ptBuffer );


		// Make the depth/stencil buffer.
		D3D11_TEXTURE2D_DESC tdDepthStencilDesc = { 0 };
		[SET ALL THE PARAMETERS]
		if ( FAILED( m_pdDevice->CreateTexture2D( &tdDepthStencilDesc, NULL, &m_pt2dDepthStencilBuffer ) ) ) {
			CStd::DebugPrintA( "Failed to create the main depth/stencil buffer.\r\n" );
			ReleaseBackBuffers();
			return false;
		}

		// And now the view.
		D3D11_DEPTH_STENCIL_VIEW_DESC dsvdDesc = { tdDepthStencilDesc.Format };
		dsvdDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
		dsvdDesc.Texture2D.MipSlice = 0;
		if ( FAILED( m_pdDevice->CreateDepthStencilView( m_pt2dDepthStencilBuffer, &dsvdDesc, &m_pdsvDepthStencilView ) ) ) {
			CStd::DebugPrintA( "Failed to create the depth/stencil view.\r\n" );
			ReleaseBackBuffers();
			return false;
		}

		return true;
	}
I get no failure debug outputs and all the objects are created successfully.
I have enabled DirectX 11 Debug Mode in the control panel. It prints nothing.
The first time and only the first time it goes into full-screen mode from windowed mode it throws this exception.
It can also throw it here:
	LSE_INLINE LSVOID LSE_FCALL CDirectX11::Present() {
		m_pscSwapChain->Present( 0, 0 );
	}
In either case it throws only one time and then works perfectly fine after that.


The double RELEASE lines in the log are because ReleaseBackBuffers() is being called twice, but SafeRelease() sets the pointers to NULL.
I have no errors with my reference counters etc.
My window code (creating and destroying, windowed mode and full-screen mode) is the same on all platforms and is not the problem.
This is all single-threaded.



Is there something I need to do when switching from windowed to full-screen the first time? It always works after the first time, so the concept and my implementation should be sound. Honestly this is looking like a driver bug.
Any ideas?


L. Spiro

Edited by L. Spiro, 23 June 2014 - 08:24 PM.


Sponsor:

#2 CodeAngry   Members   -  Reputation: 136

Like
1Likes
Like

Posted 23 June 2014 - 11:42 AM

Do you by any chance have FRAPS running?

 

I've had a major PITA from reference counting issues due to FRAPS. Then closed it...



#3 L. Spiro   Crossbones+   -  Reputation: 20909

Like
0Likes
Like

Posted 23 June 2014 - 01:12 PM

I do not.

It also happens in both 32- and 64- bit versions.


L. Spiro

#4 Jason Z   Crossbones+   -  Reputation: 6125

Like
1Likes
Like

Posted 23 June 2014 - 04:33 PM

This is just a crazy first shot, but is the exception handled somewhere other than your code?  I have had cases where the first chance exception occurs, only to be handled in one of the underlying libraries (i.e. the exception is used as a normal part of one of the sub-systems).  If you set VS to not break on first chance exceptions then you would never even know it occurred.

 

Before digging into the nitty gritty details, have you tried that out?



#5 Mona2000   Members   -  Reputation: 1102

Like
2Likes
Like

Posted 23 June 2014 - 05:55 PM

Are you sure you got debug logging properly working? IIRC exception 0x87a is the debug layer error exception.



#6 HappyCoder   Members   -  Reputation: 3120

Like
1Likes
Like

Posted 23 June 2014 - 05:55 PM

Very strange bug. Have you tested it on other machines?



#7 L. Spiro   Crossbones+   -  Reputation: 20909

Like
0Likes
Like

Posted 23 June 2014 - 08:23 PM

Before digging into the nitty gritty details, have you tried that out?

Indeed I have only tried in Visual Studio. I will try this when I can.

Are you sure you got debug logging properly working?

No. If you mean the debug run-time, I am expecting it to print some information at start-up and I am not even getting that.

Have you tested it on other machines?

Not yet. Maybe I will be able tomorrow.


L. Spiro

#8 NightCreature83   Crossbones+   -  Reputation: 3810

Like
1Likes
Like

Posted 24 June 2014 - 02:39 AM

Have you turned the Debug runtime on, because as of WIN8 SDK this has to be done through the VS2012 and up window or through executing the settings window from the WinSDK directory. It will not turn your debug runtime on other wise even though you did set it on in the D3D june SDK. http://blogs.msdn.com/b/chuckw/archive/2012/11/30/direct3d-sdk-debug-layer-tricks.aspx


Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#9 L. Spiro   Crossbones+   -  Reputation: 20909

Like
0Likes
Like

Posted 24 June 2014 - 06:37 AM

The article says all I have to do in Direct3D 11 is add it to the list in the control panel, which I’ve done.

Staring with Direct3D 10.0, a new mechanism was created for the "Developer Runtime" via a API layering mechanism and is implemented in the D3D10SDKLAYERS.DLL. Developers could opt in their specific application to the debug validation either by creating the device with D3Dxx_CREATE_DEVICE_DEBUG, or by adding the executable to a list in the DirectX Control Panel.


I’ve used it before but this is the first time it simply ignores me.
In order to be positive that I have added the correct path to my executable, I ran it in Visual Studio and got this message:
'LSTest.exe': Loaded 'E:\My Projects\LSEngine\Win32\DX11 Debug\LSTest.exe', Symbols loaded.
I copied and pasted “E:\My Projects\LSEngine\Win32\DX11 Debug\LSTest.exe” into the DirectX Control Panel, so there is no mistake as to which version of my program is running and in their list.

DCP1.png
DCP2.png

My SDK is v6.0a, included with Visual Studio 2008 (the compiler I am using).


L. Spiro

#10 Andy Gainey   Members   -  Reputation: 2658

Like
1Likes
Like

Posted 24 June 2014 - 09:28 AM

The article says all I have to do in Direct3D 11 is add it to the list in the control panel, which I’ve done.

Staring with Direct3D 10.0, a new mechanism was created for the "Developer Runtime" via a API layering mechanism and is implemented in the D3D10SDKLAYERS.DLL. Developers could opt in their specific application to the debug validation either by creating the device with D3Dxx_CREATE_DEVICE_DEBUG, or by adding the executable to a list in the DirectX Control Panel.


I’ve used it before but this is the first time it simply ignores me.

 

I ran into a similar problem on Windows 7 just a week or two ago.  It would never actually turn on the debug runtime, and every time I closed and re-opened the DX control panel, everything was unchecked back to its defaults.

 

A bit of internet searching revealed that for reasons I didn't bother to investigate, the TrustedInstaller user had taken ownership of the relevant hunk of Registry data, and thus the DX control panel changes were silently being rejected.

 

So what you might want to try is to navigate to HKLM/SOFTWARE/Microsoft/Direct3D in RegEdit, open up the security permissions for the Direct3D key, and if the owner is indeed TrustedInstaller, change it to yourself (or a user group you belong to), and then grant yourself (or the selected user group) full control permissions (they might be read only by default).



"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke

#11 L. Spiro   Crossbones+   -  Reputation: 20909

Like
0Likes
Like

Posted 24 June 2014 - 09:58 AM

I have checked permissions and all are fine.
When I change settings in DirectX Control Panel it updates in the registry.

I also changed registry items manually to 1, such as LoadDebugRuntime. Even doing that, nothing happens when I start my test program.


L. Spiro

#12 Jason Z   Crossbones+   -  Reputation: 6125

Like
3Likes
Like

Posted 24 June 2014 - 05:53 PM

I usually avoid all the craziness of the control panel by just creating the device with the debug flag - then you have no question whether it is enabled or not.



#13 L. Spiro   Crossbones+   -  Reputation: 20909

Like
0Likes
Like

Posted 25 June 2014 - 05:18 AM

I can’t use D3D11_CREATE_DEVICE_DEBUG without the Windows SDK 8 installed, something I fear doing considering apparently some things have to be done through Visual Studio 2012 (which I do not have).


L. Spiro

#14 NightCreature83   Crossbones+   -  Reputation: 3810

Like
1Likes
Like

Posted 26 June 2014 - 02:34 AM

I can’t use D3D11_CREATE_DEVICE_DEBUG without the Windows SDK 8 installed, something I fear doing considering apparently some things have to be done through Visual Studio 2012 (which I do not have).


L. Spiro

 

VS 2012 makes it easier to launch these applications, you can still just manually go into the SDK directory and launch the tool you need from there.
 


Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#15 Jason Z   Crossbones+   -  Reputation: 6125

Like
1Likes
Like

Posted 26 June 2014 - 03:19 PM

I can’t use D3D11_CREATE_DEVICE_DEBUG without the Windows SDK 8 installed, something I fear doing considering apparently some things have to be done through Visual Studio 2012 (which I do not have).


L. Spiro

 

I guess I'm going off topic here, but I exclusively use VS2012 Express for Windows Desktop at work for my visualization tools.  Is there a substantive reason you don't want to upgrade?  My applications are targeting Windows 7+, so if you are using D3D11 then that should be ok for you too.

 

When I made the switch off of the DXSDK, it was essentially to remove my D3DX dependencies and find an alternative way to load textures.  If you are working in a cross platform engine, I would assume you have both of these topics covered already, so why not upgrade?  Each version of 2012 provides performance and bug fixes for the toolset and libraries, so there is a reason to upgrade.  Plus newer C++11/14 features are being added in each release which is also a nice bonus...



#16 L. Spiro   Crossbones+   -  Reputation: 20909

Like
1Likes
Like

Posted 26 June 2014 - 03:27 PM

I had assumed without checking that it would not be free.
Apparently I was wrong: http://www.microsoft.com/en-us/download/details.aspx?id=30682
I downloaded it last night but have yet to install or convert my projects.

But why do you use the express version? It appears the professional version is free.


L. Spiro


[EDIT]
Just tried it on another computer.
 
DXGI ERROR: IDXGISwapChain::Release: Swapchain Released while fullscreen. Switch it to the windowed state first. [ MISCELLANEOUS ERROR #66: ]
LSTest.exe の 0x000007fefd4b940d で初回の例外が発生しました: 0x0000087A: 0x87a
 
I guess that explains the error then.
[/EDIT]

Edited by L. Spiro, 26 June 2014 - 03:32 PM.


#17 Jason Z   Crossbones+   -  Reputation: 6125

Like
1Likes
Like

Posted 26 June 2014 - 03:41 PM

I wasn't aware that the Pro version was free - do you have a link showing where that is stated?  We have been using the express editions because of the licensing cost, but of course if the Pro SKU is available then I would upgrade to that.  I would be really surprised if that isn't a time limited demo for free, otherwise why would they even have the Express SKU???

 

So now you have the root cause of the issue, right?  So no further need for debugging there?



#18 L. Spiro   Crossbones+   -  Reputation: 20909

Like
0Likes
Like

Posted 26 June 2014 - 03:59 PM

I looked all over to see if it isn’t free. It doesn’t seem to specify either way there.
I just downloaded without installing, but now I see people on http://stackoverflow.com/ saying it is a 90-day trial.

The reason I never get express editions is because the first Visual Studio I had was express and on every start-up it would show a pop-up saying so. It basically scarred me for life with a majorly mega-bad impression imprinted on me for all eternity. When I die and my atoms fall into a sun in a billion years that sun will have a distaste for express editions of Visual Studio.


As for the problem at hand, it seems solved. I am just not at home and can’t work on it, but 99.9% I know what to do when I get home.


L. Spiro

#19 Hodgman   Moderators   -  Reputation: 40930

Like
0Likes
Like

Posted 26 June 2014 - 06:10 PM

We have been using the express editions because of the licensing cost, but of course if the Pro SKU is available then I would upgrade to that.

Off topic - but apply to BizSpark and they'll give you free keys for every version of Visual Studio.

I downloaded it last night but have yet to install or convert my projects.

IIRC, VS2012 is the first version that gives you the option of not converting your projects (assuming you're using an older Visual Studio at the moment).
e.g. you can use a VS2010 project file, and then work on it in both VS2010 and VS2012 without having to convert it.
 
Do you really have to use VS2012 to use that debug flag though? Or can you use whatever IDE you want just as long as the platform SDK has been installed on your PC some time?



#20 Jason Z   Crossbones+   -  Reputation: 6125

Like
0Likes
Like

Posted 26 June 2014 - 07:43 PM


Off topic - but apply to BizSpark and they'll give you free keys for every version of Visual Studio.

I work at a company that has roughly 300,000 employees, so I'm pretty sure BizSpark is out of the question :)  Thanks for the suggestion though!

 

Regarding the debug flag, I was not aware that there were any restrictions about which version of the SDK had to be installed.  I added the debug flag in debug builds in one of the earliest versions of Hieroglyph 3, which was created when D3D11 was still a CTP...






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS