Jump to content


Infinite Window


21 replies to this topic

#1 _NOISEcore

    Member

  • Members
  • PipPip
  • 31 posts

Posted 27 September 2011 - 07:44 PM

Hi there.

I often create little projects, and I at the moment I have a basic window creation & message loop (handling) set up.
But often, my message loops result in the "infinite window" bug when
moving the window. This is just minor of course, but this always bugs me out.

Does anybody know what actually causes this? Is it because I'm not
double buffering yet?

Here's a link to a screenshot if you don't know what I mean with the "Infinite Window" bug.
http://imageshack.us...nitewindow.jpg/

#2 }:+()___ (Smile)

    Member

  • Members
  • PipPipPip
  • 169 posts

Posted 27 September 2011 - 09:05 PM

Do you have any wait function in your message loop? Maybe your application eats all CPU and other applications doesn't have required processor power to redraw windows?
Sorry my broken english!

#3 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 27 September 2011 - 10:53 PM

Indeed. Can you post the code for your message loop?
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#4 _NOISEcore

    Member

  • Members
  • PipPip
  • 31 posts

Posted 28 September 2011 - 12:54 AM

Well, atm it's a very basic message loop. I need to add a timer when I get up in the morning :)


MSG msg = {};

	while(msg.message != WM_QUIT)

	{

		// Send the message if one is found

		if(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))

		{

			TranslateMessage(&msg);

			DispatchMessage(&msg);

		}

	}



#5 Reedbeta

    DevMaster Staff

  • Administrators
  • 5311 posts
  • LocationSanta Clara, CA

Posted 28 September 2011 - 01:02 AM

Well, there's your problem! PeekMessage doesn't wait if there's no message available, so your app just sits in that tight loop taking up 100% CPU and not giving the other apps much chance to run. ;)

It doesn't look like you're doing any rendering yet. Once you do, you'll presumably be waiting on vsync at the end of rendering, so this problem will go away. You could also put a Sleep(0) call in the loop, although it's probably not good to have that in there long-term.
reedbeta.com - developer blog, OpenGL demos, and other projects

#6 _NOISEcore

    Member

  • Members
  • PipPip
  • 31 posts

Posted 28 September 2011 - 01:06 AM

Yeah, basically how I usually do it, I set an if else loop, where in the if it checks for a message, if none is found, it checks if the minimum time for a frame (max frame cap) has elapsed yet and renders/thinks if so.

Will this make the "infinite window" go away? Because usually when I get to that point in programming, I already use a fullscreen (which I won't in this program)

#7 Reedbeta

    DevMaster Staff

  • Administrators
  • 5311 posts
  • LocationSanta Clara, CA

Posted 28 September 2011 - 01:53 AM

Well, what does it do if the minimum time for a frame *hasn't* elapsed yet? If you do a Sleep(0) or something in that case, you should be fine, as you'll yield the rest of your time-slice back to the OS. But if you just sit in a loop and don't do anything that suspends the thread, you'll keep taking up 100% CPU and making it hard for anything else to run.

IMO, the right way to do this is to configure your rendering API to wait for vsync, and if the API is built properly this should suspend the thread until the vsync clears, which will have the side effect of reducing the CPU utilization to a more reasonable level.

For reference, here's my message loop:
MSG msg;
while (true)
{
	if (g_fRendering)
	{
		Update();
		Render();

		while (g_fRendering && PeekMessage(&msg, NULL, 0, 0, true))
			DispatchMessage(&msg);
	}
	else
	{
		if (!GetMessage(&msg, NULL, 0, 0))
			break;
		DispatchMessage(&msg);
	}
}

The g_fRendering flag gets set to false when you minimize the app, or when it starts shutting down; in that case I use GetMessage, which waits for a message, rather than PeekMessage. Down inside the Render() call I'm eventually calling Present() (since I'm using D3D) and telling it to wait for vsync, which both prevents tearing (usually...) and suspends the thread so that other apps can run.

It's also important to handle *all* available messages after each rendered frame, not just one, hence the PeekMessage in the inner while loop. Otherwise messages can back up and overflow the queue because you don't process them fast enough. Mouse moves especially can generate several messages per frame.
reedbeta.com - developer blog, OpenGL demos, and other projects

#8 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 28 September 2011 - 10:58 AM

What I usually do is using SetTimer() to let Windows post a WM_TIMER to my message queue every x milliseconds (the minimum is 10, which gives you 100 messages per second), and then do my rendering in response to a WM_TIMER. Automatic frame limiter ;)
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#9 _NOISEcore

    Member

  • Members
  • PipPip
  • 31 posts

Posted 28 September 2011 - 02:37 PM

Reedbeta said:

The g_fRendering flag gets set to false when you minimize the app, or when it starts shutting down; in that case I use GetMessage, which waits for a message, rather than PeekMessage. Down inside the Render() call I'm eventually calling Present() (since I'm using D3D) and telling it to wait for vsync, which both prevents tearing (usually...) and suspends the thread so that other apps can run.

