Skip to content
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

Emulation speed wrong and Screen is a flickering mess #214

Open
LoveBug2084 opened this issue Dec 3, 2023 · 23 comments
Open

Emulation speed wrong and Screen is a flickering mess #214

LoveBug2084 opened this issue Dec 3, 2023 · 23 comments

Comments

@LoveBug2084
Copy link
Contributor

LoveBug2084 commented Dec 3, 2023

the last time I compiled b-em in October this year everything was fine but I just compiled this latest b-em update on both my toshiba laptop and my imac (both running linux mint 21.2) and something is very wrong with this latest source code

on the toshiba laptop the emulation speed is 120% !
on the imac the emulation speed jumps very randomly from about 97% to 105%
(previously the emulation speed was rock solid 100% on both machines)

on both machines the speed menu doesn't do anything (you cannot slow down or speed up the emulation regardless of what speed setting is chosen)
on both machines the video display is showing what looks like previous screen data mixed with the current data and is a glitchy flickering mess
Screenshot from 2023-12-02 10-17-30

@LoveBug2084 LoveBug2084 changed the title Speed and Ghost frames Emulation speed wrong and Screen is a flickering mess Dec 3, 2023
@SteveFosdick
Copy link
Collaborator

SteveFosdick commented Dec 4, 2023

The root of this seems to be in some work to make the Music 5000 emulation more accurate.

Previously, the Music 5000 was driven by sound events from Allegro so worked at whatever speed was required to produce a continuous stream of audio regardless of how fast the emulation of the rest of the machine was going.

Chris Jordan, the Music 5000 designer, pointed out that this resulted in the Music 500 emulation running insufficiently often and with too much jitter compared to the 6522 timer on which AMPLE relies to accurately reproduce some sounds.

The revised version runs the Music 5000 emulation in the same synchronous manner as the 6522s and it pushes audio to the sound system as it fills a buffer. This has the effect that feeding the Music 5000 audio into the host sound system becomes a bottleneck that prevents the emulated BBC Micro from running at over 100% speed.

There was also a further issue due to something having gone wrong in the merge in that the speeds calculation was wrong as per your forum post. I have pushed a commit that fixed the mis-calculation.

The issue of the Music 5000 remains. It is possible to use the faster speeds by turning the Music 5000 off from the sound menu. Interestingly, the same issue exists with video in that if we speed up the machine so it generates frames of video more quickly, we reach a point where telling the host to flip the video buffers stalls the emulator so regardless of asking for timer events more often, it doesn't run any faster. That is handled by skipping some frames, hence why the speeds table in main.c also contains an appropriate frame skip number. We can't really do the same for sound as it isn't divided into frames in the same way. To make it completely seamless we'd have to resample the audio but that's quite a lot of work. In the meantime I may see if we can just add some dialogues to the UI to the effect that the Music 5000 and faster speeds are not compatible.

@SteveFosdick
Copy link
Collaborator

It turned out to be a little easier to resample the Music 5000 output as Allegro can do that just by b-em specifying a different sample rate. I have pushed another commit to use this to resolve the Music 5000 constraining the emulator speed.

@rjpontefract
Copy link
Contributor

On an m1 mac the screen still flickers a lot when the speed is 100% or below. Setting the speed to 150% and the screen appears fine. Also setting the speed to 100% and turning on PAL emulation stops the flickering.

I have a feeling this maybe where the inadvertent commit to the change to the skip frame count at 100% from 1 to 2 came from. I seem to recall seeing this back then and that was a quick fix for it and it sneaked its way into the Sprow ARM emulator commit.

@LoveBug2084
Copy link
Contributor Author

I just cloned the latest repo and compiled, the speed menu is now working thanks, the issue with the flickering screen is still there
Screenshot from 2023-12-05 23-12-08

@SteveFosdick
Copy link
Collaborator

I am struggling to reproduce this. Does the setting of Settings->Video->Display Type make any difference? Does turning interlace off (with *TV) in the non-teletext modes make any difference?

