New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vsync broken? #1184
Comments
I tried a few different things there. The only one that worked was private TimeSpan _targetElapsedTime = It would appear that all of the TimeSpan.From*(double) methods round to |
Yeah, this should be changed to TimeSpan.FromTicks. From MSDN: |
Fixes issue #1184 TimeSpan.FromSeconds() has an accuracy of 3 decimal places only. TimeSpan.FromTicks() is more accurate, resulting in the expected target elapsed time of 0.0166667 rather than 0.017. Reference: http://msdn.microsoft.com/en-us/library/system.timespan.fromticks.aspx
I still can't seem to disable vsync with monogame? |
What platform? There are certain platforms where you cannot... like Windows Store and iOS. |
@tomspilman WindowsGL and your windesktop-DX branch. |
I'm going to re-download/rebuild the repository and see if Vsync is achieved now. |
With Vsync enabled now it reports 59 FPS. I dont know why. My monitor refresh rate is 60Hz (60 fps)? So Vsync is still not happening. |
TargetElaspedTime is achieved by sleeping off remainder time... sleep is not exact. We do this instead of blocking because it frees the CPU time for other processes. This is something MS XNA on the desktop does not do... it will chew up all the CPU as long as the Game is in the active state. I would expect any calculation of actual FPS to be like 59.8 or 59.9 or something. If you really want to be blocked on VSync... set IsFixedTimeStep to false. Then VSync will block and you will be at a solid 60fps... and at 100% processor usage. |
Oh I see, are we unable to implement the XNA solution because of legal reasons? or other reasons (not supported on other platforms?) |
Is it causing a real issue? Or is it a case of the FPS reporting 59 instead |
It means Vsync isn't achieved, the graphics.SynchronizeWithVerticalRetrace property becomes useless. Both SharpDX.Toolkit and XNA report 60 FPS with Vsync on. |
We of course cannot legally copy their code... we can copy their behavior. In this case I made the decision to do something better than they do. If it has a bad side effect then lets see about fixing it. If you can build a zip with a simple test case that exhibits the issue i can investigate it. |
No problem, doing that now. |
I'm new to github and I cant find a attach file function. I just uploaded it to my sites FTP. http://www.xanather.com/MonoGameTest.zip Thanks for the help. My monitor has a refresh rate of 60Hz so enabling graphics.SynchronizeWithVerticalRetrace = true; should make the framerate become a solid 60 per second. It does not, this results in every x amount of time that the ball texture (in the test) becomes jittery for a bit - its just not smooth like it should be in any other vsync enabled presenter. The reasons why this concerns me so much is because having that sort of problem would not be good in a 2D side scroller (the whole display would become jittery). When I tried the MonoGame 2.5.0.0 windows project this problem did not exist, but like you say in the previous post that project did use 100% of a CPU core. I think the way SharpDX TK or XNA handled it would be a better solution. |
I'm looking at your test case and I do not see any jitter. Where would I see it? How do you know it isn't running at 60fps? |
Ok... got a jitter now. I had to switch away from it a few times then I got it for a little bit after. I see two potential culprits here... Sleep and Stopwatch. I'm investigating. |
I used fraps to see what the fps is (using that fps overlay). Yeah, it is hard to tell, but it would really show if it was a fullscreen game with scrolling/moving textures everywhere. |
So I have some initial findings. While there are some fixes to the logic we can do to smooth things out, there is one fundamental issue affecting us.... thread affinity. What is happening is that Stopwatch can return incorrect time (both elapsed or timestamps) if the thread switches cores between calls. This happens a lot more than you think.... the process thread bounces around like crazy. @xanather - Try this to verify what I found! If like in XNA (you can see it in Process Manager) you add this to your Game constructor:
You should see the jitter instantly go away almost entirely (i still see one hiccup every few minutes... that is another topic). Now setting affinity totally sucks.... it means everything is forced to that one core. If you have two instances of your game... or just two instances of a MonoGame/XNA game running on the same PC, they all pile on that one core instead of spreading out across all your cores. This cripples the OS and keeps it from smartly scheduling work. The other alternative is to not depend on Stopwatch. Our best second choice is Environment.TickCount:
This would bottleneck us at 1000 FPS. In practice this is fine, but I know some people cry if they don't see +3000 FPS on an empty vsync disabled game. The overflow is the harder issue... while most people won't play a game 29 days straight we should still allow for it (servers for one come to mind). So what I am thinking is writing a new Timer class. Internally it uses both Stopwatch and TickCount. When you want elapsed time it returns the smaller positive value between the two timers. This should ensure at least millisecond resolution when the process jumps cores and protects against the TickCount 29 day overflow. Thoughts? |
We had used the SetProcessorAffinity() solution on older PC games. You The overflow in 29 days can be accounted for as well, by checking for a |
@tomspilman ill try that right now |
I have interesting finds on my computer, it does work (sort of). It I debug/run the program and don't touch it, it does run at 60 FPS and the jitter is gone (well it happens once every minute like you say as well), but as soon as I start clicking on other windows and going back to the MonoGame window the FPS drops back down to 59 FPS and the jitter is back, does this happen to you? |
Are you sure time stamp wont suffice? SharpDX TK uses that: |
I have started to avoid looking closely at SharpDX Tookit code. I am concerned some of it comes from using reflector on XNA. Still... no Stopwatch.GetTimestamp() is just as bad... it uses the same hardware performance counter and has the same sort of jump when switching between cores. |
Ah alright no problem. Well if you do manage to create that timer class that would be great, the disadvantages of setting the affinity seems like a bad solution. I am still lost as to why I still receive 59 FPS with Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)1; after messing with the window a bit. |
Bumping this issue (if thats ok, otherwise I need to know if there are rules against this), I still think this issue needs to be solved. It really does pretty much make the v-sync properly useless. |
Right, probably the cause then. |
With my current project the XNA version just runs slower when it doesn't |
bump |
I still haven't found the time to work on this issue specifically, but we are starting a big new PC project so I will eventually get to it. |
Cool, I can obviously develop my game around this so it isn't that big of a deal considering the amount of PR's I see right now. I just like to bump it once in a while so it does not get forgotten. |
bump |
3 similar comments
bump |
bump |
bump |
So I managed to fix this myself. In the end I just did (I don't know why I didn't think of this before really...): TargetElapsedTime = new TimeSpan(163000); This makes room for the core jumping and any lost time that occurs. The game no longer has any jitter (except for once every minute obviously). For fixed time step games (I know, I know, fixed time step games are frowned upon) I really think this should get properly fixed. I did try messing with the timer recently but to no avail (I made things worse haha). Ill leave this issue open. Edit: I have a feeling this will produce different results on different processors though. |
As expected, my change will produce different results on different processors. @tomspilman should I create a whole new issue around this subject (current issue title seems misleading)? My laptop receives much less jitter than my desktop (I have hyper threading on my desktop). Also when I give my game to friends to be tested and I specifically ask them "can you see any fps lag/jitter" and they always reply with nope. Environment.TickCount last I checked also had a 10 millisecond time frame. |
FYI. @RayBatts is working on vsync support for Windows DirectX platforms. We should have a PR for it in the next day or two. Note this is the ability to disable vsync, but it is a start towards fixing this issue. |
Thanks, I actually did end up fixing the V-sync issue by using the following code:
I didn't make a pull request yet because this would affect all platforms and could be a unwanted change for others. |
@tomspilman what do you think about the code I posted above? I have been using it for the last 2 weeks and it works very well at fixing the FPS at 60 (even when the CPU is under stress and thread jumping may occur). |
I did some experiments with it and have some similar/better code. I just haven't submitted a PR for it yet. Instead of throwing away the remainder time... it just realigns it a bit. |
That seems like a better solution :) I definitely test the changes in my 2D sidescroller that is very sensitive to timings & smooth FPS. |
Did you end up finishing this PR? Is a submit possible? My solution does work okay at times, but at some times the goes out of align and I don't know how to realign it. |
Hi, Just wondering if this ever got looked at. I'm looking to integrate my game back into MonoGame for cross platform support. SharpDX Toolkit FPS timings are pretty much perfect and Vsync works well no matter what monitor your using. Thanks, |
VSync under DirectX platforms works. Don't think Vsync is implemented on any OpenGL platform beyond the mobile ones. |
Affects issue MonoGame#1184
This appears to be implemented in OpenTKGamePlatform.cs:98 But only used on Linux: GraphicsDeviceManager.cs:525 How do you change vsync in XNA? Does this take place directly or in |
Affects issue MonoGame#1184
I was primarily talking about the timing issue which results in Vsync being a failure in any circumstance anyway (WinDX is also affected). It could be fixed since the last time i tried so I will get my game working with MonoGame again soon and report back. |
That seems like your opinion... as for us vsync works, no tearing and limited to 60fps. |
I should have mentioned, this is for fixed timestep games. A variable timestep game works fine since it becomes limited to the screen rate. When you specify a fixed time step game of 60 FPS and you try to apply Vsync to a 60 hz monitor, sometimes the monitor rate can be slightly off and the game becomes limited to whatever monogame's timings are (resulting in often frame jumps/lags, not actual frame tearing). SharpDX Toolkit and XNA are both happy properly syncing the timing to the monitor refresh rate if thats the case. I would say this is more noticable in 2D sidescrolling games since its basicalling/sliding a moving image and very sensitive to stuff like this. |
This is exactly the same as (which I also posted)
#1085
I haven't played around with MonoGame for a little while but I came back and the problem still exists. I'm not sure if its just windows only or other platforms are affected by this.
Whenever I debug a new windows MonoGame project the TargetElaspedTime of the Game class returns a tick rate of 170,000 ticks, not 166,666 ticks. Which I think results in 60fps not being achieved and Vsync not available for most monitors.
Looking at the actual MonoGame code that sets this value:
private TimeSpan _targetElapsedTime = TimeSpan.FromSeconds(1 / DefaultTargetFramesPerSecond);
When I actually try that method on .net 4.5 it surely does return 170,000 ticks.
Does this need to be changed?
The text was updated successfully, but these errors were encountered: