Game engine release announcements usually read like supermarket receipts: long lists, verbs like "added" and "fixed," nothing memorable afterward. At 9:41 PM on October 8, 2026, the Bevy 0.20.0 tag shipped with 227 contributors and 817 pull requests. Only three items in that list are worth pausing on, because each is a decision rather than a feature.
Bevy is a free, open-source, data-driven game engine written in Rust. The criteria for picking these three are simple: one decides the language, one decides the direction of defaults, and one decides whether to trade image quality for performance.
Decision 1: Retire a dialect, adopt a standard
Bevy's shader language has switched to WESL. This is not a new option being added — support for the old Custom Bevy Extended WGSL dialect has been removed entirely. The migration rule is straightforward: custom shaders written in the old dialect must be translated to WESL, and file extensions change from .wgsl to .wesl. Pure WGSL files with no preprocessor directives remain usable.
WESL is an extension standard for WGSL that adds usability features like modules, imports, and conditional compilation. The project's rationale is a value judgment: it is better for the broader shader ecosystem to converge on a shared standard, pooling resources for language improvements, a module ecosystem, and IDE tooling.
Switching standards usually means ecosystem weight shifting. Accumulated experience on the old dialect must be re-translated, while the WESL team advances in parallel, jointly planning future shader development. The announcement does not state how many existing projects and plugins are affected by the migration.
Decision 2: Turn the quality switch off by default
Solari is Bevy's real-time path-tracing renderer. In this version it improved considerably: the ReSTIR implementation is now essentially unbiased, with less noise and more accurate light reproduction; shadows of moving objects no longer lag; reflections in motion flicker less, especially on non-metallic surfaces. The range of supported Bevy rendering features also expanded.
Then the project made a decision that will surprise upgraders: ReSTIR is now optional and disabled by default.
The stated reason is that in many scenes ReSTIR "eats a non-trivial performance budget without significantly improving image quality." The cost is stated plainly: with it off, expect lower shadow quality in scenes with many lights, plus missing motion shadows. Users of 0.19 who relied on ReSTIR should check whether their scenes are affected and re-enable SolariLighting::restir if needed.
The weight of this lies in the reversal of direction. A renderer optimizes ReSTIR for quality and performance, then turns it off by default. This usually means the marginal benefit of the quality gain has fallen below the performance cost — the team prefers a stable default tier, letting those who want maximum quality opt in explicitly.
| Item | 0.19 | 0.20 | |---|---|---| | ReSTIR | On by default | Off by default, can be enabled explicitly | | Quality without ReSTIR | Better than no ReSTIR | Lower shadow quality in many-light scenes | | Performance | Noticeable cost | A sizable performance saving | | macOS support | None | Yes, but no built-in denoiser |
macOS deserves its own note. Solari now runs on macOS via Metal, but the announcement explicitly states that bevy_solari currently ships no built-in denoiser for macOS, listing MetalFX Ray Reconstruction as a possible future solution.
Read together with the ReSTIR default change, a consistent trade-off direction emerges: both ends of rendering quality chose conservatism. Denoising is deferred to a future API rather than implemented in-house; ReSTIR is left to users to enable per scene. Performance budget takes priority over quality defaults; the remaining quality is left for users to tune.
Decision 3: Trade annotations for speed
Two numbers in this release deserve to be pulled out separately, because their magnitudes are entirely different.
The new despawn_all command is 1.53x faster in a 100,000-entity scene: 3.17 ms versus 2.07 ms. Measurement was the median of five runs on an AMD Ryzen 9 9950X3D. 1.53x is a solid constant-factor improvement at everyday-use scale.
The other number is 132x. It comes from a new optional component attribute, #[component(summary_tick)], which stores a column-level change flag. The project reports seeing a 132x speedup in its own GPU mesh extraction code, at the cost of making mutation operations themselves more expensive.
| Optimization | Magnitude | Conditions |
|---|---|---|
| despawn_all batch despawn | 1.53x | 100k entities, median of five runs, Ryzen 9 9950X3D |
| summary_tick change flag | 132x | Project's own GPU mesh extraction code |
These two numbers must be read differently. The 132x comes from one specific workload (GPU mesh extraction), was reported by the project itself, and carries a stated cost (more expensive mutations). The 1.53x comes from a publicly reproducible hardware and scenario setup. All performance figures are self-reported; neither the announcement nor this article performed independent benchmarking.
Consolidation elsewhere in the release
Several other items point in the same direction: merging duplication into standards.
- Mesh shaders are now wired into Bevy's pipeline cache for advanced users, with use cases including meshlets generated by tools like meshoptimizer and procedural grass with dynamic level of detail. Mesh shaders do not support the web platform. A shader working group is being planned.
- For texture compression, the
CompressedImageSaverasset processor gained a backend based on thecttlibrary, compressing to BCn for desktop GPUs or ASTC for mobile GPUs with automatic mipmap generation. The previous Basis Universal behavior moved behind thecompressed_image_saver_universalfeature, which the announcement calls the best choice for cross-platform distribution including WebGPU. - The BSN scene system received readability-oriented syntax changes; one breaking change is that all scene references now require an
@prefix. BSN scene entities gained aReadyevent that fires after all child entities are spawned, filling the gap left by the old top-downAddevent, at which point children were not yet available. - UI and scheduling details: UI now supports
emandremsizing, with the default font size changing frompx(20)torem(1); panics in systems, commands, and observers are now converted to errors passed to a fallback error handler (still re-panicking by default); scheduling gained weak ordering viachain_weak, and schedule randomization to surface dependency-order bugs more easily; the Feathers UI toolkit added a color input, scrollable list views, and dropdown selects, with drag-scrubbing on number inputs. - All performance figures (1.53x, 132x) were measured by the project on its own hardware and workloads; no independent benchmarking exists.
- The GitHub release page body only links to the diff against v0.19.1; all feature descriptions come from the project's announcement.
- The announcement does not state how many existing projects and plugins are affected by the WESL migration or the
@prefix change. - Solari support for
PointLight,SpotLight, andRectLightis listed as "coming soon," with no date given.
The editor-tooling thread is also worth watching: if one control is missing from the editor toolchain, developers get stuck waiting there.