English Amiga Board


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

 
 
Thread Tools
Old 12 January 2021, 00:17   #1
Jobbo
Registered User

Jobbo's Avatar
 
Join Date: Jun 2020
Location: Lexington, MA
Posts: 195
Copper driven blitter waits in WinUAE

[Edit] Turned out to be a copper setup bug.

I'm investigating a very strange bug in a demo effect where the colors are flickering intermittently.

I've been investigating the code for a while now but I had a thought that maybe the problem is that I'm only doing one wait between copper driven blits.

This had seemed to work fine for me until now.

Does WinUAE actually suffer from this problem, or am I looking in the wrong place again?

I understand that some old hardware will not wait correctly with just one blitter wait but for a demo I was going to ignore that.

Last edited by Jobbo; 14 January 2021 at 05:46.
Jobbo is offline  
Old 12 January 2021, 19:09   #2
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 46
Posts: 24,862
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)

A1000 (due to bltbusy wait bug which also affects copper blitter waits) can glitch more easily with only single WAIT. OCS/ECS can glitch in some special situations (which no one has managed to duplicate with simple test code so far..). AGA seems to have fixed it and single WAIT works fine.
Toni Wilen is offline  
Old 12 January 2021, 19:22   #3
Jobbo
Registered User

Jobbo's Avatar
 
Join Date: Jun 2020
Location: Lexington, MA
Posts: 195
Thanks for the response.

I'm seeing the issue in Winuae, haven't tried on real hardware. So was specifically interested to know if it's known to show up in Winuae?
Jobbo is offline  
Old 12 January 2021, 19:59   #4
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,371
Quote:
Originally Posted by Jobbo View Post
Thanks for the response.

I'm seeing the issue in Winuae, haven't tried on real hardware. So was specifically interested to know if it's known to show up in Winuae?
WinUAE does not emulate BFD single wait bug, at least till 4.4.0 version.

Are you sure it's not something different?
Could you publish an exe?
ross is offline  
Old 12 January 2021, 20:42   #5
Jobbo
Registered User

Jobbo's Avatar
 
Join Date: Jun 2020
Location: Lexington, MA
Posts: 195
Yes, I've attached the borked version and the working version.

It takes a little for them to initialize because I'm building the lookup tables.

The difference between the two in theory is just that the broken one is using an exp/log table for projection, nothing to do with the line drawing.

It's acting really weirdly, in WinUAE that comes with the VSCode plugin it'll run perfectly on A1200. But with my separate WinUAE install it works but there is a glitch at the start, which gets left behind, could just be timing issue if one frame takes too long.

Anyway regardless of different WinUAE affecting the A1200 version, it is weird that it works mostly on an A1200 but not an A500.

Any insight would be greatly appreciated.

[Edit] I've removed the links.

Last edited by Jobbo; 14 January 2021 at 05:39.
Jobbo is offline  
Old 12 January 2021, 20:55   #6
Jobbo
Registered User

Jobbo's Avatar
 
Join Date: Jun 2020
Location: Lexington, MA
Posts: 195
Just to add to the confusion I've only just noticed that if I run without the "endcli" option in VSCode then the problem goes away.

Might suggest the root fault has something to do with memory allocation. I only do one "chip" and one "any" allocations. But since I then have to make sure things get aligned to 64k it's possible that my code isn't correctly doing that.
Jobbo is offline  
Old 12 January 2021, 21:07   #7
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,371
The broken A500 version works if you set a fast CPU clock.. (even if a 68000)

EDIT: A500+ 1MB fast, base 68k speed, works.. so yes seems a timing/memory issue

EDIT2: also noticed you have some blitter setup with copper (at VBI), without blitter wait
Are you sure that this do not trash your setup at start (that only by chance works in some case, i.e. some timing and/or memory setup timing difference)?

Code:
00050000 0180 0020 0182 0660 0184 0000 0186 0770
00050010 0188 0CC0 018A 0000 018C 0880 018E 0000
00050020 0190 0000 0192 0000 0194 0000 0196 0000
00050030 0198 0000 019A 0000 019C 0000 019E 0000
00050040 00E0 0003 00E2 0500 00E4 0003 00E6 3700
00050050 00E8 0003 00EA 6900 00EC 0003 00EE 9B00
00050060 00F0 0003 00F2 CD00 00F4 0000 00F6 0000
00050070 0048 0004 0054 0004 0082 0084 0086 02C6

