Micro stutter randomly occurs
Whenever I use prboom plus 2.6.2 and dev builds above it my game will randomly stutter and skip from frames. I am running the game on a machine that is more than capable of running even the most demanding maps. I also run the game in opengl rendering in case that may be part of the problem. I have notice this also occurs in DSDA DOOM, running the latest version, so the issue can be fundamental to prboom or just my pc.
Is there any consistent trigger for when it happens? For instance, I've heard some players experience a stutter the first time certain sounds play. Is it completely random or is there a common factor at play?
Do you have uncappted framerate enabled?
Can you reproduce this issue with capped framerate?
Is there any consistent trigger for when it happens? For instance, I've heard some players experience a stutter the first time certain sounds play. Is it completely random or is there a common factor at play?
Now that you mention that it is entirely possible that is the case since I remember it happening whenever a new enemy appears. And if that is the case is there anything I can do to resolve it?
Do you have uncappted framerate enabled?
Can you reproduce this issue with capped framerate?
I have yet to try capping it with turning off uncapped frame however I have tried capping the frame rate via v sync as well as capping it with Nvidia control panel.
I have yet to try capping it with turning off uncapped frame
Please try capping framerate using the in-game configuration option and see if the issue is resolved.
I have yet to try capping it with turning off uncapped frame
Please try capping framerate using the in-game configuration option and see if the issue is resolved.
Turning off "uncapped framerate" does resolve the issue however I do prefer the smoothness that comes having a high framerate so I would like to find a way to keep it on.
Turning off "uncapped framerate" does resolve the issue however I do prefer the smoothness that comes having a high framerate so I would like to find a way to keep it on.
You can try vsync and see if the issue resolves. If not, you will need to play with capped framerate. You can increase the fps limit in dsda-doom to try and find a smooth fps that avoids the stutter.
Turning off "uncapped framerate" does resolve the issue however I do prefer the smoothness that comes having a high framerate so I would like to find a way to keep it on.
You can try vsync and see if the issue resolves. If not, you will need to play with capped framerate. You can increase the fps limit in dsda-doom to try and find a smooth fps that avoids the stutter.
ok I have been testing that out with some results, is there a recommended fps cap per hz of the monitor?
can adjusting the "texture options" fix this issue for me? The only change I make to it is turning off "texture filtering".
Yeah I have been getting this sometimes too. Easiest way to reproduce it for me to is fire up TNT m1 and sit and monitor the frames. It will just randomly dip. Even panning the camera around with the arrow keys is jerky. Settings unlimited framerate/vsync on. I have a 240hz panel too so it will dip from 240-239 to 234 randomly by doing nothing. It happens in DSDA as well, though dsda feels more stable to me. My suggestion would to disable vsync and use RTSS/or nvidia control panel and limit the frames there.
Yeah I have been getting this sometimes too. Easiest way to reproduce it for me to is fire up TNT m1 and sit and monitor the frames. It will just randomly dip. Even panning the camera around with the arrow keys is jerky. Settings unlimited framerate/vsync on. I have a 240hz panel too so it will dip from 240-239 to 234 randomly by doing nothing. It happens in DSDA as well, though dsda feels more stable to me. My suggestion would to disable vsync and use RTSS/or nvidia control panel and limit the frames there.
Yeah I have done that and it does reduce the issue but it still exists
so my best solution to the issue to play in software mode since it removes the stutters. Software mode play much smoother than I remember and I like it's lighting so I don't mind it.
All I can do now is hope the issue is resolved in the next update for either DSDA or PrBoom +
I think I accidentally stumbled upon a workaround for that problem. I also get some random hitches in PrBoom+/DSDA-Doom from time to time in OpenGL mode (never happens in software mode though). They are almost negligible in my case as I play on g-sync monitor, but I guess this is exactly the problem that others have described here already.
First of all these are my settings (in DSDA-Doom):
videomode "OpenGL" screen_resolution "960x540" use_fullscreen 1 exclusive_fullscreen 0 render_vsync 0 uncapped_framerate 1 dsda_fps_limit 105
The display is set to 120Hz, g-sync mode. V-sync is enabled in nvidia control panel for DSDA-Doom.
It seems like I can consistently eliminate those random stutters by simply changing Exclusive Fullscreen to "on" and then back to "off" for the duration of the level. And apparently the game reintroduces stutters after the map change. But if I go to the options menu and change exclusive fullscreen to on and off again, then once again it will fix random hitches for the duration of that map.
Does it have to be exclusive fullscreen or does it get fixed if you switch to software and back to opengl? Trying to find out if reinitializing the video mode fixes it (as opposed to specifically the fullscreen toggle).
I feel that adding something like "precache_sound" that is used in Woof would resolve the issue since it usually comes up when in sounds are activated such as enemies, getting a weapon, etc.
I feel that adding something like "precache_sound" that is used in Woof would resolve the issue since it usually comes up when in sounds are activated such as enemies, getting a weapon, etc.
Well, the problem is that after debugging this issue for some time the only hiccup I have managed to catch is SDL_GL_SwapWindow() function... I personally play tha game with 105 fps cap (in g-sync mode), and for 99% of time the whole program manages to finish all calculations in under ~9ms no problem (that is no surprise given how at uncapped fps it can output thousands of frames per second in same scenes), but then at random times and out of the blue, SDL_GL_SwapWindow() can take up to 45-50ms (so basically framerate drops down to ~20 for a split second), and that's where the stutter happens. Unless there are multiple sources of the stutter of course, but once again I have noticed 0 frametime fluctuations caused by sound related code (or any other code really).
Can somebody else time SDL_GL_SwapWindow() and confirm or deny whether this is the case for them?
P.S. @kraflab could you possibly add a function to DSDA Doom that would log accurate times between two points in the code to the text file, without affecting the program too much? I would volunteer for the grunt work and try to catch any frametime artifacts (if there are any besides SDL_GL_SwapWindow()).
NVM, I think the precision of QueryPerformanceFrequency() and QueryPerformanceCounter() would be enough for logs... I will try to find the root of those hiccups.
Yeah, so I added a crude function to DSDA-Doom https://github.com/rrPKrr/dsda-doom/commit/2b2b5baced08f3c7f4bdb446eabddf9812d4e0ce , and timed D_DoomLoop(), D_Display() and I_FinishUpdate() while playing E1M1 normally at 105fps (105 is chosen because it's 35x3):