@LoveBug2084
Copy link
Contributor Author

i'll test out all combinations of settings tomorrow and post my findings

@LoveBug2084
Copy link
Contributor Author

LoveBug2084 commented Dec 8, 2023

right so I tried interlace on and off with *tv with all 4 display types in settings -> video -> display type and found that the results are identical

BTW I'm really sorry that I forgot to say that this weird effect only appears in full screen mode, in windowed mode everything is normal

for me if I set b-em to full screen mode and then type mode 0 followed by mode 7 I see both screen modes on screen at the same time on alternate frames !

I'm sorry I can't be more helpful at the moment, I used to be able to deep dive into code and solve these kind of issues but since suffering a stroke a few months back my brain isn't what it used to be and tires easily :(

setting the 100% table entry in main.c to 2 frames fixes the issue but I would really like it set to 1 if possible

so far I have only tried the new code on my toshiba laptop with intel hd graphics, if I get a chance today I'll compile it on my imac with nvidia graphics and see whats what (also running linux mint 21.2)

@LoveBug2084
Copy link
Contributor Author

LoveBug2084 commented Dec 8, 2023

I compiled this latest code on my imac running linux mint 21.2, it works correctly without any flicker on the nvidia gpu
on my toshiba laptop with intel hd graphics I have the problem

*** edit ***
actually I do see a glitches in full screen mode if I move the mouse pointer

@SteveFosdick
Copy link
Collaborator

Ok, engaging full-frame does not make any immediate difference for me. This is on Linux, an i7-6700 CPU @ 3.40GHz, using the integrated Intel graphics.

What did make a difference is trying to run with frameskip as 1 at 150% speed, i.e. by editing the table as you did but the 150% entry. I attach the screen shot. What is noticeable is that it is now not achieving the 150% speed as it would have done with frameskip set to 2. I will need to do some more digging but my guess is it is being held up either when upscaling the image (al_draw_scaled_bitmap) or during the buffer flip (al_flip_display).

This could be about graphics processing power but what is slightly suspicious for me is that it is starting to happen when the emulation would be trying to push frames into the host's video system a little faster than the frame rate used between the PC graphics hardware and the display.
b-em

@LoveBug2084
Copy link
Contributor Author

good luck 👍

@LoveBug2084
Copy link
Contributor Author

LoveBug2084 commented Dec 15, 2023

btw even the latest source code has something odd going on with the frames for 150% being 3 whereas the entry for 200% is 2

const emu_speed_t emu_speeds[NUM_EMU_SPEEDS] = {
    {  "10%", 0.10, 1 },
    {  "25%", 0.25, 1 },
    {  "50%", 0.50, 1 },
    {  "75%", 0.75, 1 },
    { "100%",    1, 1 },
    { "150%", 1.50, 3 },
    { "200%", 2.00, 2 },
    { "300%", 3.00, 3 },
    { "400%", 4.00, 4 },
    { "500%", 5.00, 5 }
};

@SteveFosdick
Copy link
Collaborator

First, the vid_fksipmax of 3 against 150% is wrong. I have pushed a commit to master to change this to 2.

Back to the what is going on when two images seems to be overlaid, on investigation, it was al_flip_display that was causing b-em not to be able to run at the specified speed so using a suitable vid_fksipmax seems to allow both the specified speed to actually be reached and at the same time avoid the mixed up output.

Interestingly, al_flip_display is allowed to wait for the flip to occur, or not, depending on the host OS and display hardware. B-Em can give Allegro a hint as to which behaviour is preferred, but neither the library or OS code has to honour that.

My model for what happens in al_flip_display is that was previously the back buffer is now either actually on the display, or queued for display in a few ms time, and there is a fresh backbuffer that can be drawn on, either the old front buffer or some other. Maybe this is not completely true - it seems allowable for al_flip_display to simply return having done nothing if the hardware is not ready for a flip. That may mean that after al_flip_display b-em is drawing into the same buffer and sometimes a different buffer and that may be the issue. I am not sure we can fix that directly, though maybe there is a bug I don't understand.

