• Search Lesley's Website

  • Microblog

    Welcome to my microblog, a collection of short-form (often unpolished) posts typically published first on social media platforms and then cross-posted here.

    Substribe toMicroblog(this is a seperate feed from my mainblog)

    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 piece of code show casing render graph in action. It has two passes: "compute drawing" and "blit". No manual pipeline barriers are inserted.

    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

    A little Raspberry Pi board in a semi-transparent plastic case

    UI dashboard of AdGuard home

    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?

    No Semicolons Needed

    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 is very often seen (pick from choices, then pick from choices, etc), but I didn’t know if it has a single notation.

    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)

    Screenshot of the Forgejo web UI showing CI build and test jobs for a Rust project

    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

    1. you have a large number of entities where performance matters
    2. 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.