Textures staged with Stage::set_images after a render are silently not applied
Repro
- Create a
Stage, primitives, and a Material; attach the material and render once (any frame).
- Call
Stage::set_images([...]) to stage textures in the atlas.
material.set_albedo_texture(&entries[0]) and render again.
Result: the texture is silently not sampled — the material falls back to the
albedo factor. Renders for different textures are byte-identical (0 pixels differ).
Isolated trigger
Rendering before set_images is the trigger. Creating the material (and
attaching it to primitives) before set_images is harmless — the bug only
appears when a render happens between stage creation and set_images. Calling
set_images before the first render works fine.
Experiment (two cubes sharing one material, 512×512):
| order |
result |
render → set_images → texture → render |
flat white cubes; renders for sandstone/dirt byte-identical (6,329 bytes both) |
set_images → render → texture → render |
textures render: 193KB/159KB PNGs, 19,077 unique colors vs 23 for the flat render |
Suspected area
Stage::commit (crates/renderling/src/stage/cpu.rs, the
materials_atlas_texture_was_recreated → primitive_bind_group.invalidate()
path) apparently does not fully propagate once a render has already cached the
renderlet bindgroup — the atlas texture view and/or materials slab buffer bound
at first render persist, so the shader's texture lookup fails and silently
falls back to the albedo factor.
Suggested fix / acceptance
- Minimal test in the renderling crate: render →
set_images → set texture →
render, assert the texture is visible (unique-color count or img_diff)
- Ideally also make the silent fallback loud (log/assert) when a material
references a texture that can't be sampled
Context
Found while writing the materials manual chapter (crates/examples/src/material.rs
in the docs-missing-manual-buildout worktree; the example currently works
around it by staging all images up front, which the set_images docs recommend
anyway).
Textures staged with
Stage::set_imagesafter a render are silently not appliedRepro
Stage, primitives, and aMaterial; attach the material and render once (any frame).Stage::set_images([...])to stage textures in the atlas.material.set_albedo_texture(&entries[0])and render again.Result: the texture is silently not sampled — the material falls back to the
albedo factor. Renders for different textures are byte-identical (0 pixels differ).
Isolated trigger
Rendering before
set_imagesis the trigger. Creating the material (andattaching it to primitives) before
set_imagesis harmless — the bug onlyappears when a render happens between stage creation and
set_images. Callingset_imagesbefore the first render works fine.Experiment (two cubes sharing one material, 512×512):
set_images→ texture → renderset_images→ render → texture → renderSuspected area
Stage::commit(crates/renderling/src/stage/cpu.rs, thematerials_atlas_texture_was_recreated→primitive_bind_group.invalidate()path) apparently does not fully propagate once a render has already cached the
renderlet bindgroup — the atlas texture view and/or materials slab buffer bound
at first render persist, so the shader's texture lookup fails and silently
falls back to the albedo factor.
Suggested fix / acceptance
set_images→ set texture →render, assert the texture is visible (unique-color count or
img_diff)references a texture that can't be sampled
Context
Found while writing the materials manual chapter (
crates/examples/src/material.rsin the
docs-missing-manual-buildoutworktree; the example currently worksaround it by staging all images up front, which the
set_imagesdocs recommendanyway).