As you can see from the log, D_DoomLoop() shows consistent 28-29ms (that's because I use itoa() since approximation doesn't play any role here, as those +/- 1 ms inaccuracies aren't what's causing the problem). During these ~28 ms D_Display() consistently updates every ~9.5ms 3 times and framerate sits at 105. But when the stutter occurs D_DoomLoop() tanks down to ~79ms, and the only place where it spends so much time is I_FinishUpdate(). To be more precise it sits in gld_Finish() > SDL_GL_SwapWindow() for no apparent reasaon.
I thought it was a debugging environment that might have caused these spikes, but now after adding a logging function and playing the game normally I experience exactly the same behavior. ¯_(ツ)_/¯
I guess you already implemented a timing solution, but for future reference you are looking for dsda/time. There's an example use here: https://github.com/kraflab/dsda-doom/blob/dcb92d049f30d8b7501f14d6d2fba8a68dfef3cc/prboom2/src/dsda/key_frame.c#L390. Wrapping it in a log to the console would just be a little extra 🙂
This is a really great investigation, thanks for digging in so deep! For the first time I'm feeling really optimistic that it will be solved 😄
Just a minor update, because I began chasing ghosts after doubting my own findings...
I have simply commented out SDL_GL_SwapWindow(sdl_window) and replayed a demo so that the game could play normally in the background (because commenting out SDL_GL_SwapWindow() makes the game to not show on the screen). No single frame takes longer than ~9.5ms to finish this way. Not even one. So, yeah, now I am 100% sure. 😅
What if you play a demo without it commented out? Does it stutter?
What if you play a demo without it commented out? Does it stutter?
Yes, SDL_GL_SwapWindow() tanks regardless if it's a demo playback or a normal play.
And you don't have vsync on I assume?
And you don't have vsync on I assume?
videomode "OpenGL" screen_resolution "960x540" use_fullscreen 1 exclusive_fullscreen 0 render_vsync 0 uncapped_framerate 1 dsda_fps_limit 105
The display is set to 120Hz, g-sync mode. V-sync is enabled in nvidia control panel for DSDA-Doom.
V-sync is on because it's needed for g-sync to work properly (just to clarify it works differently than your normal v-sync).
But before you ask, no, I have already checked and SDL_GL_SwapWindow() still decides to waste time randomly regardless if it's in a g-sync mode, regular fixed refresh rate v-sync mode or if all syncing methods are forced off completely.
We could try different settings for this function https://wiki.libsdl.org/SDL_GL_SetSwapInterval
We could try different settings for this function https://wiki.libsdl.org/SDL_GL_SetSwapInterval
It's controlled by the in-game v-sync option, no? But other than that it can also be set to -1. I have already tried that.
Correct me if I'm wrong, but the rendering may be asynchronous to some extent, right? As in, there may be buffered draw commands that are only guaranteed to be done when SDL_GL_SwapWindow returns? If that's the case, then you wouldn't actually know what is slow on that frame, even though the slowdown shows up at the swap.
Wait a second... After reading this comment https://gamedev.stackexchange.com/questions/181327/are-there-any-good-techniques-for-reducing-or-smoothing-stutter-after-a-longer-f I got curious so I made a completely empty loop using glfw+glew. Just glClear(GL_COLOR_BUFFER_BIT); followed by glfwSwapBuffers(window);
That actually does exactly the same thing as DSDA-Doom. Even the frametime spikes frequency looks the same. Doesn't make any sense.
Did you try running the process with the highest scheduler priority?
It's possible the OS isn't scheduling the app every time.
Else you might try DwmFlush after every swap buffers call.
Did you try running the process with the highest scheduler priority?
It's possible the OS isn't scheduling the app every time.
Else you might try
DwmFlushafter every swap buffers call.
- Well, I've tried now after you've mentioned that. But nah, it does nothing.
- DwmFlush did a lot of things. First of all it reduced fps from capped 105 to variable ~92-94 for some reason. Then it changed SDL_GL_SwapWindow() times so that now they matched times spent in D_Display():
But, as you can see, at some point SDL_GL_SwapWindow() times still skyrocketed for no reason. So, sadly that made things only worse.