Last edited by ross; 12 January 2021 at 21:46.
ross is offline  
Old 12 January 2021, 21:47   #8
Jobbo
Registered User

Jobbo's Avatar
 
Join Date: Jun 2020
Location: Lexington, MA
Posts: 195
I'm going to have to carefully check the allocations are all landing where I'd expect.

I'll also check the blitter setup. I suspect it's not much of an issue since the blitter should always be done before the next frame. But for safety it would be wise to add a wait at there.
Jobbo is offline  
Old 13 January 2021, 16:10   #9
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 46
Posts: 24,862
Code does not guarantee copper initially starting at the beginning of display. Is that supposed to happen?
Toni Wilen is offline  
Old 13 January 2021, 16:33   #10
Jobbo
Registered User

Jobbo's Avatar
 
Join Date: Jun 2020
Location: Lexington, MA
Posts: 195
I've been starting to think the problem is with how I setup the initial cop1lc pointer and turn on the DMA.

I'm doing that with NO wait for the vbl and there is a small amount of code to get through before the first wait vbl on the update.

So far I haven't exactly figured out how to fix it.

What is good behavior for starting the copper? I have two copper lists that set the cop1lc pointer to one another at the end. But I start the process by setting cop1lc using the CPU and then turn on the DMA.

In working code if I start by setting the other list as the initial cop1lc then I can cause the broken behavior. So it would seem I might be running into a case where the back/front copper lists are inverted due to some timing issue.
Jobbo is offline  
Old 13 January 2021, 16:42   #11
Jobbo
Registered User

Jobbo's Avatar
 
Join Date: Jun 2020
Location: Lexington, MA
Posts: 195
I think I'm missing an initial strobe for copjmp1.
Jobbo is offline  
Old 13 January 2021, 16:47   #12
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 46
Posts: 24,862
Copper "remembers" that it has restarted (vsync detected) even if DMA is off. When DMA is later enabled (whatever the scanline), copper starts executing COP1LC immediately.

First waiting for line zero before enabling all DMA should fix it.

Strobe is not needed.
Toni Wilen is offline  
Old 13 January 2021, 16:52   #13
hooverphonique
ex. demoscener "Bigmama"

 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,266
Quote:
Originally Posted by Toni Wilen View Post
Copper "remembers" that it has restarted (vsync detected) even if DMA is off. When DMA is later enabled (whatever the scanline), copper starts executing COP1LC immediately.
Interesting - I did not know that! (I think )
hooverphonique is offline  
Old 13 January 2021, 19:56   #14
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 46
Posts: 24,862
Quote:
Originally Posted by hooverphonique View Post
Interesting - I did not know that! (I think )
DMA disable simply means "don't allow DMA", it does not prevent internal state machine state changes (except bitplane DMA and it also depends on chipset type, OCS and ECS have some differences).

For example blitter works similarly, writing to BLTSIZE when DMA is off will still "arm" the blitter. When blitter DMA is enabled, blitter starts immediately.
Toni Wilen is offline  
Old 14 January 2021, 05:39   #15
Jobbo
Registered User

Jobbo's Avatar
 
Join Date: Jun 2020
Location: Lexington, MA
Posts: 195
I think I've finally fixed my problem after much confusion.

There were really two issues.

The first was that I didn't have a vbl wait before starting up the DMA which meant the first frame could potentially be very short. If it was short enough then the copper lists would have swapped before my code expected which would lead to the back/front copper lists being inverted.

The second issue which probably caused most of the confusion and inconsistency was that immediately after starting the DMA I had some debug print messages using KPrintF. This is provided as part of Bartman's support code, it ends up calling RawDoFmt and then some UAE debug log function it maps to. Anyway, this code takes some time to complete which would not help with the first issue. But what was more confusing was that it takes a different amount of time in the vanilla WinUAE install. That difference would lead to my code running differently in the two version of WinUAE.

The short of it is that it was a bit stupid to put the debug code between starting DMA and the first frame.

Through this all I did completely reconfigure the GCC options so I'll know if I write anything that might cause undefined behavior, and I also updated my copper blits so they'll have two waits.

Thanks everyone for your help!
Jobbo is offline  
Old 17 January 2021, 15:44   #16
Antiriad_UK
OCS forever!

Antiriad_UK's Avatar
 
Join Date: Mar 2019
Location: Birmingham, UK
Posts: 395
Quote:
Originally Posted by Toni Wilen View Post
Copper "remembers" that it has restarted (vsync detected) even if DMA is off. When DMA is later enabled (whatever the scanline), copper starts executing COP1LC immediately.

