Posts: 273
Threads: 2
Joined: Apr 2022
Reputation:
58
(11-19-2023, 03:05 AM)TerryRitchie Wrote: Has anyone else run the example code with the changes I suggested and noticed any frame skipping?
Yes, I see it both with the original `Wait` and with a `_Limit 60`, but it's hard to tell with just the "X".
(11-19-2023, 03:05 AM)TerryRitchie Wrote: Update: DSMan posted while I was writing this. So there is an issue with QB64? Why am I getting a rock solid 60FPS then?
I didn't clarify in my post, but I suspect you're really not. You can't actually measure the FPS in a QB64 program, you can only measure the speed you're loop is producing frames via calling `_Display`. The window is supposed to get redrawn at 60 FPS regardless of anything your program does. _Limit 60 will get you pretty close to synced with the separate thread drawing the window, but stutter will still happen, and actually happens a lot more often due to that noted 55.6 FPS issue that screws everything up even more.
I would try out this program and check what you see, it's inspired by what @bplus mentioned. It draws green and red circles on alternating frames at 60 FPS, and on my (garbage...) monitors when that perfectly syncs up it just appears like a darkish yellow. When it stutters, I see a green or red circle for a moment. A big thing to keep in mind, regardless of what you see, is that the pattern should be consistent if there was no stuttering, if you're seeing any kind of random flashing then that means frames are being dropped or missed:
Code: (Select All)
SCREEN _NEWIMAGE(640, 480, 32)
COLOR &HFFFFFFFF, _RGB32(28, 28, 22)
DO
DIM c AS LONG
IF (X MOD 2) = 0 THEN
c = _RGB32(0, 255, 0)
ELSE
c = _RGB32(255, 0, 0)
END IF
CIRCLE (640 / 2, 480 / 2), 100, c,
PAINT (640 / 2, 480 / 2), c
_DISPLAY
_LIMIT 60
X = X + 1
LOOP
Here's another version you could try as well, this is a little different and uses a `_Limit 120` to attempt to create twice as many frames as can be displayed on the window. If you're getting a perfectly synced result then you should only see a green circle as all the frames with the red circle will get dropped before you see them. When I actually run it, I just get random flickering, occasionally it stays stable for a while and sometimes it starts flickering significant amounts:
Code: (Select All)
SCREEN _NEWIMAGE(640, 480, 32)
COLOR &HFFFFFFFF, _RGB32(28, 28, 22)
DO
DIM c AS LONG
IF (X MOD 2) = 0 THEN
c = _RGB32(0, 255, 0)
ELSE
c = _RGB32(255, 0, 0)
END IF
CIRCLE (640 / 2, 480 / 2), 100, c,
PAINT (640 / 2, 480 / 2), c
_DISPLAY
_LIMIT 120
X = X + 1
LOOP
Posts: 485
Threads: 24
Joined: May 2022
Reputation:
91
@DSMan195276 is correct.
@grymmjack also reported this sometime back. I am leaving his example code here which easily shows the issue.
Code: (Select All)
OPTION _EXPLICIT
DIM AS INTEGER lim, st, x, y, w, h
DIM AS SINGLE d
DIM AS STRING FGC, BGC, T, M, B, F, ALIEN
DIM AS LONG ALIEN_SPRITE, ALIEN_32, ALIEN_HW, CANVAS
CANVAS& = _NEWIMAGE(320, 200, 32)
SCREEN CANVAS&
_FULLSCREEN _SQUAREPIXELS
d! = 0
lim% = 120
st% = 1
x% = 0
y% = 10
w% = 50
h% = 50
FGC$ = "12": BGC$ = "8"
T$ = "C" + FGC$ + " R10 E5 R20 F5 R10 BL50"
M$ = "D20 BR50 BU20 D20 BL50"
B$ = "D10 E10 U10 R30 D10 F10 U10 BL50"
F$ = "BU20 BF5 P " + BGC$ + "," + FGC$
ALIEN$ = T$ + M$ + B$ + F$
ALIEN_SPRITE& = _NEWIMAGE(w% + 1, h% + 1, 256)
_DEST ALIEN_SPRITE&
PSET (0, 10)
DRAW ALIEN$
_CLEARCOLOR 0, ALIEN_SPRITE&
ALIEN_32& = _NEWIMAGE(w% + 1, h% + 1, 32)
_SOURCE ALIEN_SPRITE&: _DEST ALIEN_32&: _PUTIMAGE
ALIEN_HW& = _COPYIMAGE(ALIEN_32&, 32)
_DEST CANVAS&
DIM oldx AS INTEGER
DO
x% = x% + st%
CLS , _RGB32(0, 0, 255)
PRINT x%, y%
IF ABS(oldx - x%) > 1 THEN PRINT "SKIPPED SOME!"; oldx: STOP
oldx = x%
IF x% <= 0 OR x% >= _WIDTH - w% THEN st% = -st%
_PUTIMAGE (x%, y%), ALIEN_HW&
_DISPLAY
_LIMIT 60
LOOP UNTIL _KEYHIT = 27
_FREEIMAGE ALIEN_SPRITE&
_FREEIMAGE ALIEN_HW&
SYSTEM
Posts: 3,447
Threads: 376
Joined: Apr 2022
Reputation:
345
All these pretty graphic examples, and nobody even bothered to look at my simple PRINT illustration. /sniffle
Code: (Select All) DO
LOCATE 1, 1: PRINT x
_LIMIT 600
_DISPLAY
x = x + 1
LOOP
If the display was 60 FPS, and was perfectly synced, with a limit of 600 we'd only see it counting by 10s, and that's not happening. No need for fancy graphics to showcase the issue, when all you have to do is PRINT to see it in action.
Posts: 489
Threads: 17
Joined: Nov 2022
Reputation:
59
(11-20-2023, 01:10 AM)a740g Wrote: @grymmjack also reported this sometime back. I am leaving his example code here which easily shows the issue.
It's good to see that the issue is getting discussed (and possibly getting fixed?)
Posts: 50
Threads: 12
Joined: Nov 2023
Reputation:
3
08-06-2025, 10:22 AM
(This post was last modified: 08-06-2025, 10:28 AM by pmackay.)
(11-18-2023, 10:09 PM)Haggarman Wrote: Thanks for the replies, I really do appreciate the help.
@bplus, good thinking on adjusting the _Limit duration at program run. I can't seem to find a sweet spot however.
It feels like there is something lurking beneath that has to do with _Display having a high variability (10~20 ms) in when the actual memory copy occurs.
I realize _Display needs to call a graphics copy function at the OS level, but it's actually waiting for something too? What would that be?
As for 55.6 fps, is the wait &h3da, 8 command unsupported at this point? I know from original QB that this waited for vsync (vertical refresh) back in the VGA compatible days.
The process on Old QBASIC was draw to the working screen page, wait until vsync, flip the screen page, clear the new working screen page, wait until not in vsync, repeat.
For QB64, I wish there was a command to essentially wait for vsync and copy over the image buffer to the OS at that point and return. And then if it was called again while in the same vsync period, it would actually just wait until the next vsync to do the copy.
thanks wait &h3da,8 : wait &h3da ,8,8
curious if $checking off makes any difference
|