MCPcopy Create free account
hub / github.com/Bloom-Engine/engine / capture_pending_mesh_cards

Method capture_pending_mesh_cards

native/shared/src/renderer/mod.rs:6640–6839  ·  view source on GitHub ↗

Ticket 013 — rasterise every pending mesh card into its assigned atlas slot. Called once per frame before the HW probe trace samples the atlas. Drains `scene.pending_card_captures`; subsequent frames with no new meshes are free.

(
        &mut self,
        scene: &mut crate::scene::SceneGraph,
        encoder: &mut wgpu::CommandEncoder,
    )

Source from the content-addressed store, hash-verified

6638 /// trace samples the atlas. Drains `scene.pending_card_captures`;
6639 /// subsequent frames with no new meshes are free.
6640 fn capture_pending_mesh_cards(
6641 &mut self,
6642 scene: &mut crate::scene::SceneGraph,
6643 encoder: &mut wgpu::CommandEncoder,
6644 ) {
6645 if scene.pending_card_captures.is_empty() {
6646 return;
6647 }
6648 // Rate-limit: at 6 axes per mesh one encoder fills up after a
6649 // few hundred render passes (observed hang on Sponza's 405 ×
6650 // 6 = 2430-pass batch). Drain in chunks and let subsequent
6651 // frames continue the work — Sponza finishes in a few frames.
6652 const CAPTURE_MAX_PER_FRAME: usize = 20;
6653 let take = scene.pending_card_captures.len().min(CAPTURE_MAX_PER_FRAME);
6654 let pending: Vec<f64> = scene.pending_card_captures.drain(..take).collect();
6655
6656 // Pre-compute per-slot world-space normals for the whole batch.
6657 // `slot_meta` is a Vec<[f32;4]> where entry `first_slot + axis`
6658 // carries the card face's world-space normal (xyz) + unused w.
6659 // Uploaded in one `queue.write_buffer` after the capture loop
6660 // so the card-lighting compute pass sees the populated slots.
6661 let mut slot_meta_updates: Vec<(u32, CardSlotMetaCpu)> = Vec::new();
6662
6663 for handle in pending {
6664 let (first_slot, bmin, bmax, transform, has_tex, bc, tex_idx, has_em, em_factor, em_idx, vb_ptr, ib_ptr, index_count) = {
6665 let Some(node) = scene.nodes.get(handle) else { continue; };
6666 let Some(first_slot) = node.card_first_slot else { continue; };
6667 if first_slot + CARD_AXES_PER_MESH > CARD_MAX_SLOTS {
6668 continue;
6669 }
6670 let Some(vb) = node.gpu_vb.as_ref() else { continue; };
6671 let Some(ib) = node.gpu_ib.as_ref() else { continue; };
6672 let has_tex = node.material.texture_idx != 0;
6673 let em_idx = node.material.emissive_texture_idx;
6674 let has_em = em_idx != 0;
6675 (
6676 first_slot,
6677 node.bounds_min,
6678 node.bounds_max,
6679 node.transform,
6680 has_tex,
6681 node.material.color,
6682 node.material.texture_idx,
6683 has_em,
6684 node.material.emissive,
6685 em_idx,
6686 vb.clone(),
6687 ib.clone(),
6688 node.gpu_index_count,
6689 )
6690 };
6691 if index_count == 0 {
6692 continue;
6693 }
6694
6695 // Card textures + sampler binding stay the same across all
6696 // 6 axes, so build the bind groups once per mesh.
6697 let tex_view = if has_tex && (tex_idx as usize) < self.textures.len() {

Callers 1

end_frame_with_sceneMethod · 0.80

Calls 9

build_card_ortho_v2Function · 0.85
cloneMethod · 0.80
set_viewportMethod · 0.80
set_scissor_rectMethod · 0.80
sliceMethod · 0.80
getMethod · 0.45
set_vertex_bufferMethod · 0.45
set_index_bufferMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected