From bc7416aa228566d1835ec0f2946f995e4620890f Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Sat, 15 Mar 2025 15:16:32 +0100 Subject: [PATCH] Use 4-byte LightmapSlabIndex for batching instead of 16-byte AssetId (#18326) Less data accessed and compared gives better batching performance. # Objective - Use a smaller id to represent the lightmap in batch data to enable a faster implementation of draw streams. - Improve batching performance for 3D sorted render phases. ## Solution - 3D batching can use `LightmapSlabIndex` (a `NonMaxU32` which is 4 bytes) instead of the lightmap `AssetId` (an enum where the largest variant is a 16-byte UUID) to discern the ability to batch. ## Testing Tested main (yellow) vs this PR (red) on an M4 Max using the `many_cubes` example with `WGPU_SETTINGS_PRIO=webgl2` to avoid GPU-preprocessing, and modifying the materials in `many_cubes` to have `AlphaMode::Blend` so that they would rely on the less efficient sorted render phase batching. Screenshot_2025-03-15_at_12 17 21 A 44.75us or 7.5% reduction in median execution time of the batch and prepare sorted render phase system for the `Transparent3d` phase (handling 160k cubes). --- ## Migration Guide - Changed: `RenderLightmap::new()` no longer takes an `AssetId` argument for the asset id of the lightmap image. --- crates/bevy_pbr/src/lightmap/mod.rs | 6 ------ crates/bevy_pbr/src/render/mesh.rs | 6 +++--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/bevy_pbr/src/lightmap/mod.rs b/crates/bevy_pbr/src/lightmap/mod.rs index 348ec49b69..80df8c73ae 100644 --- a/crates/bevy_pbr/src/lightmap/mod.rs +++ b/crates/bevy_pbr/src/lightmap/mod.rs @@ -116,9 +116,6 @@ pub struct Lightmap { /// There is one of these per visible lightmapped mesh instance. #[derive(Debug)] pub(crate) struct RenderLightmap { - /// The ID of the lightmap texture. - pub(crate) image: AssetId, - /// The rectangle within the lightmap texture that the UVs are relative to. /// /// The top left coordinate is the `min` part of the rect, and the bottom @@ -245,7 +242,6 @@ fn extract_lightmaps( render_lightmaps.render_lightmaps.insert( entity.into(), RenderLightmap::new( - lightmap.image.id(), lightmap.uv_rect, slab_index, slot_index, @@ -305,14 +301,12 @@ impl RenderLightmap { /// Creates a new lightmap from a texture, a UV rect, and a slab and slot /// index pair. fn new( - image: AssetId, uv_rect: Rect, slab_index: LightmapSlabIndex, slot_index: LightmapSlotIndex, bicubic_sampling: bool, ) -> Self { Self { - image, uv_rect, slab_index, slot_index, diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 433df17c54..a66f9233fa 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -1905,7 +1905,7 @@ impl GetBatchData for MeshPipeline { type CompareData = ( MaterialBindGroupIndex, AssetId, - Option>, + Option, ); type BufferData = MeshUniform; @@ -1946,7 +1946,7 @@ impl GetBatchData for MeshPipeline { mesh_instance.should_batch().then_some(( material_bind_group_index.group, mesh_instance.mesh_asset_id, - maybe_lightmap.map(|lightmap| lightmap.image), + maybe_lightmap.map(|lightmap| lightmap.slab_index), )), )) } @@ -1976,7 +1976,7 @@ impl GetFullBatchData for MeshPipeline { mesh_instance.should_batch().then_some(( mesh_instance.material_bindings_index.group, mesh_instance.mesh_asset_id, - maybe_lightmap.map(|lightmap| lightmap.image), + maybe_lightmap.map(|lightmap| lightmap.slab_index), )), )) }