Blitzmax fullscreen application crash

Archives Forums/BlitzMax Bug Reports/Blitzmax fullscreen application crash

Armoured(Posted 2011) [#1]
Hi,
With the directx 9 and 7 any fullscreen compiled programs crash after try to resume from a standby.
I use BlitzMax 1.45 on Windows 7


Armoured(Posted 2011) [#2]
Try this simple code to reproduce the "bug":



After run it activate the suspend mode of your PC
the result after the resume is this error:

RUNTIME ERROR:_d3dDev.Reset failed

Some specs:
Windows 7 Ultimate 32bit
Nvidia Geforce GTX 260 driver 280.26

Last edited 2011


therevills(Posted 2012) [#3]
Bump!!!!!

I'm releasing my game very soon on BFG and they have found this bug (also on 1.48).


therevills(Posted 2012) [#4]
The place where this is throwing the error is here in mod\brl.mod\dxgraphics.mod\d3d9graphics.bmx:

Function ResetD3DDevice()
	If _d3dDev.Reset( _presentParams )<0
		Throw "_d3dDev.Reset failed"
	EndIf
		
End Function


If I change that to this:

Function ResetD3DDevice()
	_d3dDev.Reset( _presentParams )
End Function


It works fine... but I'm sure there was a reason for the <0 - Any ideas?

Oh and heres a quick batch file to test sleeping quickly:
echo.
echo. Sleeping
TIMEOUT /T 15 /NOBREAK
echo.
rundll32 powrprof.dll,SetSuspendState 0,1,0


Last edited 2012


therevills(Posted 2012) [#5]
Been doing some more research and both these examples dont do the <0 checks:

http://www.cplusplus.com/forum/windows/13935/

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_DESTROY:
            {
                PostQuitMessage(0);
                return 0;
            } break;

			case WM_ACTIVATEAPP:
            {
                if(wParam)
					if(d3ddev)
                    d3ddev->Reset(&d3dpp);
            } break;
    }

    return DefWindowProc (hWnd, message, wParam, lParam);
}


http://g-engine-rts.googlecode.com/svn-history/r28/trunk/GEngine/D3DApp.cpp

bool D3DApp::isDeviceLost()
{
	// Get the state of the graphics device.
	HRESULT hr = d3ddev->TestCooperativeLevel();

	// If the device is lost and cannot be reset yet then
	// sleep for a bit and we'll try again on the next 
	// message loop cycle.
	if( hr == D3DERR_DEVICELOST )
	{
		Sleep(20);
		return true;
	}
	// Driver error, exit.
	else if( hr == D3DERR_DRIVERINTERNALERROR )
	{
		MessageBox(0, "Internal Driver Error...Exiting", 0, 0);
		PostQuitMessage(0);
		return true;
	}
	// The device is lost but we can reset and restore it.
	else if( hr == D3DERR_DEVICENOTRESET )
	{
		InvalidateDeviceObjects();
		d3ddev->Reset(&md3dPP);
		RestoreDeviceObjects();
		return false;
	}
	else
		return false;
}



col(Posted 2012) [#6]
How come I never saw this post before :D

I dont think its good practice to combine D3D calls within the windows message handler.

Anyway, the < 0 will be true when ANY errors occur. However, an error isnt necessarily a bad thing in this instance, so providing that the error code isnt D3DERR_INTERNALERROR then it should be ok.

In file d3d9graphics.bmx

Function ResetD3DDevice()
	_d3dDev.Reset( _presentParams )	
End Function

Same file, modify the TD3D9Graphics.Flip method to :-
	Method Flip( sync )
	
		Local reset

		If sync sync=D3DPRESENT_INTERVAL_ONE Else sync=D3DPRESENT_INTERVAL_IMMEDIATE
		If sync<>_presentParams.PresentationInterval
			_presentParams.PresentationInterval=sync
			reset=True
		EndIf
		
		Select _d3dDev.TestCooperativeLevel()
			Case D3DERR_DRIVERINTERNALERROR
				Throw "D3D Internal Error"
			
			Case D3D_OK
				If reset
					ResetD3DDevice

				Else If _attached
			
					Local rect[]=[0,0,_width,_height]
					Return _d3dDev.Present( rect,rect,_hwnd,Null )>=0

				Else
				
					Return _d3dDev.Present( Null,Null,_hwnd,Null )>=0

				EndIf
			Case D3DERR_DEVICENOTRESET
				ResetD3DDevice

		End Select
	End Method


Will need some testing on a variety of machines though before saying its a good fix.

The Dx7 driver suffers the same fate!


therevills(Posted 2012) [#7]
Cheers Dave, I came up with something similar but within the ResetD3DDevice method :)

The Dx7 driver suffers the same fate!

Where is the issue for DX7? I can't see the Reset method call...


col(Posted 2012) [#8]

Where is the issue for DX7?



Using the same scenario, putting DX7 into fullscreen then put the pc to sleep, during waking I get an error code that equates to E_FAIL at the DXASS function called from Line 482 in the _Validate method which is called from Line 509 in the Validate method.

Could be one for Mr S.
Dx7 is old now, surely people arent relying on it nowadays? Even MS dont have any docs for Dx8 on MSDN let alone Dx7! They dropped it years ago.


therevills(Posted 2012) [#9]
during waking I get an error code that equates to E_FAIL at the DXASS function called from Line 482 in the _Validate method


Ah yes, the _ValidateGraphics method, I did see that one but can't test here atm.

			If renderSurf.IsLost()<0
				DXASS _dd7.RestoreAllSurfaces()
			EndIf


In these example: http://read.pudn.com/downloads135/sourcecode/game/574390/Tank/CDDraw.cpp__.htm and http://nate.deepcreek.org.au/svn/DigitalWatch/trunk/src/OSD/DirectDraw/DWDirectDrawScreen.cpp

They do this:
        if (lpDDSPrimary->IsLost()==DDERR_SURFACELOST)   
            lpDDSPrimary->Restore();   
        if (lpDDSBack->IsLost()==DDERR_SURFACELOST)   
            lpDDSBack->Restore();  


BMax does: DXASS _dd7.RestoreAllSurfaces()



Oh and I found this MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/gg426207%28v=vs.85%29.aspx

Last edited 2012

Ah RestoreAllSurfaces is a convenience method. "Effectively, this method calls the IDirectDrawSurface7::Restore method for each surface that is created by this DirectDraw object. "

http://msdn.microsoft.com/en-us/library/windows/desktop/gg426153%28v=vs.85%29.aspx

Last edited 2012


col(Posted 2012) [#10]
Yep, Read that. It restores them all in one go. This surface is definitely lost too with error code $887601c2 :-

HRESULT: 0x887601c2 (2289435074)
Name: DDERR_SURFACELOST
Description: Access to this surface is being refused because the surface is gone. The DIRECTDRAWSURFACE object representing this surface should have Restore called on it.
Severity code: Failed


After that the surface(s) are all attempting to be restored with the _dd7.RestoreAllSurfaces()

That then fails with a code of $80004005 :-

HRESULT: 0x80004005 (2147500037)
Name: E_FAIL
Description: An undetermined error occurred
Severity code: Failed


Good find with the MSDN link! I obviously looked with my eyes shut! :P


therevills(Posted 2012) [#11]
Description: An undetermined error occurred


LOL! Great error message there!


col(Posted 2012) [#12]
I'm testing this on Win7 and if I recall correctly its emulated on it, and the latest gpu drivers probably arent too well tested for it anymore either.


marksibly(Posted 2012) [#13]
Hi,

Weird, this isn't happening here. I tried the code above (modified - see below) and it works in either d3d7/d3d9. The desktop shows briefly sometimes when the app is restored, but it eventually works.

Also tested with sleep vs hibernate (which you can do using a 'run as admin' console and 'powercfg -h on/off') and both work. Hibernate causes a 'sort of' system reboot here, but even then the app still recovers.

So I guess it's a graphic driver issue...? I'm on 64 bit Windows 7 SP1, with a GeForce GTX 460 and driver V295.73

Removing the error checking as you guys have done above should be harmless though, so next release will include these fixes.



Last edited 2012


therevills(Posted 2012) [#14]
Hey Mark,

My specs are in my sig: i7 920, 6GB DDR3, 896MB Nvidia GeForce GTX 275, Windows 7 64Bit and driver V296.10.

When I run your code (either DX7 or DX9), it does work fine... but when I force the sleep/hibernate with the batch file it crashes - Strange...

With the fix that Dave (Col) suggested it works fine with DX9, but of course DX7 still fails (due to the fix is in d3d9graphics.bmx).

Batch file:
echo.
echo. Sleeping
TIMEOUT /T 15 /NOBREAK
echo.
rundll32 powrprof.dll,SetSuspendState 0,1,0


Last edited 2012


col(Posted 2012) [#15]
Hi Mark,

How bizarre!
Your example works here too. I used a Sony Vaio VGN-FW31M.

If I use the power button to put the laptop to sleep and again to wake it, or use therevills batch file then I get the crash.


Grey Alien(Posted 2012) [#16]
So is this all fine now with Col's fix which Mark has now made standard?

Well apart from DX7 but that probably doesn't matter so much these days. For example if BFG test it on a relatively new machine, most of our games are using DX9 anyway and only fall back to DX7 if DX9 is not found so I bet they won't find the sleep/restore issue on DX7

Last edited 2012


GfK(Posted 2012) [#17]
It's not standard, yet. Therevills confirmed the bug in 1.48 and for PC, that's still the latest version.

Nobody's mentioned it in a while so I'm assuming col's fix is fine. Thanks for bumping this thread though - about a week from completion and I'd completely forgotten about this.


therevills(Posted 2012) [#18]
Well BFG passed my game with this fix :)


Grey Alien(Posted 2012) [#19]
Ah got it thanks, I only glanced at the code and thought it was the same but I see it's not quite.