English Amiga Board

English Amiga Board (https://eab.abime.net/index.php)
-   Coders. Asm / Hardware (https://eab.abime.net/forumdisplay.php?f=112)
-   -   Blitter interrupt during VERTB interrupt (https://eab.abime.net/showthread.php?t=89614)

phx 27 November 2017 15:18

Blitter interrupt during VERTB interrupt
 
In an unnamed project I have a queue with several 16x16 tiles to blit (each node has bitmap and tile image address). I thought about processing the queue with Blitter interrupts, so I am free to run any code I like while the Blitter is busy.

The problem: My main program is running in a VERTB interrupt, and I am probably confused. Both are level 3 interrupts, so the Blitter can never interrupt my program, right?

Does it make sense to change the interrupt mask with "MOVE #$2200,SR" during my VERTB interrupt to allow new level 3 interrupts again?

I really would like to have both: run my program in VERTB and use Blitter interrupts...

StingRay 27 November 2017 15:24

Read INTREQR to check what kind of level 3 interrupt was triggered (copper, blitter, vertical blank) and acknowledge them accordingly.

phx 27 November 2017 15:52

Hmm? Are you saying that Copper, Blitter and Vertb interrupts can interrupt each other?

That would be easy...

To clarify: I want several Blitter interrupts to be processed WHILE the VERTB interrupt handling is still running.

ross 27 November 2017 16:14

Quote:

Originally Posted by phx (Post 1202410)
Hmm? Are you saying that Copper, Blitter and Vertb interrupts can interrupt each other?

That would be easy...

No, StingRay refer to something different (a who required IRQ check).

The only way to get a same level IRQ is as you say, but you have to clean INTREQ VERTB first to avoid immediate re-trigger.
Or poll BLIT bit at some time in your VBL routine.. (not so good).

EDIT: and warning, the following VERTB can trigger :) (so better some semaphore in code)

phx 27 November 2017 16:52

Ahh, ok! Thanks. Makes sense.

The following VERTB should not interrupt me, otherwise my game engine is too slow and I have to optimize it. ;)

meynaf 27 November 2017 16:55

I think the best way to achieve this is to trigger a SoftInt (which is level 1) at the start of the vertical blank interrupt, then do the job in that new int.
Then this work can be interrupted by a level 3 interrupt and you have no risk of reentrancy.
How exactly this is done, depends if your code is OS friendly or not.

a/b 27 November 2017 17:00

VBL won't interrupt Blitter handler and vice versa. You'll need one handler and then check INTREQR bits and clear them appropriately, as pointed out above.
Something like:
Code:

  btst #6,$dff01e
  beq.b NotBlitter
  move.w #$0040,$dff09c
; start another blit here
NotBlitter:
  btst #5,$dff01e
  beq.b NotVBL
  move.w #$0020,$dff09c
; your main VBL code here
NotVBL:
  rte


ross 27 November 2017 17:12

Quote:

Originally Posted by meynaf (Post 1202421)
I think the best way to achieve this is to trigger a SoftInt (which is level 1) at the start of the vertical blank interrupt, then do the job in that new int.
Then this work can be interrupted by a level 3 interrupt and you have no risk of reentrancy.
How exactly this is done, depends if your code is OS friendly or not.

Interesting.. but a little dangerous.

If your "new VBL Level 1" is interrupted immediately by a blitter storm, and you needed to make some init before some raster position, you can have bad video glitch.

EDIT: indeed these are only theoretical speculations, if the BLIT or VBL IRQ drivers are slow then there is something wrong in code :D

Kalms 27 November 2017 17:22

Quote:

Originally Posted by a/b (Post 1202422)
VBL won't interrupt Blitter handler and vice versa. You'll need one handler and then check INTREQR bits and clear them appropriately, as pointed out above.
Something like:
Code:

  btst #6,$dff01e
  beq.b NotBlitter
  move.w #$0040,$dff09c
; start another blit here
NotBlitter:
  btst #5,$dff01e
  beq.b NotVBL
  move.w #$0020,$dff09c
; your main VBL code here
NotVBL:
  rte


You also need to change the IPL bits in SR. It's very fiddly, most other solutions (like moving heavy processing out of the VERTB handler) are better choices.

meynaf 27 November 2017 17:55

Quote:

Originally Posted by ross (Post 1202428)
Interesting.. but a little dangerous.

If your "new VBL Level 1" is interrupted immediately by a blitter storm, and you needed to make some init before some raster position, you can have bad video glitch.

Of course only the low priority stuff has to be put out of the vbl handler. This is, as Kalms said, moving heavy processing out of the vbl.

phx 27 November 2017 18:16

Indeed, I quite like the soft-int solution. Will think about it.
Thanks for your comments!

dissident 27 November 2017 20:43

Quote:

Originally Posted by phx (Post 1202406)
In an unnamed project I have a queue with several 16x16 tiles to blit (each node has bitmap and tile image address). I thought about processing the queue with Blitter interrupts, so I am free to run any code I like while the Blitter is busy.

This method will take lots of rastertime as your interrupt handler has to be executed for every blit. Only the rte command needs alone 20 cycles to be executed on the MC68000. This is only efficient, if you have few big blits in a queue. If possible, use the copper with a double buffered list to wait for the blitter instead. While waiting, the copper is off bus and could also feed the blitter faster than the CPU does. The only time critical thing would be updating the copperlist by the CPU with new values for the copper move commands. And if the amount of blits changes, you could initialize a copperlist for the maximum of blits and jump into this list with COP2LC/COPJMP2 at the end and step backwards blit by blit. So only the parts of the copperlist will be excuted which were initialized by the CPU.

Quote:

Originally Posted by phx (Post 1202406)
I really would like to have both: run my program in VERTB and use Blitter interrupts...

Does your main routine needs to run in supervisor mode? If not, you could also wait for the VBI by hand checking the INTREQR register and execute your main routine in user mode. So it would be no problem to interrupt it by a level3 blitter-finish-interrupt.

ross 27 November 2017 21:55

Hi dissident! Good ideas in your post but .. how to make them coexist real-time copper video effects with blitter register write that copper should do in "random" moments?

Create a (slow) copper list that already contains all possible blitter register writes in every lines?
[EDIT: yes, you can insert a simple COPxLC/COPJMPx pair, but then you need to limit your CMOVEs to defined quantity to not disrupt CWAIT code when you are back in the original list]

And there also the question of double writes to "slow bus".. first write to chip ram to fill copper list, then from copper to registers.

phx is not talking about a demo in which you manage the limitations you are subjected to, but a game where you have to make switches of various colors each line, modify BPLxPT, multiplexing sprite or who know :)