What I have done is created a new branch for this issue: https://github.com/stardot/b-em/tree/sf/issue214 with some changes to automatically manage vid_fksipmax. The new default is that, instead of relying on the table, at any speed change vid_fksipmax is set to one and then the same mechanism that displays the actual speed on the title bar is used to check if the target speed is reached. If not, it increases vid_fksipmax. That is repeated until the speed is acheived. This mode can be disabled from the Speed menu and there is also a command line override that enables vid_fksipmax to be fixed to a particular value.

I have also done something similar with "full speed" mode. For that to work properly the Music 5000 emulation needs to be off. When full speed is engaged, either from the menu or by pressing the PgUp key, it will keep increasing vid_fksipmax until it no longer leads to an increase in actualy emulator speed, until it becomes CPU limited.

These should also cope with full-screen being slower on any given hardware than working in a Window.

Can you try this version and see how you get on, please.

@rjpontefract
Copy link
Contributor

I tried the new version on macOS 14.2 with an m1 max CPU and it still exhibits screen flickering. I tried it with just the internal laptop display and with 1, 2 and 3 external 4K monitors and saw no real difference. I also tried altering the refresh rate of the internal display to 60Hz and 50Hz, which also made no difference. The speed does sit at around 100% so I guess the code to increase the frame skip count doesn't get invoked,

Having said that, I have seen it increase the frame skip count to 2 (and 3 on one occasion) when changed the display scaling to "more space", so it does work in some circumstances. Does it ever go down, for example when it is increased to 3 will it ever go back to 2? When it was increased to 2 and above the screen flickering ceased as would be expected.

It's hard to believe that this mac can't keep up with the display for b-em, so I suspect that there may be a bug or an inefficiency in the allegro code somewhere. I suspect that macOS isn't at the top of their supported platforms list.

@SteveFosdick
Copy link
Collaborator

No, with the auto-determination of vid_fskipmax, it doesn't go down again. I can see how we can detect that it could be lowered without actually trying it and, if it can't be lowered, that would lead to the speed oscillating.

I do think it is not so much CPU power limited as an interaction with the refresh rate. I thought it would be useful to try some different speed combinations and, along the way, I added some code to enable the table of speeds to be loaded from the config file. That means that, if all else fails, people can have their own vid_fskipmax values that work for their hardware, though I would still prefer to have it work correctly for everyone with a good set of defaults.

To use this new feature, put a section in b-em.cfg like this:

[speeds]
10%=0.1,1
25%=0.25,1
50%=0.5,1
75%=0.75,1
100%=1,1
120%=1.2,1
130%=1.3,1
150%=1.5,2
200%=2,2
300%=3,3
500%=5,5

So the format is Label=multipler,fskipmax

I will experiment with some different speeds and see what happens.

@SteveFosdick
Copy link
Collaborator

Another thing worth experimenting with is the setting of ALLEGRO_VSYNC. See line 777 of video.c and https://liballeg.org/a5docs/trunk/display.html#al_set_new_display_option

@SteveFosdick
Copy link
Collaborator

The refresh rate for my display appears to be fixed at 60 frames/sec. Experimenting by adding additional fields suggests the problem of sometimes displaying an old buffer starts to happen as the emulation speed reaches the hardware refresh rate but is actually very slighly under it, with BBC Micro generating 50 fields/sec and the host refresh rate at 60 frames/sec, it should be possible to run the emulation at 120%, but problem start showing up at 119%.

Another possibility is that sometime the emulation ends up calling al_flip_display more than once during one 20ms period. The code in video_poll (video.c) has three places where it calls video_doblit. I think depending on various settings, only one should be called for any given field but it is possible that more than one is.

The other interesting thing is that the old buffer contents only seem to be displayed in mode 7, not in the graphics mode so it seems there must be something different about the way the CRTC is programmed between these two modes that is causing this.

