From 07f7a40f4e7c7e1f054e285bb15c3fec48ac8608 Mon Sep 17 00:00:00 2001 From: JohnM <234386938+treuenten@users.noreply.github.com> Date: Mon, 12 Oct 2026 17:43:52 +0800 Subject: [PATCH] Send dirty static-model lighting tiles to the GPU as tile writes update_smodel_lighting wrote each dirty static-model lighting tile into the model lighting atlas through a tracked Assets::get_mut. Every frame with a dirty tile therefore marked the whole atlas modified, so Bevy extracted all of it again and rewrote the whole texture on the GPU, up to 1 MiB, for a few 256-byte tiles. The tile is now written through an untracked borrow and queued in ModelLightingAtlasTileWrites, as the moving-model lighting cache already does for the same atlas. Co-Authored-By: Claude Opus 5.5 --- .../render_frontend/src/prepare/scene/smodel_lighting.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/render_frontend/src/prepare/scene/smodel_lighting.rs b/crates/render_frontend/src/prepare/scene/smodel_lighting.rs index df1f949..8849833 100644 --- a/crates/render_frontend/src/prepare/scene/smodel_lighting.rs +++ b/crates/render_frontend/src/prepare/scene/smodel_lighting.rs @@ -10,6 +10,7 @@ use crate::prepare::scene::cull::smodel_cull_dist_skips_slot; use crate::prepare::scene::model_lighting_atlas::{ WorldModelLightingAtlas, model_lighting_atlas_write_tile, }; +use crate::prepare::scene::model_lighting_cache::ModelLightingAtlasTileWrites; use crate::prepare::scene::smodel_geom_cache::LodRampDvar; use crate::prepare::scene::view_parms::PreparedSceneView; use crate::prepare::scene::world::{WorldScene, WorldSmodelLightingSample}; @@ -184,6 +185,7 @@ pub(crate) fn update_smodel_lighting( atlas: Option>, scene: Res, mut images: ResMut>, + mut tile_writes: ResMut, prepared: Res, lock_pvs: Res, lod_ramp: Res, @@ -339,7 +341,8 @@ pub(crate) fn update_smodel_lighting( if !dirty_slots.is_empty() { let dims = atlas.dims; let atlas_handle = atlas.image.clone(); - if let Some(mut atlas) = images.get_mut(&atlas_handle) { + // Untracked: only `tile_writes` carries the tiles to the GPU. + if let Some(atlas) = images.get_mut_untracked(&atlas_handle) { for &(slot, handle) in &dirty_slots { let Some(Some(tile)) = lighting.tiles.get(slot) else { continue; @@ -347,7 +350,9 @@ pub(crate) fn update_smodel_lighting( let Some(entry) = ModelLightingTileIndex::from_handle(handle) else { continue; }; - if !model_lighting_atlas_write_tile(&mut atlas, dims, entry, tile) { + if model_lighting_atlas_write_tile(atlas, dims, entry, tile) { + tile_writes.push(atlas_handle.id(), entry, tile); + } else { diag::error!( World, "smodel lighting: tile for slot {slot} handle {handle} refused by atlas write"