FPS frustrations

Started by
24 comments, last by Erik Rufelt 8 years, 4 months ago
woah, quotes are messed up.
I tried to fix it but something is very screw-y. I preferred the forum software from 10 years ago lol.
Advertisement

I think your problem is almost certainly in DirectX or related, and not in your app.

Go into DirectX Control Panel (64 bit if your app is 64 bit), and then on the Direct3D 9 tab set all debug levels to max, and choose the Debug version. Then build in debug and run with the VS debugger so you get all debug output in the VS output window, and you should get warnings if you have any.

Once there are no warnings, set everything to release and no warnings in the control panel, then build a release version of your app and run that (without any debugger attached, like from Windows).

Also clean and reinstall your graphics drivers (latest non-beta version) and perhaps the DirectX runtime as well.

(If you don't have debug versions in the control panel you need to install the DirectX SDK I think..)

Also, if you have a bunch of debug prints or something disable all of those and all logging in release mode, such things could interfere. Text output in DirectX probably allocates buffers every frame as well so try disabling them as well just to rule it out.

Many Windows functions work differently and may use different memory allocators when run with a debugger from VS.

Well thanks for the tips everyone.

I ended up using the dreaded tight loop for a time delay, and turned off VSYNC. Seems to work so far, although the CPU is buzzing a little more than it used to.

At first I tried putting sleep(1) in my loop but as I suspected it was inaccurate. I was targeting 100 FPS but my actual FPS was anywhere between 92 and 100.

So I replaced it with sleep(0), and then my FPS was exactly 100 at all times, however the CPU spiked up to 100% (well, 25% since this is single threaded on 1 of 4 cores). The CPU fan was going crazy, and I knew I could not leave things like this.

So what I ended up doing is sleeping based on the time remaining. For example if I needed to sleep for 14 milliseconds, then I would basically do 12-13 sleep(1)'s and then sleep(0) until the remainder of the 14 millis was up. This way the CPU gets a break, but I'm still hitting exactly 100 FPS, which is a good indication that I have complete control over the game now.

I will do more testing and reply back if anything changes, but I think its looking good!

Are you doing window mode by the way?

If so that sounds like a pretty good solution, but if you do fullscreen you really should try to use vsync.. it will be quite apparent if the game has any camera movement and isn't vsynced.

Yup, Its a window'd game. But it may become fullscreen later, or at least have the option.

I don't understand why it would make a difference whether its fullscreen or windowed. I understand VSYNC eliminates tearing, but why does window vs fullscreen factor into it?

My faith in VSYNC has taken a beating from all the replies in this thread, plus the issue I experienced.

That may explain a lot of things. Vsync can't really be perfect in windowed mode.. though it depends on your OS and system settings. On Windows 8 and up (I think) they swap the whole desktop I believe.. so your Present actually just copies to another buffer (which is always RGBA Float16 I think, not sure exactly), and then swaps. Also not sure if this is actually true on desktop always or just on the metro stuff.. perhaps someone else here has done more apps targeting Windows beyond 7 and knows for certain?

There are some articles on MSDN about this stuff if you're targeting those systems.. they changed quite a bit. This is the reason (again, I think, or at least probably partly the reason) why you can't shut off the DWM composition on later Windows...

In general.. what happens if you have two Windows that both present their buffers to the screen, can they be VSynced?

The driver may be able to make this happen.. but it's sortof imperfect.. window mode is not really the target for vsync. There's also the whole frame-buffering issue. In fullscreen the driver will buffer up frames and schedule them for swapping when VSync is approaching, which isn't really enabled in windowed by default (you may be able to use some DXGI functions to override it, not sure, and probably also required latest Windows, as it's dependent on the new composition, again sortof guessing :)).. not sure if it's a technical issue in window mode or just that they don't bother, to avoid having to deal with edge cases when there are two apps running DX etc.

To get window mode VSync as good as possible, I've found the best way is to call Flush or Finish or whatever the function is called in your particular API version to make the driver finish everything on the GPU, then after that call Present with VSync or disable VSync and manually wait for it using DXGI or DirectDraw, to present when the last update is finished (VBlank I think it's called, the slight pause between one screen redraw finishes and the next begins).

Then make sure you wait between frames until that vblank is done so you don't present twice on the same vblank which can happen if your app would run at like 1000 FPS if it was allowed to, so combine with some wait or sleep like you have now.

This topic is closed to new replies.

Advertisement