Saturday, 15 May 2021

Profiling and palette manipulation?

I was thinking more about the glitches I saw and race conditions in the code which also reared their heads in the prototype PC port. There are two areas of the code which could, under certain conditions, cause issues. The one relevant here occurs when the mainline code is (still) drawing the landscape and gets interrupted by the next VBLANK. Not that this should never happen on the original machine.

So a few profiling experiments tonight to see how much time is spent doing what.

I thought of using the background colour to indicate which area of code was being executed. I was shocked to see how much time was spent in the ISR - not actually running Scramble code but updating the Neo Geo display hardware or, more specifically, the tilemap palette (there's 1024 tiles to update every frame).

The background is set to RED in the ISR during the video hardware update, YELLOW when the Scramble ISR code is running, and BLUE when the mainline code is updating the landscape (drawing the right-most 2 columns).

Everything enabled

As you can see, it spends about two-thirds of the time in the ISR, and more than half of that is just updating the video hardware (red). When the ISR queues a few commands to be executed by the mainline code, the landscape draw function (blue) extends to the right-hand edge of the screen. This is where you'd see glitches before I disabled interrupts around the VRAM accesses.

I halved the number of tilemap palette updates and saw a correspondingly shorter red area. And after eliminating all tilemap palette updates, the red isn't even visible which means the (Scramble) sprite updates are taking very little time at all.

Updating only half the tilemap palette

Although the blue area sometimes moves a little towards the right-hand edge, I never saw it actually get there. What this tells me is that there's sufficient time to execute all the Scramble code on the 68K; it's just the VRAM accesses that are causing issues. So there's little point trying to optimise the generate ASM code any further I don't think.

So what can I do from here? Ideally the landscape drawing (blue) should be finished before the next VBLANK interrupt, otherwise it's possible some object can be drawn in the wrong column - even with the interrupt protection. That's because the ISR changes some variables used by the landscape drawing function.

One option is to update the palette only when the palette actually changes, and only for those tiles that have changed, rather than each and every tile every frame. But that doesn't actually change the worse-case scenario, and will only reduce the problem, not eliminate it. And the extra code could push the landscape update further into the next VBLANK.

The landscape draw function is also surprisingly slow, though it requires quite a few VRAM accesses as well. I could take a copy of the variables updated in the ISR at the start of the function which means it would only be critical that the ISR start before the next VBLANK...

Something I need to ponder further... feel free to provide suggestions.

Actually I just had a thought - how about updating the palette entries instead of updating all the tilemap entries!?! This might have merit... stay tuned!

UPDATE: I'm yet to try it, but I think this will work! On Scramble there's a colour (palette index) for each column (32 tiles) - so 32 index entries. I can simply assign each of the columns to its own Neo Geo palette, and then update the three words for each column every frame - a total of 32x3=96 writes and no VRAM address register slowing it down ever more!

No comments:

Post a Comment