English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 26 April 2021, 16:10   #21
Jobbo
Registered User
 
Jobbo's Avatar
 
Join Date: Jun 2020
Location: Druidia
Posts: 386
I've run into this synchronization problem again after changing some things around and I realize that I didn't completely fix things last time.

I do have a fix but I don't fully understand why it wasn't working in the first place.

I'll explain my code and see if anyone can help me understand where it was going wrong and if the fix is reasonable.

So... I have double buffered screen bitplanes and copper lists. Each copper list will set the bitplane pointers along with the bitplane controls and the color registers, it will then run some copper driven blits and finally it will attempt to flip to the other copper list before ending.

Here is the layout for one copper list:

Code:
    // Set bpl pointers.
    move bpl0pth
    move bpl0ptl
    .
    .etc
    .

    // Set bpl controls.
    move bplcon1
    .
    .etc
    .

    // Set colors.
    move color0
    .
    .etc
    .

    // Run some blits.
    wait blt
    wait blt
    move bltcon0
    .
    .etc - (for however many blits).
    .

    // Finally flip to the other copper list.
    move cop1lch
    move cop1lcl

    // End.
    wait end
It's a bit more complicated for the blits since I have it jumping around using cop2lc and returning with a cop1lc jump. But I don't think this is the issue. Also lets assume my blits all easily fit inside one frame.

What seems to be the problem is the copper list flip at the end. This doesn't seem to work exactly as I was hoping.

The way I start the copper list is pretty simple, in C code I do the following:

Code:
custom.cop1lc = (int) pFrontCopList;

WaitVbl();

custom.dmacon  = DMAF_SETCLR | DMAF_BLITTER | DMAF_COPPER | DMAF_RASTER | DMAF_MASTER | DMAF_BLITHOG;
Here WaitVbl will loop until vpos is NOT 311 and then loop until vpos IS 311.

The main loop is then basically something like:

Code:
// Do some slow stuff.
DoWork();

// Update the colors and scrolling in the front copper list.
// This assumes the front copper list has already finished
// setting the colors and bitplanes etc for the frame.
// It needs to update the front rather than the back because
// the blits we are about to add won't show up until two frames
// later.
UpdateColorsAndScrolling();

// Add blits to back buffer copper list.
AddBlits();

// Swap buffer pointers.
swap(pBackBpls, pFrontBpls);
swap(pBackCopList, pFrontCopList);

WaitVbl();
I realize I'm leaving out lots of details, but the short of it is that the main loop will calculate and patch the back buffer copper list while the copper is working through the front copper list.

The front copper list being executed by the copper will trigger blits to the back bitplane buffer.

Where it gets a little sketchy I suppose is that in order to update the correct copper list that will show the right colors and scrolling alongside the drawn blits we need to update the front copper list and assume it has already run past where we are updating.

Maybe this is part of the problem, but I'm not sure why since there is plenty of time between the top of the frame and when I make changes to the top of the front copper list.

In any case the fix I have is related to the copper list swapping that happens right at the end of my copper lists.

If I remove the cop1lc setting from the end of the copper lists and just do it in the main loop instead like so:

Code:
// Mainloops
DoWork();

// Etc...

// Swap buffer pointers.
swap(pBackBpls, pFrontBpls);
swap(pBackCopList, pFrontCopList);

WaitVbl();

// Set front copper list.
custom.cop1lc = (int) pFrontCopList;
Doing this will fix my problem, what it's doing makes sense but I'm not sure why there's a problem to fix.

It seems to suggest that with the copper lists doing the swap over it's somehow swapping too soon and causing my copper lists to be inverted, or something like that.

Anyway. This has been far too long and hard to explain. But I guess I am wondering what is wrong with the copper list swap-over I had setup. And also if the new fix is reasonable.

It would probably also be good to know really specifically at what time the copper gets auto reloaded with cop1lc. Is it right after line 311? With my new setup where I manually load cop1lc after a WaitVbl, is there some chance it'll already have progressed through the copper list for the old location? It seems like it would, but wouldn't get very far.

Does manually reloading cop1lc safely restart the copper from the beginning of the new list?

Maybe I should triple buffer the copper lists, but that seems like overkill?

Generally I also wonder why for games and demos I so often see people using the vbl interrupt rather than just busy waiting. I don't see an advantage to doing that.

Anyway thanks.

Last edited by Jobbo; 26 April 2021 at 16:23.
Jobbo is offline  
Old 27 April 2021, 09:51   #22
pink^abyss
Registered User
 
