Today’s cursed CMake:
if bringing external dependencies directly into the build, such as with `FetchContent` or a direct call to `add_subdirectory()`, and one of those dependencies has such a call to `option(BUILD_SHARED_LIBS …)`, the top level project must also call `option(BUILD_SHARED_LIBS …)` before bringing in its dependencies. Failure to do so can lead to different behavior between the first and subsequent CMake runs.
That’s some nasty linker error to debug
WIP Galaxy renderer in Vulkan
I did something similar in Rust + wgpu a few years ago, but that project was abandoned and also looked pretty ugly. I want to give it another try.
git LFS + multiple remote mirrors (one for my personal Forgejo instance and another for Codeberg) are annoying
- Forgejo’s push mirror: does not sync large files
- one remote with multiple push URLs: only push large files to the “first” push URLs
- multiple remotes: seems to work. But it’s annoying since I need to “git push“ multiple times for different remotes now
Some advice I gave someone on Discord today:
A common beginner mistake is to optimize by vibes just because some experts said “doing X is more efficient than Y”, “avoid doing Z”, etc. Further, different applications can have drastically different performance characteristics and requirements. One can easily micro-optimize for nanoseconds when the program wastes seconds elsewhere. Writing code with performance in mind is good. But don’t think too hard or perform micro-optimization until
- you identified some performance problems
- you measured that your optimization meaningfully improves performance
by profiling and benchmarking
Weekend project: Compute Toy: compute shader-based Shadertoy-like thing. It uses my existing Vulkan project infrastructure, like shader hot reloading.
Shader in the demo is copied from the “Raymarching - Primitives” shader on shadertoy
Baby’s WIP Vulkan render graph implementation.
I am still working out how best to automatically generate barriers. The current heuristic is fairly coarse and may limit expressiveness.
Good bye vkCmdPipelineBarrier2.

A nice side effect of converting an old C++ project to use C++20 modules is that I no longer need to think about which header to include to use particular functions. I am using a much larger granularity for modules (one CMake target per module), whereas before I had hundreds of small header files.
What a good treat when you are learning something (generating functions in my case) and find a blog post written by someone you know: Dice, (De)Convolution and Generating Functions. Thank you, @demofox.
Also, it’s a good observation that generating functions are like the Z-transform (and also Fourier/Laplace in continuous space). All of those solve problems by transforming into a different space, solving the problem there, and then transforming back.
TIL about Rust ‘s Option::transpose. Pretty cool stuff:
// this will give you Result<Option<T>, E>optional.map(|v| something_that_can_fail(v)).transpose()Since I reduced my use of em dashes (it’s pretty hard to type anyway), my new best friend is parentheses. (Parentheses are really cool since you can use them to express non-linear flow, and you can also nest them (like this (isn’t this cool?)))
What? It’s hard to read? If you can read Lisp (I am sure, you, my target audience, can), this is a piece of cake
Added Mastodon comments functionality to my blog (the function is already there for the “microblog” section, and I just added it to regular posts).
Now, if I link a Mastodon post in a blog entry, all the replies from Mastodon will appear on the page.
Test page: Fifty Shades of OOP
I hope generators get more love in the C++ circle.
Unfortunately, I think a C++ coroutine-based generator has a non-trivial overhead compared to a hand-written iterator or state machine. It probably doesn’t matter for a lot of use cases (like the example the author showed).
Looking at Unity finally made me understand the point of C++ coroutines
BTW, there’s tension here about how to present this stuff. The example author showed is clear for someone with gamedev experience, but I am not sure if it is as easy to comprehend for people with a different background. At least when I’m shown “practical examples” in a domain I am completely unfamiliar with, it’s usually a distraction for me.
Just set up AdGuard Home on a new Raspberry Pi for the first time. As someone who has never used a Raspberry Pi before, this whole process of assembling the case, installing the OS, and installing the software took less than 2 hours (I’d expect it to take like a whole weekend). Pleasantly surprised


I don’t know. The complexity of this issue (both implementations and the mental overhead of programmers) just to save a few keystrokes makes me feel it’s not really worthwhile? It feels more like a fashion when the convinience is debatable?
Haven’t done webdev for a while, and it seems (at least some) things are getting better. TIL HTML popover attribute, goodbye to all the previous hacks with an invisible checkbox + label to achieve a “no-js dropdown menu”. A bonus point is that keyboard focus and dismissal with either “esc” or mouse clicks all work out of the box.
My PostgreSQL database got nuked lol
Ugh. Needless to say, I’ve made the same mistake in almost all my docker-compose files. I am only saved because
- I don’t have any database ports exposed directly via Docker
- I have an extra firewall setup at the VPS’s web console
Update (an hour later): while trying to fix this, I somehow nuked my own PostgreSQL database in one of my containers. No idea why. Lucky I have backups
TIL falling factorial:
It’s interesting that
It’s also interesting that with the falling factorial definition, one doesn’t need to think about what the value of “negative factorial.” It just works when
Lesson learned: do not put a Forgejo instance behind Cloudflare proxy. It breaks SSH over git, and also causes some weird session-related issues
Baby’s first Forgejo actions pipeline. Can probably reduce my GitHub Actions usage substantially (the only use case not covered is for Windows runners)

Quoting Arseny Kapoulkine:
It’s funny to see some folks advocate ECS but if you ask them what they think of GoF design patterns they’d bring out the pitchforks.
Further down:
So to me GoF patterns are about:
- a core of the idea that is sensible
- wrapped into restrictive language specific monstrosity
- blindly applied to problems regardless of the fit
- replacing problem solving and thinking with “pattern” matching
- with a pointless taxonomy nobody asked for.
… wait, but ECS is all of these too.
IMO ECS is useful if
- you have a large number of entities where performance matters
- you entities have many variants, and you basically need the flexibility akin to a dynamic-typed language to handle them
Most hobbyist games have neither, but most people talking about ECS are hobbyists who don’t actually ship games at the end.
If you only have 2, then just do something ad-hoc procedural, or OOP, it will probably be cleaner and easier to write.
If you only have 1 (e.g., in rendering or physical simulation), then bespoke data-oriented design can bring much more performance compared to ECS.
So I don’t see how ECS can bring benefit if the game is neither medium-to-large scale game (also where the game category demands you to have entities of huge quantity and variety) nor game engines that don’t know what games they are targeting.