How do I get rid of the delay when my program ends

BlitzMax Forums/BlitzMax Programming/How do I get rid of the delay when my program ends

sswift(Posted 2008) [#1]
When using OpenGL there's no delay when I end my program, but when I use Direct3D, there's a two second delay when the program ends before it goes back to the desktop when running in fullscreen mode.

Has anyone figured out how to reduce this delay? I don't see why there should be any delay at all.


tonyg(Posted 2008) [#2]
There's no noticeable difference in a test I just ran.
How about providing some example code which shows the problem?


sswift(Posted 2008) [#3]
I discovered something odd just now...

If I run the game fullscreen initially, it loads fast, but takes forever to quit.

Also, if I start the game in fullscreen, but switch to windowed mode, it takes forever to make the switch. But it will then toggle back and forth quickly and exit quickly.

However, if I run the game in a window initially, it loads fast, and it exits fast.

And finally, if I run the game in a window initially, then toggle to fullscreen, it takes forever to switch to fullscreen, but once fullscreen it will exit fast and toggle back and forth between windowed and fullscreen fast.


sswift(Posted 2008) [#4]
How about providing some example code which shows the problem?





Change the loop at the start to load a large image, say 800x600. Run the program. It will run in fullscreen, display a mouse cursor only, and with one image loaded it should exit fullscreen immediately when you hit ESC.

Now try changing the loop to load 10 images. There should be a significant pause before it exits when you hit ESC. If not, try 100 images.

Pressing F will toggle between fullscreen and windowed. Changing the App.Create() function call so that the first True is a False will make the app begin in a window. You may then test it to see if it pauses when you press F to toggle to fullscreen. The window will dissapear while it's taking its time switching modes. This indicates that it executes everything up to the HideGadget Window call in the SetFullscreen() function.

I suspect the point where it chokes in both scenarios is the If TG_Fullscreen = Null Then TG_Fullscreen = Graphics(Width, Height, Depth) line in the SetFullscreen() function.


tonyg(Posted 2008) [#5]
If I set to 100 then I get an Unhandled Memory Exception as the array is only declared for 100 (e.g. 0 to 99).
If I press 'esc' quickly then I get the delay but, my guess, is it is still in the image loading loop. If I wait for 10-15 secs to ensure the load has ended to seems to esc immediately.
<edit> Sorry if I have missed something. I added
		For Loop = 1 To 99
			IMG_Dust[Loop] = LoadImage("background.png")
			Print "doing"
		Next
		
		Print "Done"

and whenever I hit 'esc' I always see 'done' printed as it can only end once out of the loop. (e.g. the 'ESC' key is buffered for reading after the loop.

<EDIT> You might also want to make your example code a bit simpler.


sswift(Posted 2008) [#6]
Yeah, I just checked it, and the test code isn't reproducing the error after all.

However, the problem is real, and I'm sure that the error isn't in my code.

When you hit ESC in the game, it's just like in this demo. It simply calls END. You can be playing the game, hit ESC, and it freezes up for a little bit before going back to the desktop. And the issue doesn't present itself when running in OpenGL.

Maybe the problem is the images aren't being drawn to cause them to be cached. I'll try that.


sswift(Posted 2008) [#7]
Hm... nope. Loading the same large dust image 50 times and drawing each one doesn't expose the issue. Nor does loading 30 different smaller images of enemies which I load when my game begins.

Doesn't make any sense. :-(


tonyg(Posted 2008) [#8]
I would have debug/trace messages in all functions/methods but, more specifically, I would have 'esc' key call onend() which draws some text or an image. If that is seen before the delay then it's probably some clean-up happening in DX and not OGL.


sswift(Posted 2008) [#9]
I don't see how making ESC print something would provide me with any additional information. I already know that keyboard input gets responded to instantly.

And debug messages if I can work out a way to see them will almost certainly show me that it freezes at that fullscreen set graphics line.

As for it being some kind of clean up, that was the first thing I suspected but the fact that the delay happens when going from windowed to fullscreen and then never again doesnt really fit that theory.

I'll see if I can prove it's locking up at the graphics line though. Maybe I can have it play a sound.


sswift(Posted 2008) [#10]
Okay I did the sound test. When in windowed mode and switching to fullscreen, it seems like, the FreeGadget Canvas line in the fullscreen() function is the culprit.

But that doesn't mean much because a simple END is the culprot when the game starts in fullscreen mode and you attempt to quit.

But maybe end calls FreeGadget internally and freeing that canvas the first time it's created causes the hiccup. No idea why recreating it and freeing it again would not exhibit the same behavior though.


tonyg(Posted 2008) [#11]
I don't see how making ESC print something would provide me with any additional information. I already know that keyboard input gets responded to instantly.

it was the delay from hitting esc to onend displaying anything to the program finishing I was suggesting might be useful.

And debug messages if I can work out a way to see them will almost certainly show me that it freezes at that fullscreen set graphics line.


... write them to a log with a statement when you hit 'esc' during onend(). Again a suggestion because, basically, you have all the code I am having to make guesses.
As for it being some kind of clean up, that was the first thing I suspected but the fact that the delay happens when going from windowed to fullscreen and then never again doesnt really fit that theory.


Unless there is some cleanup when switching for the first time. Again, I haven't got any code to recreate so am guessing.
Anyway, you seem to have it well in hand and seem intent on keeping all the information to yourself so... good luck.


ImaginaryHuman(Posted 2008) [#12]
Maybe it has to reload/wipe images in video ram as you switch?


sswift(Posted 2008) [#13]
Speculation of this nature isn't really gonna help things. I was really hoping someone else had encountered this issue themselves and could confirm that way that it is in fact a BlitzMax issue so that maybe I could then convince Mark to look into it.

It's obviously some kind of graphics related issue, and given that it doesn't occur when using OpenGL it almost certanly is either a limitation of DirectX, or a problem with how BlitzMax is shutting down/starting up DirectX apps.

Unfortunately since we don't have access to the code that does those things, the only person who can really be of any help with this problem is Mark or Simon or whoever the other guy working on the code is.

I already know the lines where the delay occurs. One is "FreeGadget Canvas" line, and the other is "End".

The issue's clearly something internal, dealing with freeing up something DirectX graphics related, and no amount of debug logging is going to provide me with any more information about what is going on.

Putting code in OnEnd() is pointless. It won't tell me anything. We'd have to know what shutdown code is actually executed before and after that for it to narrow down the problem.


GaryV(Posted 2008) [#14]
It sounds like you are using Vista


sswift(Posted 2008) [#15]
Nope. XP.

And one of the latest Nvivia graphics cards.


GaryV(Posted 2008) [#16]
hmm... the only time I have run into what you described is on Vista systems and I chalked it up to DX7 being emulated. :/


MGE(Posted 2008) [#17]
" there's a two second delay "

That's not an application killer by a long shot. ;) I've experienced the same delay, sometimes it's 1 second, sometimes it's 2-3 seconds. I think it's related to how much graphics are in the gpu at the time the program calls "EndGraphics()". I would guess images in the gpu are being flushed, copies in sram are being flushed, etc.

I didn't really think anything of it. If it was 10 seconds or longer, I would be very concerned though.


Arowx(Posted 2008) [#18]
As a work around could you close/hide the window before ending?

Then the user does not see a delay?

e.g. CloseGraphics() or EndGraphics()

Just a thought but could there be any connection to the polled input mode which is started with the Graphics?


sswift(Posted 2008) [#19]
No, the problem isn't running in a window. Running in a window the game opens fast and exits fast.

It's only when toggling from windowed to fullscreen, or from fullscreen to windowed, or starting in fullscreen and exiting from there, that the game hangs up for a bit.

Though I haven't tried minimizing/tabbing out of the game from fullscreen to see what happens there. Guess that's an area I could explore.


Just a thought but could there be any connection to the polled input mode hich is started with the Graphics?


Unlikely, because the delay doesn't just happen when switching to fullscreen. It also happens when toggling from fullscreen to windowed mode and when exiting.

[edit]

Alt-tabbing out of the app is fast. Don't know yet if minimizing from within the app is. Also, alt-tabbing out, then returning to fullscreen does not get rid of the delay when ending the program.


sswift(Posted 2008) [#20]
Argh, now I've got a new issue. When tabbing out and back, blitzmax resets the projection matrix, so my code to display everything the same regardless of video resolution breaks, and everything gets stuck in one small corner of the high res screen because it's rendered at 800x500 but should be stretched over 1920x1200.

I thought it was an easy fix. When switching from windowed to fullscreen, I just call my function that sets the projection matrix again after I set the graphics up. But for some reason, when tabbing back into the game, even though my code is in there for setting the projection matrix up again when the APPRESUME event occurs, it doesn't put things back the way they were.

It's almost as if BlitzMax is giving my app the APPRESUME event first, and then it gets around to setting up the graphics again afterwards.

Also, the events it triggers are weird. This is what I get when loading the game fullscreen, alt-tabbing out, then alt tabbing back in, and quitting:

DebugLog:EVENT_WINDOWMOVE
DebugLog:EVENT_WINDOWSIZE
DebugLog:EVENT_APPRESUME
DebugLog:EVENT_APPRESUME
[TAB OUT]
DebugLog:EVENT_APPSUSPEND
DebugLog:EVENT_APPSUSPEND
DebugLog:EVENT_APPSUSPEND
[TAB IN]
DebugLog:EVENT_APPRESUME
DebugLog:EVENT_APPRESUME

Why three suspend events and two resume events when the app is alt-tabbed out of?


Muttley(Posted 2008) [#21]
What I had to do with the retroremakes framework to sort out the projection matrix issue you describe

Method CheckIfActive()
	If AppSuspended()
		TGameEngine.GetInstance().LogInfo("Game Suspended")
		rrPauseSound(True)
		Local susTimer:TTimer = CreateTimer(60)  'temporary timer to help free up CPU when game suspended
		'wait until app is active again
		While AppSuspended() 
			WaitTimer(susTimer)   'Do nothing and free up CPU
		Wend
		TGameEngine.GetInstance().LogInfo("Game Resumed")
		If Not windowed
			'When resuming from minimised full-screen display we need to recreate Grahics
			'and set up the projection matrix again due to DirectX oddness
			TGameEngine.GetInstance().LogInfo("Resetting Graphics Mode")
			Reset()
		EndIf
		'Reset the fixed timestep timer so we don't have any glitches
		rrResetFixedTimestep()
		rrResetFPS()
		rrPauseSound(False)
	EndIf		
End Method


The Reset() method does EndGraphics(), creates the Graphics mode again and then sets up the projection matrix again.

If you want to check all the code you can grab it from the Google Code link in my signature.