Posting here just to say
thanks for the great advice in this thread, as it amazingly solved my sooo frustrating problem with ACC.
So my issue was micro-stuttering in hotlaps (much worse in races), usually when turning (or at least that's when it was most noticeable) to the point I couldn't enjoy the game and even ruined my laptimes. My system is RTX2080ti (slightly OCed), i9 (non-OCed), RAM @3200MHz.
This is what I mean, hotlapping at Zandvoort on epic @ 3325x1871, v-sync on, in-game frame limiter @ 60fps:
Okay, the resolution is clearly high and epic is overkill, I know, so I didn't mind turning them down (even though I'm at GPU load < 80%, which is suspicious). To my frustration, same results @ 2715x1527, v-sync on, frame limiter @ 60fp:
I got the same results when lowering epic to high, and it was obvious there was something else going on. So I tried a myriad of things, from HPET, to disabling fullscreen optimizations, disabling all kinds of overlays (game bar, steam, nvidia experience etc), ultra low latency mode, prefer maximum performance mode, measuring the exact refresh rate of my monitor (turns out it is 60.001), pfff lowering the temps at my system... haha I was so desperate.
Using in-game fps limiters usually is a bad idea because of huge input lag penalties due to bad coding.
And then I came across this... boom, mind blown!! Why on earth would an in-game frame limiter work so badly?
This is what I get now on epic @ 3325x1871, v-sync on, with RTSS frame limiter @ 60fps (in-game limiter off):
(side note: Unfortunately I couldn't also use scanline as it insists on capping me at 30fps but anyways...)
So, the obvious dilemma now was 60fps or 59.99fps? Because I can't
consistently tell the difference (my poor man's test is I switch v-sync option many times while not looking at it until I lose count and then apply and check with the in-game wheel if I can guess corrently 8 or more times out of 10).
It boggles my mind that such a setting can possibly be a good thing. Can't understand it, not one little bit!
Exactly!!
My knowledge of graphics/DX/internals in general is very limited and I have seen no docs or code besides scattered information online like the posts in this thread, but nevertheless I tried to run it "on paper" and see if it actually makes sense. And it seems it does, so I'll share my reasoning and hopefully someone will (in)validate it. But please
take it with a grain of salt as like I said, I have no clue what goes on behind the scenes, besides double buffering and v-sync.
For the sake of this example, I'm assuming a 10Hz display (refreshes every 100ms), and a stable frame output time of 60ms. Start with both buffers full, gpu idle and monitor ready to display contents of front buffer.
(fb: front buffer, bb: back buffer, fn: n-th frame, "fn begins on bb": gpu begins rendering frame n on the back buffer )
[v-sync]
0000ms: display f0 / fb = f1 / f2 begin on bb
0060ms: f2 complete
0100ms: display f1 / fb = f2 / f3 begin on bb
0160ms: f3 complete
0200ms: display f2 / fb = f3 / f4 begin on bb (200ms input lag)
0260ms: f4 complete
0300ms: display f3 / fb = f4 / f5 begin on bb (200ms input lag)
(Seems like input lag here averages 2 x refresh interval under the assumption of 1 back buffer)
[v-sync + 10fps/100ms limiter]
0000ms: display f0 / fb = f1 / f2 begin on bb
0060ms: f2 complete
0100ms: display f1 / fb = f2 / f3 begin on bb
0160ms: f3 complete
0200ms: display f2 / fb = f3 / f4 begin on bb (200ms input lag)
0260ms: f4 complete
0300ms: display f3 / fb = f4 / f5 begin on bb (200ms input lag)
(I believe there must be some element of luck in the above, e.g. what if the limiter and the refresh rate is de-synced in such a way that frames are completed right before a buffer swap? Assuming the gpu load is well under 100%)
[v-sync + 9.901fps/101ms limiter]
0000ms: display f0 / fb = f1 / f2 begin on bb
0060ms: f2 complete
0100ms: display f1 / fb = f2
0101ms: f3 begin on bb
0161ms: f3 complete
0200ms: display f2 / fb = f3 (200ms input lag)
0202ms: f4 begin on bb
0262ms: f4 complete
0300ms: display f3 / fb = f4 (199ms input lag)
0303ms: f5 begin on bb
0363ms: f5 complete
[...skip to the 41st refresh...]
4040ms: f42 begin on bb
4100ms: f42 complete
4100ms: display f41 / fb = f42 (161ms input lag)
4141ms: f43 begin on bb
4200ms: display f42 / fb unchanged (160ms input lag)
4201ms: f43 complete
4242ms: (would render f44 but bb is occupied, so idles and we should see a dip in fps)
4300ms: display f42 / fb = f43 (260ms input lag + stutter)
4300ms: f44 begin on bb
4360ms: f44 complete
4400ms: display f43 / fb = f44 (259ms input lag)
4401ms: f45 begin on bb
4461ms: f45 complete
4500ms: display f44 / fb = f45 (200ms input lag)
4502ms: f46 begin on bb
4562ms: f46 complete
4600ms: display f45 / fb = f46 (199ms input lag)
(back to where we started)
So my understanding is the fractional frame limiter is basically "holding" the gpu back (a tiny bit more every time) so as to fill the back buffer all the more closer to the consumption of the front buffer by the monitor. It's doing it slowly but it's still better than nothing. The above goes from 200ms lag down to 160, where it stutters and then repeats. It is an average input lag of ~184ms, which is only an 8% improvement. But! This improvement depends on gpu load (frametime with respect to monitor refresh rate), as well as on how small a fraction of the refresh rate we choose (if the stutter is too often, the input lag that comes with it is significant). At least, my conclusion based on this aligns with what others recommend online: keep the load low, and the fraction as small as possible. And it also aligns with my inconsistency to detect input-lag during my tests (I was using a 59.999 limit). Oh, and if you're simracing, choose monza to increase your chances of having the stutter in the straights
(no I don't like monza).