It's also important to handle *all* available messages after each rendered frame, not just one, hence the PeekMessage in the inner while loop. Otherwise messages can back up and overflow the queue because you don't process them fast enough. Mouse moves especially can generate several messages per frame.

If you do this, how would you then set in a frame limiter? Would you do that inside the scope where Update & Render get called?

#10 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 28 September 2011 - 02:49 PM

No, I would do that in the message loop itself. Calculate how much time there's left before you want to do another frame, and use MsgWaitForMultipleObjects() to wait for a message with a timeout, and use as the timeout the time until the next frame you just calculated.

But as said, I would just stick to SetTimer(), it makes your code clean and simple.
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#11 Reedbeta

    DevMaster Staff

  • Administrators
  • 5311 posts
  • LocationSanta Clara, CA

Posted 28 September 2011 - 04:59 PM

_NOISEcore said:

If you do this, how would you then set in a frame limiter? Would you do that inside the scope where Update & Render get called?

Frame limiting is taken care of by the vsync. I don't have a need to limit to some arbitrary rate like 100 fps; I only ever want to run at the refresh rate (or divisors thereof).
reedbeta.com - developer blog, OpenGL demos, and other projects

#12 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 28 September 2011 - 05:09 PM

Some people turn off vsync. You'd better still have some other means to limit the framerate available as well. Besides, there is no vsync in windowed mode.
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#13 Reedbeta

    DevMaster Staff

  • Administrators
  • 5311 posts
  • LocationSanta Clara, CA

Posted 28 September 2011 - 06:10 PM

.oisyn said:

Besides, there is no vsync in windowed mode.

Uhm...what? ;) I'm using vsync just fine in windowed mode in my own Direct3D app...
reedbeta.com - developer blog, OpenGL demos, and other projects

#14 _NOISEcore

    Member

  • Members
  • PipPip
  • 31 posts

Posted 28 September 2011 - 06:36 PM

Well, the problem is that I'm currently working on a little project for school (sort of) that tries to make as much use of GDI as possible.

So I don't really have access to VSYNC (I think), in which I just switch to limiting the framerate to the refresh rate of the screen (or more if desired)

That's why I need to implement the timer :)

#15 }:+()___ (Smile)

    Member

  • Members
  • PipPipPip
  • 169 posts

Posted 28 September 2011 - 07:36 PM

For simple game you don't need to redraw every frame (for tetris you must redraw on button press & timer tick only). Put you drawing code in WM_PAINT handler (together with ValidateRect if needed) and call InvalidateRect when you need to update window contents.
Sorry my broken english!

#16 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 28 September 2011 - 09:39 PM

Reedbeta said:

Uhm...what? :huh: I'm using vsync just fine in windowed mode in my own Direct3D app...
It appears that you are right. I don't know where I got this from ;)
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#17 _NOISEcore

    Member

  • Members
  • PipPip
  • 31 posts

Posted 29 September 2011 - 09:50 AM

'}:+()___ [Smile said:

']For simple game you don't need to redraw every frame (for tetris you must redraw on button press & timer tick only). Put you drawing code in WM_PAINT handler (together with ValidateRect if needed) and call InvalidateRect when you need to update window contents.

I actually haven't thought of that. I still need alot of "lessons" on effeciency :)
Thank you !

EDIT: I do have an additional problem atm. Well 2, concerning the same things.
First of all, my message loop looks like this:
        MSG msg = {};
	while(msg.message != WM_QUIT)
	{
		if(m_bActive)
		{
			// If the window is active

			while(m_bActive && PeekMessage(&msg,NULL,0,0,PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}

			Sleep(0);
		}
		else
		{
			if(!GetMessage(&msg,NULL,0,0))
				break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

The problem is, m_bActive gets set to false when WM_ACTIVATE with wParam being WA_INACTIVE, and else it gets set back to true.
When I click away, this works, but when I just minimize it keeps using thesame CPU amount as when activated.

This comes to my second problem, at the moment my program doesn't do that much, but yet it uses 25% of my CPU (dual core so..)
This is probably because of me not returning the remainder of my time slice, but I don't know how to do this. They say with Sleep(0)
but this doesn't seem to do anything.

#18 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 29 September 2011 - 11:01 AM

Please, don't resort to Sleep(0), it's bad practice for the purpose you're using it for.

Quote

hey say with Sleep(0) but this doesn't seem to do anything.
It does, but if there's no other process who wants CPU time it still goes to your app.
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#19 _NOISEcore

    Member

  • Members
  • PipPip
  • 31 posts

Posted 29 September 2011 - 02:32 PM

If sleep is a bad practice, what should I use then? MsgWaitForMultipleObjects ?

#20 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 29 September 2011 - 02:47 PM

I'm not saying Sleep is bad practice, I was talking about Sleep(0). You don't want to just give up the remainded of the time slice, you want to wait until it's time for the next frame. So you should calculate how long you'd like to wait.

And you can implement the wait with Sleep(), but the downside is that you're unable to process messages when you're sleeping. So MsgWaitForMultipleObjects() is, in my opinion, the better choice.
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users