Join Date: Aug 2018
Location: Untergrund/Germany
Posts: 408
Quote:
Originally Posted by Jobbo View Post
Generally I also wonder why for games and demos I so often see people using the vbl interrupt rather than just busy waiting. I don't see an advantage to doing that.
I used copper blits too in 'Tiny Bobble'. To avoid synchronization issues I did set cop1lc at the top of my copperlist to a dummy copperlist that just showed the screen but without doing any copperblits. Cop1lc was then resetted in my 'end of screen' busy loop with the CPU. If the cpu was too slow this frame then nothing bad happend, because the CPU does handle the switching.
To still be able to have copper jumps i used only Cop2lc for them and patched these jumps every frame. I only had 4 blitter jumps to to patch (16 pixel bobs, 32 pixel bobs, and the same for restoring).

In your code above you write to cop1lc after waiting for line 311. Perhaps the vbl can interrupt you there?
In my code i waited for line 309 (just to be safe). I also disabled blitter dma before writting to cop1lc to avoid a hardware bug.

Last edited by pink^abyss; 27 April 2021 at 10:03.
pink^abyss is offline  
Old 27 April 2021, 12:43   #23
defor
Registered User
 
Join Date: Jun 2020
Location: Brno
Posts: 90
Quote:
Originally Posted by Jobbo View Post
Generally I also wonder why for games and demos I so often see people using the vbl interrupt rather than just busy waiting. I don't see an advantage to doing that.
I remember back in early 90s when learning Amiga programming, all tutorials for "demo" coding were using either VBI or SOFTI (from a copper-list). And so I used it as well. Last year, when I returned to hobby programming on Amiga, I wondered the same as you: Why bother with interrupt handling and waste CPU cycles (by jumping to/from supervisor mode).
http://eab.abime.net/showthread.php?t=103755
If one has some 'higher priority' code which should run 'in parallel' (for example: user mode does a decrunch while VBI code draws something), I see the reason. Otherwise not much?
defor is offline  
Old 27 April 2021, 18:16   #24
Jobbo
Registered User
 
Jobbo's Avatar
 
Join Date: Jun 2020
Location: Druidia
Posts: 386
Quote:
Originally Posted by pink^abyss View Post
I used copper blits too in 'Tiny Bobble'. ....

Pink


Definitely a good idea to handle long frames the way you have, so will probably copy that.


I'll have a think about the use of copjmp1/2. I might be able to do the same since there are only a few jump points.


I'll give the 309 wait a try as well.


Anyway thanks, lots of good suggestions!
Jobbo is offline  
Old 27 April 2021, 18:24   #25
Jobbo
Registered User
 
Jobbo's Avatar
 
Join Date: Jun 2020
Location: Druidia
Posts: 386
Quote:
Originally Posted by defor View Post
I remember back in early 90s when learning Amiga programming, all tutorials for "demo" coding were using either VBI or SOFTI (from a copper-list). And so I used it as well. Last year, when I returned to hobby programming on Amiga, I wondered the same as you: Why bother with interrupt handling and waste CPU cycles (by jumping to/from supervisor mode).
http://eab.abime.net/showthread.php?t=103755
If one has some 'higher priority' code which should run 'in parallel' (for example: user mode does a decrunch while VBI code draws something), I see the reason. Otherwise not much?

Thanks, like you I just followed other examples back in the day. But now I prefer to know why!
Jobbo is offline  
Old 28 April 2021, 15:34   #26
pink^abyss
Registered User
 
Join Date: Aug 2018
Location: Untergrund/Germany
Posts: 408
Quote:
Originally Posted by Jobbo View Post
Anyway thanks, lots of good suggestions!

Your welcome! Having copper blits (and having them stable) in a game is not easy. You need to solve many tiny issues and work around hardware bugs (plus the bugs you introduce yourself ).
Looking forward to your project!
pink^abyss is offline  
Old 28 April 2021, 16:17   #27
hooverphonique
ex. demoscener "Bigmama"
 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
Quote:
Originally Posted by pink^abyss View Post
I also disabled blitter dma before writting to cop1lc to avoid a hardware bug.
If the bug in question is what I think it is, it can only happen when you write COPxJMP with the cpu while the blitter is active; I never heard of writing to COPxLC proposed any danger.
hooverphonique is offline  
Old 28 April 2021, 19:47   #28
pink^abyss
Registered User
 
Join Date: Aug 2018
Location: Untergrund/Germany
Posts: 408
Quote:
Originally Posted by hooverphonique View Post
If the bug in question is what I think it is, it can only happen when you write COPxJMP with the cpu while the blitter is active; I never heard of writing to COPxLC proposed any danger.

I meant the blitter wait bug when doing copper blits. Depending on number of active bitplanes you need a different number of blitter waits, otherwise on OCS/ECS you will get garbage on the screen. If i remember right then one wait was ok for up to 4 planes, 5 planes needed at least two waits. I'm not sure if this now emulated in WinUAE.