I'm not against this method, but I think that is useful for CWAIT (with BFD=0) in vertical video blank period only. And then in that case COP2LC/COPJMP2 idea is applicable.
I vaguely remember that i've debugged something similar.

phx 27 November 2017 23:28

Quote:

Originally Posted by dissident (Post 1202478)
This method will take lots of rastertime as your interrupt handler has to be executed for every blit. Only the rte command needs alone 20 cycles to be executed on the MC68000.

Yes. And the interrupt processing will also need more than 40 cycles, IIRC. I am not totally convinced myself that it will turn out as hoped, but the alternative is to waste all these cycles by waiting for the Blitter. There is not much else to do, as all data to feed the Blitter was already generated earlier.

How many cycles will pass, when blitting a 16x16 tile with 5 planes and mask? All DMA channels used.

Quote:

If possible, use the copper with a double buffered list to wait for the blitter instead.
I agree that this might be faster, but also extremely more complex to manage. I can have any number of tiles in the queue, at different times during the frame.


Quote:

Does your main routine needs to run in supervisor mode? If not, you could also wait for the VBI by hand checking the INTREQR register and execute your main routine in user mode.
I would really prefer when the game engine, which renders the frames, runs in an interrupt, triggered by VERTB. This way I have a kind of multitasking and let the "main program" do tasks which are not VERTB-synced, like reading data from the disk.


Quote:

Originally Posted by ross (Post 1202493)
phx is not talking about a demo in which you manage the limitations you are subjected to, but a game where you have to make switches of various colors each line, modify BPLxPT, multiplexing sprite or who know :)

Indeed, there will be multiplexed sprites, color changes and scrolling.

ross 28 November 2017 00:39

Quote:

Originally Posted by phx (Post 1202509)
I would really prefer when the game engine, which renders the frames, runs in an interrupt, triggered by VERTB. This way I have a kind of multitasking and let the "main program" do tasks which are not VERTB-synced, like reading data from the disk.

Coincidence.. just a couple of days ago I was thinking a very very similar system for asynchronous load and unpacking from floppy, with a running main prog. not from user mode but from level 1 IRQ.
Well, there are actually several reasons for this choice.
But too OT, maybe for another thread ;)