The other thing here is that I think this not a case of the recent batch of merges having introduced a bug. It is more the case that "fixing" the slow refresh has revealed something that has been there for some time.

@SteveFosdick
Copy link
Collaborator

See if this commit e84b643 (the latest on the Issue#214 branch as I write this) fixes this issue. It eliminates one of the calls to video_doblit that obly seems to occur when the CRTC registers are in an inconsistent state, something which would typically occur during a mode change and not when stable and running in any given mode,

@rjpontefract
Copy link
Contributor

I gave the latest code from the issue 214 branch a test and I don't see any improvement in behaviour unfortunately.

On startup the frame skip value remains at 1 and on occasion will be changed to 2. I guess the speed must be very close to what is required to run with a skip value of 1. When it is changed to 2 the issues go away as expected.

My external display is fixed at 60Hz although I can change it 30, but 50 is not an option.

I did some playing around with different speed settings and I don't seem to be able to get the new version to work correctly under 300%. Previous versions did work OK at 150%, just not 100% and below with the default frame skip settings.

I tried pretty much every display option, none of which had any effect on the flickering issue, other than enable PAL emulation. Turning that on does remove the flickering.

I added a speeds section to the config file and set 100% to skip 2 frames. Initially this didn't have any effect, but when I turned off "Auto Frameskip" in the settings menu it worked as expected. Thanks for adding this option as it allows me to use b-em without rebuilding with a edited speed table.

I also tried enabling allegro_vsync in the video section but it had no effect that I can see. However, I didn't see the debug message either, so maybe I got something wrong. I change it to an info message and got the following when it was set to 1 in the config file:

video: config vsync=1, actual=2

I'll have to read the allegro docs to see what that means.

@SteveFosdick
Copy link
Collaborator

As I think we mentioned earlier, this could be a buffer management issues somewhere within Allegro so with removing the extra call to video_doblit I wasn't thinking that would be solved, but given the observation that the issue occurs when the rate of frames generated by the emulation approaches the hardware refresh rate, I was hoping this would just about allow a frameskip of 1 at 100% speed as it seemed to do so for me at 120% speed.

video: config vsync=1, actual=2

This is interesting. It means you specified 1 in the config line, which calls for al_flip_display to wait for hardware vsync before returning, but the library says that can't be done and the actual setting being used is 2 which is to return immediately.

In the case that al_flip_display returns immediately, B-Em then re-locks the buffer called 'b' that it draws the emulated display into and carries on. In theory, b should be fine to draw on as, immediately prior to al_flip_display, the image on 'b' should have been upscaled onto the back buffer. The PAL emulation introduces another buffer copy.

@SteveFosdick
Copy link
Collaborator

SteveFosdick commented Dec 20, 2023

Ok, try now (e920379). I tried adding al_set_target_bitmap(b) before locking the bitmap region for drawing. I don't know if this is an undeclared pre-requistite for locking the bitmap or whether just de-selecting the back buffer as the drawing target is what matters, but, for me, this enables me to go over the hardware refresh rate without the flickering.

@rjpontefract
Copy link
Contributor

I tried the new code and the flickering is still there. I also still see this:
video: config vsync=1, actual=2
I then tried changing ALLEGRO_SUGGEST to ALLEGRO_REQUIRE and still got this:
video: config vsync=1, actual=2
So I don't know what's going on. Do you get a different result on Linux?

@SteveFosdick
Copy link
Collaborator

Apologies, I have put the wrong commit in my previous message. I meant to put the last commit, at the time of writing, on the Issue#214 branch but GitHub showed me the last commit on the master branch. It should have been: abe5e49

I will try the vsync and report back.

@SteveFosdick
Copy link
Collaborator

I get the same video: config vsync=1, actual=2 as you on Linux and also on Windows (though that is running in a VM on the same hardware so maybe more to do with hardware than OS).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants