Sign in

Patrick Walton

@pcwalton.turbofishstudios.com
2.6K followers 48 following 167 posts

Programming languages and graphics person. Rust compiler and Firefox contributor. Currently working on an unannounced project!

PostsRepliesMedia
Patrick Walton @pcwalton.turbofishstudios.com · 14/04/2026
This mess is a stress test of Bevy 0.19 with 2,000,000 instances of 100,000 separate meshes. Runs at 60 FPS on my laptop. Each of the 2M mesh instances is a separate entity. There's no special "instanced mesh" component needed; the GPU driven rendering does all the batching automatically.
Grayscale static (essentially) in a window saying "many_cubes"
21369
Patrick Walton @pcwalton.turbofishstudios.com · 09/02/2026
The GPU clustering itself runs at about 110 μs, a speedup of 30x over Bevy 0.18 on this stress test. It automatically resizes the clusters as necessary for best performance. There are no arbitrary limits on the number of lights or clusters. The same system handles light probes and decals too.
A screenshot of the Nsight profiler, showing that the GPU clustering takes 108.736 μs
0120
Patrick Walton @pcwalton.turbofishstudios.com · 09/02/2026
In my GPU clustering branch, which is making its way through review, Bevy 0.19 can render ~8,000 visible lights (of 100k total) at about 200 FPS on my laptop 4070. This also adds the infrastructure for particle systems to emit lights entirely from GPU without any CPU involvement at all.
A screenshot of Bevy's `many_lights` stress test, showing about 8,000 small colored lightsA screenshot of the Tracy profiler showing a frame of Bevy rendering at 4.22 ms
1776
Patrick Walton @pcwalton.turbofishstudios.com · 07/02/2026
I'm taking no position on the technical merits of Godot here, but I will say that this is the exact kind of thing people used to say about GCC right up until it and LLVM killed all the other compilers because they couldn't keep up.
These findings, combined with the general messaging of “we’re an engine made for our users and contributors, not an engine made for our own goals” (paraphrased heavily), gives me the impression that there is no plan. Godot will have the features people decide to build for themselves, or the features that lots of people ask for, on some sort of timeline. And even if you make a feature, there’s no guarantee it will get merged, even if it is highly upvoted. This doesn’t have to be a bad thing, but it does mean you can’t expect from Godot the sort of steady, planned, expected updates you can expect from a professional software company. This is a risk, and one that should not be dismissed out of hand if you’re a games company that needs to ship your game to pay the bills. Consider carefully whether or not you’re comfortable needing to review changes before taking new versions, or taking what is in the engine right now with no guarantee vague future promises will materialise, because that is the worst case scenario of this sort of development. (To be perfectly clear I am not saying this will come to pass with Godot, just that with their current structure it is very possible, and would leave you with no recourse).
1291
Patrick Walton @pcwalton.turbofishstudios.com · 03/02/2026
TIL about Autoconf quadrigraphs and I'm screaming
8.1.6 Quadrigraphs

When writing an Autoconf macro you may occasionally need to generate special characters that are difficult to express with the standard Autoconf quoting rules. For example, you may need to output the regular expression ‘[^[]’, which matches any character other than ‘[’. This expression contains unbalanced brackets so it cannot be put easily into an M4 macro.

Additionally, there are a few m4sugar macros (such as m4_split and m4_expand) which internally use special markers in addition to the regular quoting characters. If the arguments to these macros contain the literal strings ‘-=<{(’ or ‘)}>=-’, the macros might behave incorrectly.

You can work around these problems by using one of the following quadrigraphs:

‘@<:@’
    ‘[’
‘@:>@’
    ‘]’
‘@S|@’
    ‘$’
‘@%:@’
    ‘#’
‘@{:@’
    ‘(’
‘@:}@’
    ‘)’
‘@&t@’
    Expands to nothing. 

Quadrigraphs are replaced at a late stage of the translation process, after m4 is run, so they do not get in the way of M4 quoting. For example, the string ‘^@<:@’, independently of its quotation, appears as ‘^[’ in the output.
57013
Patrick Walton @pcwalton.turbofishstudios.com · 10/12/2025
I dusted off an old patch and landed the infrastructure for portals and mirrors in Bevy for 0.18: github.com/bevyengine/bevy/pull/13797 This builds the Lengyel oblique clip plane technique into the engine, which is the fastest way to do the clipping necessary for mirrors to work.
An example of mirrors in the Bevy game engine. A low-poly fox looks at a reflection of itself in a mirror.
0509
Patrick Walton @pcwalton.turbofishstudios.com · 09/12/2025
Landed normal maps, metallic/roughness maps, and emissive maps for clustered decals in Bevy 0.18: github.com/bevyengine/b... They compose with other decals and whatever maps are on the base material, if any. Additionally, in a custom shader you can use these textures for whatever you want.
A demonstration of many Bevy logo decals on a plane. Each decal has normal, metallic/roughness, and emissive maps. The plane has its own normal map.
1423
Patrick Walton @pcwalton.turbofishstudios.com · 13/08/2025
I think I just answered my own question, from Kent Dybvig's 1987 dissertation agl.cs.unm.edu/~williams/cs...
Lexical variable bindings are recorded in an environment structure. The environment is a list of pairs of lists, the two lists in each pair being a list of variables and a corresponding list of values. During the evaluation of any expression, the list of pairs corresponds to the nesting of the lambda expressions surrounding the expression; the first pair of lists contains the bindings for the closest enclosing lambda, the second contains the bindings for the next enclosing lambda, and so on.
This environment representation is often referred to as a rib cage because of its structure, and the list of variables and list of values are referred to as variable and value ribs. This structure is used as well in Chapter 3 and is described more completely there.
2180
Patrick Walton @pcwalton.turbofishstudios.com · 09/05/2025
Also something I realized: AArch64 has a scaled base + index addressing mode, so the lookup and branch in the compressed instruction case is 3 instructions. godbolt.org/z/nnWKcPcWc
030
Patrick Walton @pcwalton.turbofishstudios.com · 02/05/2025
And they say that comptime is better than generics.
1201