My workaround, for the COPxJMP issue you mentioned, was to disable the blitter dma before writing to COPxJMP with the CPU.
pink^abyss is offline  
Old 28 April 2021, 21:08   #29
hooverphonique
ex. demoscener "Bigmama"
 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
Quote:
Originally Posted by pink^abyss View Post
I meant the blitter wait bug when doing copper blits. Depending on number of active bitplanes you need a different number of blitter waits, otherwise on OCS/ECS you will get garbage on the screen. If i remember right then one wait was ok for up to 4 planes, 5 planes needed at least two waits. I'm not sure if this now emulated in WinUAE.
Ahh, that one, yes - there is a recent thread on here discussing that..
hooverphonique is offline  
Old 20 May 2021, 20:02   #30
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,502
Quote:
Originally Posted by Toni Wilen View Post
This behavior is not yet fully known. But it seems two waits are needed to be 100% sure there are no glitches. (=WAIT ends too early)
After weeks of testing (hi ross!) and staring at logic analyzer captures trying to catch randomly happening glitches, exact requirements and cause for copper blitter wait graphics corruption without two back to back WAITs is finally fully known.

Not going to reveal it too soon but here are some hints first

- There is no new undocumented features.
- There is nothing wrong with the copper.
Toni Wilen is offline  
Old 20 May 2021, 21:09   #31
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Toni Wilen View Post
After weeks of testing (hi ross!) and staring at logic analyzer captures trying to catch randomly happening glitches, exact requirements and cause for copper blitter wait graphics corruption without two back to back WAITs is finally fully known.

Not going to reveal it too soon but here are some hints first

- There is no new undocumented features.
- There is nothing wrong with the copper.
It's nice to see all the glitches on WinUAE now too

A big step forward in perfect emulation!

ross is offline  
Old 20 May 2021, 21:30   #32
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by pink^abyss View Post
I meant the blitter wait bug when doing copper blits. Depending on number of active bitplanes you need a different number of blitter waits, otherwise on OCS/ECS you will get garbage on the screen. If i remember right then one wait was ok for up to 4 planes, 5 planes needed at least two waits. I'm not sure if this now emulated in WinUAE.
The cause is not the number of bitplanes, at least not directly.
You can 'generate' the glitches even with only 3 active planes.

oops, I've given you another hint
ross is offline  
Old 20 May 2021, 22:03   #33
Jobbo
Registered User
 
Jobbo's Avatar
 
Join Date: Jun 2020
Location: Druidia
Posts: 386
I'm not going to make any guesses.

But I would like to know if it's possible to get away with one blitter wait in certain situations and what those cases are?
Jobbo is offline  
Old 20 May 2021, 22:10   #34
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,502
Everything will be explained soon..

---

WAIT BFD=0 + WAIT BFD=0 is not required. First WAIT must have BFD=0. Second WAIT can have BFD=1. Or even WAIT BFD=0 + SKIP works too.

Isn't that interesting?
Toni Wilen is offline  
Old 21 May 2021, 17:21   #35
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,502
Copper blitter wait bug full details!

Simple example copper list:

MOVE something1,BLTCON0
... (more blitter register updates)
MOVE something2,BLTSIZE
WAIT ($0001, $0000)
MOVE something3,BLTCON0
... (more blitter register updates)
MOVE something4,BLTSIZE
WAIT ($0001, $0000)

4 lores bitplanes enabled (example only, it can even happen without bitplane DMA)
D=A blit. (to keep example simple, any non-line mode blit with D channel active can cause it)

xxxx = unused cycle.

Cycle diagram when everything works as expected:

...
A-DAT
BPL
D-DAT (After this second to last D write blit has finished. Even if final D write is still pending.)
BPL
D-DAT (final D write). This is also copper "wakeup" cycle. Copper needs free cycle after WAIT ends but cycle is still available for blitter/CPU.
BPL
COP ("MOVE something3,BLTCON0", first word)
BPL
COP ("MOVE something3,BLTCON0", second word)
.... (more BPL/COP pairs)
COP ("MOVE something4,BTLSIZE", second word)
BPL
COP ("MOVE something4,BTLSIZE", second word)
BPL
COP ($0001)
BPL
COP ($0000)
BPL
xxx
BPL
xxx
BPL
A-DAT

and so on.

Same cycle diagram including bug condition:

