Screen tearing after playing Zelda LTTP for multiple hours. [Fixed]
- Grabulosaure
- Core Developer
- Posts: 79
- Joined: Sun May 24, 2020 7:41 pm
- Location: Mesozoic
- Has thanked: 3 times
- Been thanked: 92 times
- Contact:
Re: Screen tearing after playing Zelda LTTP for multiple hours.
@AtomicShroom
I really have no idea on what could cause tearing after hours. The scaler continuously selects the latest updated frame.
I've made a version of SNES with a "border" option which shows input video in the border of the scaled image. I'd be curious to know if the tearing is synchronised with the input video sliding :
http://temlib.org/pub/mister/SNES_border.rbf
With SNES NTSC mode, the skew compared to 60Hz output is around 1 frame per 10 second.
I really have no idea on what could cause tearing after hours. The scaler continuously selects the latest updated frame.
I've made a version of SNES with a "border" option which shows input video in the border of the scaled image. I'd be curious to know if the tearing is synchronised with the input video sliding :
http://temlib.org/pub/mister/SNES_border.rbf
With SNES NTSC mode, the skew compared to 60Hz output is around 1 frame per 10 second.
-
- Core Developer
- Posts: 217
- Joined: Sun May 24, 2020 8:48 pm
- Has thanked: 50 times
- Been thanked: 300 times
Re: Screen tearing after playing Zelda LTTP for multiple hours.
@Grabulosaure What I think is happening is that in some edge case 'o_ibuf0' and 'o_obuf0' become equal. The 'buf_next' function defaults to buffer 1 so when o_ibuf0 and o_obuf0 are equal then they both get stuck at buffer 1.
I had to wait a long time for it to start tearing again but I could finally confirm with SignalTap that they are both stuck at buffer 1.
I had to wait a long time for it to start tearing again but I could finally confirm with SignalTap that they are both stuck at buffer 1.
- Grabulosaure
- Core Developer
- Posts: 79
- Joined: Sun May 24, 2020 7:41 pm
- Location: Mesozoic
- Has thanked: 3 times
- Been thanked: 92 times
- Contact:
Re: Screen tearing after playing Zelda LTTP for multiple hours.
i suspect the input and output synchro that triggers buffer swap occurring at exactly the same cycle. Something as stupid. Sorrypaulbnl wrote: ↑Sun Jul 04, 2021 9:00 am @Grabulosaure What I think is happening is that in some edge case 'o_ibuf0' and 'o_obuf0' become equal. The 'buf_next' function defaults to buffer 1 so when o_ibuf0 and o_obuf0 are equal then they both get stuck at buffer 1.
I had to wait a long time for it to start tearing again but I could finally confirm with SignalTap that they are both stuck at buffer 1.
I'l post a tentative fix today.
- Grabulosaure
- Core Developer
- Posts: 79
- Joined: Sun May 24, 2020 7:41 pm
- Location: Mesozoic
- Has thanked: 3 times
- Been thanked: 92 times
- Contact:
Re: Screen tearing after playing Zelda LTTP for multiple hours.
@paulbnl
@AtomicShroom
I have posted an updated version of SNES which may fix the problem : End of input and begin of output during the same clock cycle.
http://temlib.org/pub/mister/SNES.rbf
http://temlib.org/pub/mister/SNES_border.rbf
@AtomicShroom
I have posted an updated version of SNES which may fix the problem : End of input and begin of output during the same clock cycle.
http://temlib.org/pub/mister/SNES.rbf
http://temlib.org/pub/mister/SNES_border.rbf
Code: Select all
diff --git a/sys/ascal.vhd b/sys/ascal.vhd
index 2d21b35..f157e9f 100644
--- a/sys/ascal.vhd
+++ b/sys/ascal.vhd
@@ -383,8 +383,8 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL avl_fb_ena : std_logic;
FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS
- BEGIN
- IF (freeze='1') THEN RETURN a; END IF;
+ BEGIN
+ IF (freeze='1') THEN RETURN a; END IF;
IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF;
IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF;
RETURN 1;
@@ -401,7 +401,7 @@ ARCHITECTURE rtl OF ascal IS
----------------------------------------------------------
-- Output
SIGNAL o_run : std_logic;
- SIGNAL o_freeze : std_logic;
+ SIGNAL o_freeze : std_logic;
SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0);
SIGNAL o_format : unsigned(5 DOWNTO 0);
SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0);
@@ -1731,8 +1731,8 @@ BEGIN
--------------------------------------------
-- Triple buffering.
-- For intelaced video, half frames are updated independently
- -- Input : Toggle buffer at end of input frame
- o_freeze <= freeze;
+ -- Input : Toggle buffer at end of input frame
+ o_freeze <= freeze;
o_inter <=i_inter; -- <ASYNC>
o_iendframe0<=i_endframe0; -- <ASYNC>
o_iendframe02<=o_iendframe0;
@@ -1746,7 +1746,12 @@ BEGIN
o_ibuf1<=buf_next(o_ibuf1,o_obuf1,o_freeze);
o_bufup1<='1';
END IF;
+
-- Output : Change framebuffer, and image properties, at VS falling edge
+ IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN
+ o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze);
+ o_bufup0<='0';
+ END IF;
IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN
o_obuf1<=buf_next(o_obuf1,o_ibuf1,o_freeze);
o_bufup1<='0';
@@ -1755,6 +1760,33 @@ BEGIN
o_hdown<=i_hdown; -- <ASYNC>
o_vdown<=i_vdown; -- <ASYNC>
END IF;
+
+ -- Simultaneous change of input and output framebuffers
+ IF o_vsv(1)='1' AND o_vsv(0)='0' AND
+ o_iendframe0='1' AND o_iendframe02='0' THEN
+ o_bufup0<='0';
+ o_obuf0<=o_ibuf0;
+ END IF;
+ IF o_vsv(1)='1' AND o_vsv(0)='0' AND
+ o_iendframe1='1' AND o_iendframe12='0' THEN
+ o_bufup1<='0';
+ o_obuf1<=o_ibuf1;
+ END IF;
+
+ -- Non-interlaced, use same buffer for even and odd lines
+ IF o_inter='0' THEN
+ o_ibuf1<=o_ibuf0;
+ o_obuf1<=o_obuf0;
+ END IF;
+
+ -- Triple buffer disabled
+ IF o_mode(3)='0' THEN
+ o_obuf0<=0;
+ o_obuf1<=0;
+ o_ibuf0<=0;
+ o_ibuf1<=0;
+ END IF;
+
-- Framebuffer mode.
IF o_fb_ena='1' THEN
o_ihsize<=o_fb_hsize;
@@ -1774,25 +1806,6 @@ BEGIN
o_stride<=to_unsigned(o_ihsize_temp2,14);
o_stride(NB_BURST-1 DOWNTO 0)<=(OTHERS =>'0');
END IF;
-
- IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN
- o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze);
- o_bufup0<='0';
- END IF;
-
- IF o_inter='0' THEN
- o_ibuf1<=o_ibuf0;
- o_obuf1<=o_obuf0;
- END IF;
-
- -- Triple buffer disabled
- IF o_mode(3)='0' THEN
- o_obuf0<=0;
- o_obuf1<=0;
- o_ibuf0<=0;
- o_ibuf1<=0;
- END IF;
-
------------------------------------------------------
o_hmode<=o_mode;
IF o_hdown='1' AND DOWNSCALE THEN
Re: Screen tearing after playing Zelda LTTP for multiple hours.
BOOOM
MiSTer community to the rescue!
my next questions is, can this fix be applied to other cores?
seems like some folks would appreciate this, if this tearing with vsync_adjust=0 is a widespread issue
MiSTer community to the rescue!
my next questions is, can this fix be applied to other cores?
seems like some folks would appreciate this, if this tearing with vsync_adjust=0 is a widespread issue
-
- Posts: 172
- Joined: Sun Mar 07, 2021 12:28 pm
- Has thanked: 31 times
- Been thanked: 48 times
Re: Screen tearing after playing Zelda LTTP for multiple hours.
Holy hell that was fast! Thank you so much for looking into this and attempting a fix! It’s currenty running so I’ll report back with my results when I get back home tonight!Grabulosaure wrote: ↑Sun Jul 04, 2021 12:58 pm @paulbnl
@AtomicShroom
I have posted an updated version of SNES which may fix the problem : End of input and begin of output during the same clock cycle.
http://temlib.org/pub/mister/SNES.rbf
http://temlib.org/pub/mister/SNES_border.rbf
Code: Select all
diff --git a/sys/ascal.vhd b/sys/ascal.vhd index 2d21b35..f157e9f 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -383,8 +383,8 @@ ARCHITECTURE rtl OF ascal IS SIGNAL avl_fb_ena : std_logic; FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS - BEGIN - IF (freeze='1') THEN RETURN a; END IF; + BEGIN + IF (freeze='1') THEN RETURN a; END IF; IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF; IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF; RETURN 1; @@ -401,7 +401,7 @@ ARCHITECTURE rtl OF ascal IS ---------------------------------------------------------- -- Output SIGNAL o_run : std_logic; - SIGNAL o_freeze : std_logic; + SIGNAL o_freeze : std_logic; SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0); SIGNAL o_format : unsigned(5 DOWNTO 0); SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0); @@ -1731,8 +1731,8 @@ BEGIN -------------------------------------------- -- Triple buffering. -- For intelaced video, half frames are updated independently - -- Input : Toggle buffer at end of input frame - o_freeze <= freeze; + -- Input : Toggle buffer at end of input frame + o_freeze <= freeze; o_inter <=i_inter; -- <ASYNC> o_iendframe0<=i_endframe0; -- <ASYNC> o_iendframe02<=o_iendframe0; @@ -1746,7 +1746,12 @@ BEGIN o_ibuf1<=buf_next(o_ibuf1,o_obuf1,o_freeze); o_bufup1<='1'; END IF; + -- Output : Change framebuffer, and image properties, at VS falling edge + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN + o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); + o_bufup0<='0'; + END IF; IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN o_obuf1<=buf_next(o_obuf1,o_ibuf1,o_freeze); o_bufup1<='0'; @@ -1755,6 +1760,33 @@ BEGIN o_hdown<=i_hdown; -- <ASYNC> o_vdown<=i_vdown; -- <ASYNC> END IF; + + -- Simultaneous change of input and output framebuffers + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe0='1' AND o_iendframe02='0' THEN + o_bufup0<='0'; + o_obuf0<=o_ibuf0; + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe1='1' AND o_iendframe12='0' THEN + o_bufup1<='0'; + o_obuf1<=o_ibuf1; + END IF; + + -- Non-interlaced, use same buffer for even and odd lines + IF o_inter='0' THEN + o_ibuf1<=o_ibuf0; + o_obuf1<=o_obuf0; + END IF; + + -- Triple buffer disabled + IF o_mode(3)='0' THEN + o_obuf0<=0; + o_obuf1<=0; + o_ibuf0<=0; + o_ibuf1<=0; + END IF; + -- Framebuffer mode. IF o_fb_ena='1' THEN o_ihsize<=o_fb_hsize; @@ -1774,25 +1806,6 @@ BEGIN o_stride<=to_unsigned(o_ihsize_temp2,14); o_stride(NB_BURST-1 DOWNTO 0)<=(OTHERS =>'0'); END IF; - - IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN - o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); - o_bufup0<='0'; - END IF; - - IF o_inter='0' THEN - o_ibuf1<=o_ibuf0; - o_obuf1<=o_obuf0; - END IF; - - -- Triple buffer disabled - IF o_mode(3)='0' THEN - o_obuf0<=0; - o_obuf1<=0; - o_ibuf0<=0; - o_ibuf1<=0; - END IF; - ------------------------------------------------------ o_hmode<=o_mode; IF o_hdown='1' AND DOWNSCALE THEN
-
- Posts: 172
- Joined: Sun Mar 07, 2021 12:28 pm
- Has thanked: 31 times
- Been thanked: 48 times
Re: Screen tearing after playing Zelda LTTP for multiple hours.
And yuuup that totally seems to fix it! Super Mario World has been running for well over 5 hours now and no screen tearing to be seen! Absolutely impeccable!Grabulosaure wrote: ↑Sun Jul 04, 2021 12:58 pm @paulbnl
@AtomicShroom
I have posted an updated version of SNES which may fix the problem : End of input and begin of output during the same clock cycle.
http://temlib.org/pub/mister/SNES.rbf
http://temlib.org/pub/mister/SNES_border.rbf
Code: Select all
diff --git a/sys/ascal.vhd b/sys/ascal.vhd index 2d21b35..f157e9f 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -383,8 +383,8 @@ ARCHITECTURE rtl OF ascal IS SIGNAL avl_fb_ena : std_logic; FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS - BEGIN - IF (freeze='1') THEN RETURN a; END IF; + BEGIN + IF (freeze='1') THEN RETURN a; END IF; IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF; IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF; RETURN 1; @@ -401,7 +401,7 @@ ARCHITECTURE rtl OF ascal IS ---------------------------------------------------------- -- Output SIGNAL o_run : std_logic; - SIGNAL o_freeze : std_logic; + SIGNAL o_freeze : std_logic; SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0); SIGNAL o_format : unsigned(5 DOWNTO 0); SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0); @@ -1731,8 +1731,8 @@ BEGIN -------------------------------------------- -- Triple buffering. -- For intelaced video, half frames are updated independently - -- Input : Toggle buffer at end of input frame - o_freeze <= freeze; + -- Input : Toggle buffer at end of input frame + o_freeze <= freeze; o_inter <=i_inter; -- <ASYNC> o_iendframe0<=i_endframe0; -- <ASYNC> o_iendframe02<=o_iendframe0; @@ -1746,7 +1746,12 @@ BEGIN o_ibuf1<=buf_next(o_ibuf1,o_obuf1,o_freeze); o_bufup1<='1'; END IF; + -- Output : Change framebuffer, and image properties, at VS falling edge + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN + o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); + o_bufup0<='0'; + END IF; IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN o_obuf1<=buf_next(o_obuf1,o_ibuf1,o_freeze); o_bufup1<='0'; @@ -1755,6 +1760,33 @@ BEGIN o_hdown<=i_hdown; -- <ASYNC> o_vdown<=i_vdown; -- <ASYNC> END IF; + + -- Simultaneous change of input and output framebuffers + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe0='1' AND o_iendframe02='0' THEN + o_bufup0<='0'; + o_obuf0<=o_ibuf0; + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe1='1' AND o_iendframe12='0' THEN + o_bufup1<='0'; + o_obuf1<=o_ibuf1; + END IF; + + -- Non-interlaced, use same buffer for even and odd lines + IF o_inter='0' THEN + o_ibuf1<=o_ibuf0; + o_obuf1<=o_obuf0; + END IF; + + -- Triple buffer disabled + IF o_mode(3)='0' THEN + o_obuf0<=0; + o_obuf1<=0; + o_ibuf0<=0; + o_ibuf1<=0; + END IF; + -- Framebuffer mode. IF o_fb_ena='1' THEN o_ihsize<=o_fb_hsize; @@ -1774,25 +1806,6 @@ BEGIN o_stride<=to_unsigned(o_ihsize_temp2,14); o_stride(NB_BURST-1 DOWNTO 0)<=(OTHERS =>'0'); END IF; - - IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN - o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); - o_bufup0<='0'; - END IF; - - IF o_inter='0' THEN - o_ibuf1<=o_ibuf0; - o_obuf1<=o_obuf0; - END IF; - - -- Triple buffer disabled - IF o_mode(3)='0' THEN - o_obuf0<=0; - o_obuf1<=0; - o_ibuf0<=0; - o_ibuf1<=0; - END IF; - ------------------------------------------------------ o_hmode<=o_mode; IF o_hdown='1' AND DOWNSCALE THEN
Edit: If confirmed by others, could you make sure to propagate this fix to all other cores? Thanks!
Re: Screen tearing after playing Zelda LTTP for multiple hours.
i dont have too much time to tinker with this tonight, but im noticing something similar happening as of lately.
tested with the new shadow mask core and standard SNES core thats released, but its a judder or frame drop every second or so when im running with mario at full speed
240 testsuite scrolls the screen just fine up to the super fast speeds that the grid and sonic background can display,
but super mario world, with either "match core frequency" or "low lag" has a slight loading/catchup/frame drop every second or so.
its like a frame drop about every second, only when im running at full speed.
i can record a video to show what im talking about, and/or make a separate thread if its not related to this issue
tested with the new shadow mask core and standard SNES core thats released, but its a judder or frame drop every second or so when im running with mario at full speed
240 testsuite scrolls the screen just fine up to the super fast speeds that the grid and sonic background can display,
but super mario world, with either "match core frequency" or "low lag" has a slight loading/catchup/frame drop every second or so.
its like a frame drop about every second, only when im running at full speed.
i can record a video to show what im talking about, and/or make a separate thread if its not related to this issue
Re: Screen tearing after playing Zelda LTTP for multiple hours.
weird, reproduced it with the SNES version posted above by Grabulosaure, and on the shadow mask version of the SNES core,
in vsync mode 0, 1, or 2 if i run full speed with mario, the screen is briefly loading/catching up every second or so
good example is the first levels of SMW, where you have a long section to run on the foreground and look at the background.
but, test suite does not do this in the scroll test, so maybe its just how SMW is??
maybe a video buffer maxout, due to so many sprites and objects entering the screen when running at full speed?
i will have to check on my actual SNES and CRT and report back
EDIT *****
yes, happens on SNES with a CRT. i guess this is just how mario has always played, but ive never noticed
EDIT *****
in vsync mode 0, 1, or 2 if i run full speed with mario, the screen is briefly loading/catching up every second or so
good example is the first levels of SMW, where you have a long section to run on the foreground and look at the background.
but, test suite does not do this in the scroll test, so maybe its just how SMW is??
maybe a video buffer maxout, due to so many sprites and objects entering the screen when running at full speed?
i will have to check on my actual SNES and CRT and report back
EDIT *****
yes, happens on SNES with a CRT. i guess this is just how mario has always played, but ive never noticed
EDIT *****
-
- Top Contributor
- Posts: 1019
- Joined: Thu Dec 10, 2020 5:44 pm
- Has thanked: 315 times
- Been thanked: 238 times
Re: Screen tearing after playing Zelda LTTP for multiple hours.
That's potentially interesting for all those complaints about SMW scrolling on LG CX!