The Shape of Everything
A website mostly about Mac stuff, written by Gus Mueller
» Acorn
» Twitter
» Maybe Pizza?
» Code
» Archive
December 8, 2017

I'm taking a little break from building out the New App to get started on Acorn 6.1. I don't do code names for releases anymore, but if I did this one would be called Acorn "Whatever Gus F'n Wants to Do" Version 6.1.

So what do I want to do in 6.1? A couple of things. No new user facing features, updating the pixel plumbing, and an option for bringing color back to the UI (color has actually already started for 6.0.4, with a secret defaults pref: defaults write com.flyingmeat.Acorn6 colorPalette 1. If you turn it on it's obviously not finished, but you might like it better regardless).

Why would I want to update the "pixel plumbing" and just what does this plumbing really mean?

Acorn versions 4 through 6 store the memory for your layers in your computer's main memory- ie, not on the GPU. Drawing is still done through the GPU via OpenGL, but in most cases I make sure that the pixel processing happens on the CPU.

There's a couple of really good reasons to have the pixel processing happen on the CPU. The main reason I've done this is for fidelity. For many years GPUs have been more concerned about speed than accuracy. Well, I care about accuracy so that's why Acorn has filters running on the CPU.

Another reason is so Acorn has easy and fast access to the pixels for operations which can't be done on the GPU in a reasonable manner. Things like seed fill operations (which make up flood fill, magic wand, instant alpha) need quick access to the pixels and I haven't found a great way to run that on the GPU yet. It's not an inherently parallel operation.

And the the last major reason is just about the amount of memory Acorn can gobble up. I've had people create and edit terapixel images in Acorn (Mega: 1 million pixels. Giga: 1 billion pixels. Terra: 1 trillion pixels). It might be slow, but it's possible. My fear is that if someone tries to do that with the GPU, then that just won't be possible because of the limited amount of memory available there. (The obvious solution to this is to fallback to CPU rendering in these cases, but to be honest I haven't really explored that yet.)

This past summer at WWDC I got some good news about Core Image on the GPU- most of my concerns about fidelity are gone in MacOS 10.13 High Sierra. So I decided then that Acorn 6.1 would try and switch to Metal when running on 10.13.

Then 10.13 was released, and I put out the usual maintenance releases to fix little bugs that come with any major OS update. But something very odd happened as well- 10.13 customers were reporting slow brushing with images up to a certain size. I couldn't get the problem to reproduce on my test images, so I had folks send in the images they were having problems with and all of a sudden I got the problems to reproduce. The problem on my end was that the images I was testing with were too big.

What was going on? Core Image was taking my images created in main memory and copying them to (what I presume to be) IOSurfaceRefs. This is fine for smaller images, but when you get to bigger images those copies can take a while. But there's an upper limit to the amount of memory Core Image is willing to copy before it says screw it, and my test images were over that limit. So instead of making copies to an internal CI only buffer, it would then reference the original memory for these giant images. So brushing on big images was ironically faster.

While I've got some workarounds in Acorn 6.0.4 to keep copying down to a minimum, it isn't a solution I'm happy with. Instead I should change how Acorn stores the memory for images to something which has less of an impedance mismatch with Core Image.

So not only is Acorn 6.1 switching to Metal on 10.13 High Sierra, it will also be switching to using IOSurfaceRefs to store the pixels in. These are two very big changes and I've made some great progress over the past week with this, so I'm 99.9% sure it'll ship this way.

So that's what the new pixel plumbing will look like. Moving Acorn from local memory backed images (CGImageRef + CGBitmapContext) and pushing through OpenGL, to IOSurfaceRef backed images and pushing things through Metal 2.

It's been fun so far, and hopefully I'll have a test build later this month or early 2018 for people to play with.