...
A-DAT
BPL
D-DAT
BPL
CPU (Blitter wanted this but CPU stole it)
BPL
COP ("MOVE something3,BLTCON0", first word)
BPL
COP ("MOVE something3,BLTCON0", second word)
.... (more BPL/COP pairs)
COP ("MOVE something4,BTLSIZE", first word)
BPL
COP ("MOVE something4,BTLSIZE", second word)
BPL
COP ($0001)
BPL
COP ($0000)
BPL
D-DAT (final D-write of previous blit! This is first available cycle for the blitter in this example, pending D was finally completed. This does not directly break already active blit because pending final D does not use blitter's channel sequencer, even written D value is correct. But final D write does add +2/-2 and modulo..)
BPL
xxx
BPL
A-DAT

Result: new blit works normally except D pointer value is wrong.

Wasn't that too simple and too obvious?

Bug "requirements":

- Blitter nasty off (CPU steals "important" blitter cycles)
- OCS/ECS. (Fixed in AGA by delaying blitter busy clear by 2 cycles if blit has D channel active and is not linemode)
- Enough DMA cycles that keeps blitter from getting any cycles until new blit's copper MOVEs start.
- D channel enabled and not line mode. (Line mode does not have 2 D-DAT writes when blit finishes)
- No two WAITs (*1)

*1) second WAIT fixes it because WAIT needs free cycle when it starts waiting and also need free cycle when WAIT wakes up. This guarantees 2 back to back copper cycles that are not used, one of them might be stolen by the CPU but one of them is guaranteed to be available for the blitter. Second WAIT can have BFD=1, second WAIT can also be dummy SKIP with BFD=1. WAIT and SKIP use same internal timing.

Even without bitplane DMA, enough back to back DMA cycles (for example multiple sprites active at the same time), can trigger this condition. The less copper MOVEs between WAIT and BLTDPT MOVE, the easier it can happen.

In practise only way to 100% guarantee bug free operation is to use 2xWAIT, require AGA or keep blitter nasty on.
Toni Wilen is offline  
Old 21 May 2021, 21:29   #36
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
That is fascinating!
I'm not even sure that'd really qualify as a 'bug' as much as an 'unexpected result'.

Thanks for looking into it in such detail
roondar is offline  
Old 21 May 2021, 22:11   #37
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,502
Yeah, as I said in previous "hint posts", there is no new undocumented features. It works as exactly as designed, unfortunately design had a hidden flaw.

Here is some history of tests done before real reason was found (if anyone cares):

- Blitter nasty on: problem disappeared.
- Code in fast RAM: problem disappeared.
- Try different number of bitplanes. Always happened if 3 or more.
- WAIT + dummy moves before BLTSIZE: no difference.
- WAIT BFD=0 + dummy SKIP (BFD=0 or BFD=1) or WAIT BFD=0 + WAIT BFD=1 (Problem disappeared. WTF? That can't make any sense. This was the big clue)
- Use different patterns in test graphics: pattern didn't change but this made it clear the position of graphics jumped horizontally. So it must be something to do with D channel.

Biggest problem was catching the problem with logic analyzer. I wasn't even sure what I was searching...
Toni Wilen is offline  
Old 22 May 2021, 06:02   #38
Jobbo
Registered User
 
Jobbo's Avatar
 
Join Date: Jun 2020
Location: Druidia
Posts: 386
Thanks for the details.

My take-away is that I only need 1 wait because I'm setting the nasty bit and I'm only drawing lines!

Wish I hadn't refactored everything to 2 waits a few weeks back!
Jobbo is offline  
Old 22 May 2021, 20:48   #39
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,502
There is possibly even more nasty situation. I noticed that test program sometimes (quite rarely) corrupted source data (and more) used for blits.

I couldn't duplicate this in emulation (at least not yet) but here is one example of this situation (catched in logic analyzer capture):

...
A-DAT
BPL
D-DAT
BPL
CPU (Blitter wanted this but CPU stole it)
BPL
COP ("MOVE something3,BLTCON0", first word)
BPL
COP ("MOVE something3,BLTCON0", second word)
BPL (near end of scanline, last BPL fetch)
COP ("MOVE something4,BLTDPTH", first word) (BLTDPTL would also cause same effect)
CPU (again stolen from blitter)
COP ("MOVE something4,BLTDPTH", second word)
D-DAT
...

BLTDPTH write does nothing (old value is not changed) because it is immediately followed by same channel DMA transfer. (Every DMA channel has same side-effect). It can be much more nasty because BLTDPTH uses old value but BLTDPTL uses new value (which gets properly set later in copper list).
Toni Wilen is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
blitter waits and hardware bugs jotd Coders. Asm / Hardware 39 16 September 2020 18:29
Multiple copper waits beyond 255 Auscoder Coders. Asm / Hardware 8 29 July 2019 12:56
Blitter-driven tile map Leffmann Coders. Tutorials 5 11 November 2015 17:17
non-atomic Copper waits for MrgCop? Samurai_Crow Coders. System 0 01 April 2014 20:07
Lack of blitter waits on A500 Codetapper Coders. Asm / Hardware 3 09 September 2012 13:45

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 16:36.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.11185 seconds with 15 queries