Toni Wilen 28 November 2017 15:57

There is not much gained by running CPU and blitter simultaneously if blitter cycle sequence does not have any idle cycles (which are always available for the CPU. Don't waste them!). In no-idle-cycle case CPU is immediately (technically after 2 or 3 cycles) blocked until blitter finishes.

IMHO it is practically only useful when clearing (every other blitter cycle is idle cycle) or D=A filling (every 3rd cycle is idle cycle). All other common channel combinations don't have idle cycles.

Only exception is if code is running in real fast ram. (or blitter nasty not set but why would you do that in a demo or game?)

dissident 29 November 2017 17:17

Quote:

Originally Posted by ross (Post 1202493)
Hi dissident! Good ideas in your post but .. how to make them coexist real-time copper video effects with blitter register write that copper should do in "random" moments?

Create a (slow) copper list that already contains all possible blitter register writes in every lines?

[EDIT: yes, you can insert a simple COPxLC/COPJMPx pair, but then you need to limit your CMOVEs to defined quantity to not disrupt CWAIT code when you are back in the original list]

Hi ross, it depends on the size of the blit to be done in a scanline. A coexist of real time copper effects with for example vertical rasterbars (Kefrens/Alcatraz-Bars) is possible. Just check my copper-demo http://www.pouet.net/prod.php?which=65627 . I combined there the rasterbars with a sheared effect by a bitplane shift and a vertical colourscroll line per line. For this routine I didn't need any COPJMPs as it is clear that every visible scanline there will be a blit.

For OCS, assuming the steady registers are already initialized and the A&B-pointers point to the repeated bar/mask pattern (8 colours) in memory which are increased after every blit automatically, this could look like this:

The CPU only changes the $xxxx positions, the display starts at $2C and is visible within the positions $81-$1C1, the blit and the BPLxPT updates are done in the horizontal blank area.

Code:

  DC.W $0040,$xxxx ;BLTCON0
  DC.W $0042,$xxxx ;BLTCON1
  DC.W $0048,$xxxx ;BLTCPTH
  DC.W $004a,$xxxx ;BLTCPTL
  DC.W $0054,$xxxx ;BLTDPTH
  DC.W $0056,$xxxx ;BLTDPTL
  DC.W $2bd3,$fffe  ;WAIT $D2,$2B
  DC.W $0058,(3*1*64)+(32/16);BLTSIZE 
  DC.W $2be1,$fffe  ;WAIT $E0,$2B
  DC.W $00e2,$0040 ;BPL1PTH
  DC.W $00ea,$nnnn ;BPL1PTL
  DC.W $00f2,$0040 ;BPL2PTH
  DC.W $00e6,$nnnn ;BPL2PTL
  DC.W $00ee,$0040 ;BPL3PTH
  DC.W $00f6,$nnnn ;BPL3PTL
  DC.W $0102,$xxxx ;BPLCON1
  DC.W $0180,$xxxx ;COLOR00
  DC.W $0001;$0000 ;Pseudo blitter finished (OCS A1000/2000A bug)
  DC.W $0001;$0000 ;The real blitter wait
  DC.W $0040,$xxxx ;BLTCON0
  DC.W $0042,$xxxx ;BLTCON1
  DC.W $0042,$xxxx ;BLTCON1
  DC.W $0048,$xxxx ;BLTCPTH
  DC.W $004a,$xxxx ;BLTCPTL
  DC.W $0054,$xxxx ;BLTDPTH
  DC.W $0056,$xxxx ;BLTDPTL
  DC.W $2bd3,$fffe  ;WAIT $D2,$2C
  ...



Quote:

Originally Posted by ross (Post 1202493)
And there also the question of double writes to "slow bus".. first write to chip ram to fill copper list, then from copper to registers.

It makes no difference. If you use the blitter finished interrupt, you also have to store the data for the blits in a buffer (which could be in FAST memory), read it and write the data to the blitter registers in the blitter interrupt routine.

Quote:

Originally Posted by ross (Post 1202493)
phx is not talking about a demo in which you manage the limitations you are subjected to, but a game where you have to make switches of various colors each line, modify BPLxPT, multiplexing sprite or who know :)

I understand. My first assumption was a vertical or horizontal fullscreen textscroll with 16x16 pixel characters. This routine could be also used to display a landscape created of different tiles.

Quote:

Originally Posted by ross (Post 1202493)
I'm not against this method, but I think that is useful for CWAIT (with BFD=0) in vertical video blank period only. And then in that case COP2LC/COPJMP2 idea is applicable.
I vaguely remember that i've debugged something similar.

Yes, this is a good idea as in the vertical blank area no bitplane DMA interrupts the blitter DMA.

dissident 29 November 2017 17:57

Quote:

Originally Posted by phx (Post 1202509)
Yes. And the interrupt processing will also need more than 40 cycles, IIRC. I am not totally convinced myself that it will turn out as hoped, but the alternative is to waste all these cycles by waiting for the Blitter. There is not much else to do, as all data to feed the Blitter was already generated earlier.

This is the same method you need waiting with the copper for the blitter. Your buffer mentioned above with all the blitter data is the copperlist.

Quote:

Originally Posted by phx (Post 1202509)
How many cycles will pass, when blitting a 16x16 tile with 5 planes and mask? All DMA channels used.

As the HRM says http://amigadev.elowar.com/read/ADCD.../node012A.html we could calculate it this way:

Code:

    8*16*5*2
t= ---------- =180,55 microseconds
      7.09

But this is only a theoretical value as bitplane DMA could steal some cycles and maybe slows the blitter down.

BTW: Why do you use all channels? I suppose these are your blits to copy objects in to a background picture.

Quote:

Originally Posted by phx (Post 1202509)
I agree that this might be faster, but also extremely more complex to manage. I can have any number of tiles in the queue, at different times during the frame.

Generally it is not so complex as you can see here: http://www.pouet.net/prod.php?which=71971 I used this method for the line blits for the Triple-Glenz and for the Vector-Balls copy blits. You just count the blits you need and calculate the copper jump-adress at the end. It behaves like a stack-pointer logic.

COP2LC-jump-pos already initialized by the CPU. The CPU only changes $xxxx.

Code:

cop1
  ...
  DC.W $008A,$0000 ;Jump to copperlist2


cop2
  ...
  DC.W $0001,$0000 <- Entry for second blit
  DC.W $0001,$0000
  DC.W $0040,$xxxx
  ....
  DC.W $0058,$xxxx

  DC.W $0001,$0000 <- Entry for first blit
  DC.W $0001,$0000
  DC.W $0040,$xxxx
  ....
  DC.W $0058,$xxxx

  DC.W $FFFF,$FFFE <- Entry for no blit

Quote:

Originally Posted by phx (Post 1202509)
I would really prefer when the game engine, which renders the frames, runs in an interrupt, triggered by VERTB. This way I have a kind of multitasking and let the "main program" do tasks which are not VERTB-synced, like reading data from the disk.

Okay, for this case this it is the best method using the VBI generating a level1-interrupt like meynaf already suggested.

Quote:

Originally Posted by phx (Post 1202509)
Indeed, there will be multiplexed sprites, color changes and scrolling.

So you could only do small blits for example every second line without any COPJMP:

Code:

  DC.W $2C01,$7FFE ;Wait y-pos & pseudo waitblit
  DC.W $0180,$xxxx
  DC.W $0001,$0000
  DC.W $0040,$xxxx
  ....
  DC.W $01FE,$0000 ;Changed to $0058,$xxxx if blit is used / needed

  DC.W $2D01,$FFFE
  DC.W $0180,$xxxx

  DC.W $2E01,$7FFE
  DC.W $0180,$xxxx
  DC.W $0001,$0000
  DC.W $0040,$xxxx
  ....
  DC.W $01FE,$0000 ;Changed to $0058,$xxxx if blit is used / needed


phx 29 November 2017 18:03

Toni is certainly right. This discouraged me so much that I reverted all my Blitter interrupt code last night. So I will just set Blitter to Nasty and copy all masked tiles.

phx 29 November 2017 18:30

Quote:

Originally Posted by dissident (Post 1202862)
BTW: Why do you use all channels? I suppose these are your blits to copy objects in to a background picture.

Foreground tile animations, and foreground tiles which have to be redrawn because BOBs moved behind them, or because of background tile animation.

Thanks for the examples with the Copper blits. I have to think about it. Maybe there will even be enough room after the last sprite-multiplexing in the middle of the screen (for a parallax effect). There shouldn't be much copper activity until end of frame.


All times are GMT +2. The time now is 21:39.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.

Page generated in 0.04928 seconds with 11 queries