26 April 2021, 16:10 | #21 |
Registered User
Join Date: Jun 2020
Location: Druidia
Posts: 387
|
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 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; 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(); 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; 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. |
27 April 2021, 09:51 | #22 | |
Registered User
Join Date: Aug 2018
Location: Untergrund/Germany
Posts: 408
|
Quote:
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. |
|
27 April 2021, 12:43 | #23 | |
Registered User
Join Date: Jun 2020
Location: Brno
Posts: 90
|
Quote:
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? |
|
27 April 2021, 18:16 | #24 |
Registered User
Join Date: Jun 2020
Location: Druidia
Posts: 387
|
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! |
27 April 2021, 18:24 | #25 | |
Registered User
Join Date: Jun 2020
Location: Druidia
Posts: 387
|
Quote:
Thanks, like you I just followed other examples back in the day. But now I prefer to know why! |
|
28 April 2021, 15:34 | #26 |
Registered User
Join Date: Aug 2018
Location: Untergrund/Germany
Posts: 408
|
|
28 April 2021, 16:17 | #27 |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
|
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.
|
28 April 2021, 19:47 | #28 | |
Registered User
Join Date: Aug 2018
Location: Untergrund/Germany
Posts: 408
|
Quote:
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. |
|
28 April 2021, 21:08 | #29 | |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
|
Quote:
|
|
20 May 2021, 20:02 | #30 | |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
|
Quote:
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. |
|
20 May 2021, 21:09 | #31 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
A big step forward in perfect emulation! |
|
20 May 2021, 21:30 | #32 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
You can 'generate' the glitches even with only 3 active planes. oops, I've given you another hint |
|
20 May 2021, 22:03 | #33 |
Registered User
Join Date: Jun 2020
Location: Druidia
Posts: 387
|
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? |
20 May 2021, 22:10 | #34 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
|
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? |
21 May 2021, 17:21 | #35 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
|
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. |
21 May 2021, 21:29 | #36 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,409
|
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 |
21 May 2021, 22:11 | #37 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
|
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... |
22 May 2021, 06:02 | #38 |
Registered User
Join Date: Jun 2020
Location: Druidia
Posts: 387
|
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! |
22 May 2021, 20:48 | #39 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
|
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). |
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 |
|
|