Graphics/game/low level programming. Former Apple engineer.

Georgia
Joined October 2011
My UI library is now twice as fast thanks new a single draw call UI renderer: every layer is an instanced textured quad. Stroke, rounded corners, clipping, and fill are handled in the shader... 1/n
15
8
318
20,264
Recently attended an in-person handheld game console hackathon. I wrote a raycaster by hand. Someone wearing a “I ❤️ slop” tshirt saw mine and said “oh I wrote a ray caster too!”. They showed me. It was a ray *tracer* and claude did all the work. The person didn’t know basic graphics terms. They couldn’t answer basic questions about how it worked, could only talk about their prompting harness. Sad how AI is ruining the craft and community for people that actually like to program and have spent their lives getting good at it.
37
367
77
5,977
308,370
The problem is not that they used AI, or didn’t know things. The problem is they *liked* not knowing, AND that they didn’t use the in-person event the way it was intended: to exchange ideas with others. I would’ve been happy to teach, but they didn’t ask any questions and didn’t care to talk about anything but AI. They didn’t even *ask the AI* how their project worked. Willful Ignorance is not a virtue.
1
24
8
696
21,950
TIL the "mip" in mipmapping stands for multum in parvo, Latin for "many things in a small place"
I’m studying the ancient texts.
15
131
1
2,182
40,344
FYI: you can indent your C preprocessor directives like this
33
16
2
590
34,491
I prefer the whitespace after the # instead of before because many editors and reformatting tools remove whitespace before the # When any preprocessor if/else body is long, I'll still add a comment after the endif to make it clear what it pairs with:
3
1
27
4,330
My C generics trick got approval from the legendary Sean Barrett!
15
26
4
898
34,292
oh no my side project is more interesting than my main project
4
2
32
2,632
I’m studying the ancient texts.
18
20
2
934
58,288
AFAIK it’s still the best single book for filling holes in graphics knowledge. Wish there was a 5th edition — a lot has changed since 2018!
2
53
2,231
I used the perpetual license + 1 year of updates model for @principleapp and I regret it. It seemed like a fair approach to monetizing native local-only software but it causes a lot of problems. At that one year mark people don’t feel like they’re getting free use forever, they feel like they’re losing updates. I have to constantly justify how it’s is a good deal. People kind of understand not getting new features after a year but they’re pissed if they have to pay to get a bug fixed. I attempted to offer free bug fix updates, but it was a huge task to patch and release updates for every version ever released. I have 11 years of versions out there now! In many cases the code had changed enough between versions that I couldn’t automatically apply the same diff to all versions. lesson learned. Free bug fix updates are only practical for the newest version. The licensing model causes users to all end up on different versions. Technical Support is harder because the answer to some questions depends on what version they’re using. People on old versions regularly email me about bugs and features that I addressed years ago. Server side features are problematic because I have to maintain old api endpoints “forever”. Principle interacts with Sketch and Figma and whenever those programs change their file format or api (which they do often) I have to do an unplanned update to restore compatibility. When this happens, users on old versions feel like either my software has a bug, or I am taking away features and charging to give them back. It’s a hard explain “if you don’t want to update Principle you need to downgrade sketch” because they had often just paid for a new sketch license. In Figma’s case, users *cant* go back to the old version because it’s a web app! I had to create a server side file that would tell Principle what versions of sketch and figma it is compatible with so it shows a nice incompatibility message instead of crashing or corrupting data. Unfortunately the niceness of that message just appears to some users like a planned incompatibility to make them pay. The licensing model creates a perverse incentive for me to wait more than a year between releasing major updates. I’ve never let that affect my plans but I’m aware that strategically I’d be better off operating that way. So I had to deal with all that while making way less money than if I had used a subscription model. I was naive 11 years ago when I chose this licensing model. I only considered fairness without understanding its other implications. I think subscriptions don’t have to be predatory if you offer partial refunds for people that forgot about the subscription, proactively cancel subscriptions that haven’t been used in a long time, and offer tiers (free, basic, pro, enterprise).
I'm not sure at what point this entitlement settled in that perpetual licenses must also include perpetual updates? Do people think good software grows on trees? When did we suddenly OWE you anything?
13
4
4
86
15,785
New Apple Clang feature gives C bounds safety checks via the __counted_by() attribute. Compiler automatically carries range information into locals too
10
10
2
301
28,521
Now that I've ported to linux, I'll find out firsthand if developing for linux is financially sustainable. I've gotten a lot of interest from linux users but culturally seems like they won't pay for software.
8
1
58
8,053
Took 2 days to port to linux. Just had to port a few os-specific functions (timing, threading, files), and make a linux sysroot so zig cc could cross-compile. A few things I learned about linux dev... 1/n
4
28
2,804
Most of today was spent on the eBPF code that captures fork/exec/exit. eBPF is weird: it is its own instruction set that gets verified and then JIT-ed by the kernel before running. You have to write the code in weird ways to appease its verifier, for example... 4/n
1
3
589
Weird things about eBPF programming: - kernel will only load your eBPF program if it's GPL licensed! - no unbounded loops - 512-byte stack - no libc - eBPF programs have an instruction limit - kernel's struct layouts aren't stable so all field offsets get auto-rewritten 5/n
1
7
598