First waiting for line zero before enabling all DMA should fix it.

Strobe is not needed.
I was just playing around with this as part of the other startup/shutdown thread. What I am seeing is that the copper starts executing the list that was at cop1lc at the time of the vblank and not it's current value. Which thinking about it makes sense. For example,

;disable copper dma
move.l #list1,cop1lch
;wait for vblank
move.l #list2,cop1lch
;enable copper dma, list1 actually runs as it was the last "triggered". At next vblank list2 is installed

Does that sound correct?
Antiriad_UK is offline  
Old 17 January 2021, 16:33   #17
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,371
Quote:
Originally Posted by Antiriad_UK View Post
I was just playing around with this as part of the other startup/shutdown thread. What I am seeing is that the copper starts executing the list that was at cop1lc at the time of the vblank and not it's current value. Which thinking about it makes sense. For example,

;disable copper dma
move.l #list1,cop1lch
;wait for vblank
move.l #list2,cop1lch
;enable copper dma, list1 actually runs as it was the last "triggered". At next vblank list2 is installed

Does that sound correct?
Yes this works, but for a simple reason: your copper DMA reactivation is done not nuch after the VB.
If for any reason you have an IRQ or init code that 'moves' the reactivation of the copper further down the video, you may have problems.

Better if you reverse it like this:
;disable copper dma
move.l #list1,cop1lch
;wait for vblank
; immediately enable copper dma, list1 actually runs as it was the last "triggered" (better if you are sure that no interruption can come).
move.l # list2, cop1lch ;At next vblank list2 is installed
ross is offline  
Old 17 January 2021, 16:43   #18
Antiriad_UK
OCS forever!

Antiriad_UK's Avatar
 
Join Date: Mar 2019
Location: Birmingham, UK
Posts: 395
Yes I wasn't trying to "use" this it was just explaining a weird situation I had previously worked around.

I had a custom list that disabled sprite dma. On restoring system I had this order:
;wait vblank
;disable dma
;restore system CL
;restore system DMA

Result = mouse pointer sprite still disabled because the custom CL ran one more time after renabling copper. If I add one more vblank wait like so it works:
;wait vblank
;disable dma
;restore system CL
;>> WAIT for vblank <<
;restore system DMA
Antiriad_UK is offline  
Old 17 January 2021, 16:53   #19
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,371
Quote:
Originally Posted by Antiriad_UK View Post
Yes I wasn't trying to "use" this it was just explaining a weird situation I had previously worked around.

I had a custom list that disabled sprite dma. On restoring system I had this order:
;wait vblank
;disable dma
;restore system CL
;restore system DMA

Result = mouse pointer sprite still disabled because the custom CL ran one more time after renabling copper. If I add one more vblank wait like so it works:
;wait vblank
;disable dma
;restore system CL
;>> WAIT for vblank <<
;restore system DMA
yep, even in my code you can often find those that seem more WaitTOF than they should.
In fact, there is a reason, for the 'unfortunate' cases
ross is offline  
Old 05 February 2021, 19:49   #20
Photon
Moderator

Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 4,963
When preparing Copper blit lists, clean Copper swaps are vital, because if it's a pure blit list, it no longer contains anything to sync to the raster with, causing it to skip one frame and autocorrect itself.

For clean Copper swap in general, putting a (VHPOS) WAIT instruction before modifying custom registers at the start of the Copper list helps - if you do Copper swaps with the VBI.

Another point is that when switching scenes there will be a frame displaying the (empty) front buffer as the very first copper list is executed, drawing to the back buffer. This creates a gap in visuals.

For normal code that uses the CPU or Blitter directly to draw stuff, you can prepare a clean switch without this gap; you can still display the old scene. This is not really possible when switching to a scene that has a Copper blit list unless the new scene has <= number of bitplane DMA (more accurately, less DMA total to allow the Blitter to finish before the swap to what's been drawn). Then, you can poke the old bitplane pointers and values into the new Copper list being run the first time.

A great way to mitigate these raster timing headaches is to use a "header" Copper list which is poked by the VBI and which contains a VHPOS wait, and then jump COP2 which contains a prepared Copper blit list.

However, this header Copper list can be replaced by a VBI which pokes (or copies from dynamic structures to) custom registers directly, which is even better. This separates out the scene swaps from any workload the Copper is to process, without having to even use COP2.
Photon is online now  
 


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 00:20.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.
Page generated in 0.11550 seconds with 13 queries