1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use crate::render_features::registry::MAX_RENDER_FEATURE_COUNT;
use crate::render_features::render_features_prelude::*;

/// Read documentation on `SubmitPacketData`.
pub struct ViewSubmitPacket<SubmitPacketDataT: SubmitPacketData> {
    view: RenderView,
    view_frame_index: ViewFrameIndex,

    pub(crate) per_view_submit_data: AtomicOnceCell<SubmitPacketDataT::PerViewSubmitData>,
    pub(crate) render_object_instances_submit_data:
        AtomicOnceCellArray<SubmitPacketDataT::RenderObjectInstancePerViewSubmitData>,

    submit_node_blocks: Vec<SubmitNodeBlock<SubmitPacketDataT>>,
    submit_node_phases: [Option<u8>; MAX_RENDER_FEATURE_COUNT as usize],
}

impl<SubmitPacketDataT: 'static + Send + Sync + SubmitPacketData>
    ViewSubmitPacket<SubmitPacketDataT>
{
    pub fn from_view_packet<RenderPhaseT: RenderPhase>(
        view_packet: &dyn RenderFeatureViewPacket,
        num_submit_nodes: Option<usize>,
    ) -> Self {
        let view_packet_size = ViewPacketSize::size_of(view_packet);
        let submit_node_blocks = vec![SubmitNodeBlock::with_capacity::<RenderPhaseT>(
            view_packet.view(),
            num_submit_nodes.unwrap_or(view_packet_size.num_render_object_instances),
        )];

        ViewSubmitPacket::new(
            submit_node_blocks,
            &view_packet_size,
            view_packet.view_frame_index(),
        )
    }

    pub fn new(
        submit_node_blocks: Vec<SubmitNodeBlock<SubmitPacketDataT>>,
        view_packet_size: &ViewPacketSize,
        view_frame_index: ViewFrameIndex,
    ) -> Self {
        assert!((u8::MAX as u32) > MAX_RENDER_FEATURE_COUNT);
        let mut submit_node_phases = [None; MAX_RENDER_FEATURE_COUNT as usize];
        for (index, submit_node_block) in submit_node_blocks.iter().enumerate() {
            submit_node_phases[submit_node_block.render_phase() as usize] = Some(index as u8);
        }

        Self {
            view: view_packet_size.view.clone(),
            view_frame_index,
            per_view_submit_data: AtomicOnceCell::new(),
            render_object_instances_submit_data: AtomicOnceCellArray::with_capacity(
                view_packet_size.num_render_object_instances,
            ),
            submit_node_phases,
            submit_node_blocks,
        }
    }

    pub fn render_object_instances_submit_data(
        &self
    ) -> &AtomicOnceCellArray<SubmitPacketDataT::RenderObjectInstancePerViewSubmitData> {
        &self.render_object_instances_submit_data
    }

    pub fn view_frame_index(&self) -> ViewFrameIndex {
        self.view_frame_index
    }

    pub fn per_view_submit_data(&self) -> &AtomicOnceCell<SubmitPacketDataT::PerViewSubmitData> {
        &self.per_view_submit_data
    }

    pub fn push_submit_node<RenderPhaseT: RenderPhase>(
        &self,
        data: SubmitPacketDataT::SubmitNodeData,
        sort_key: SubmitNodeSortKey,
        distance: f32,
    ) -> SubmitNodeId {
        self.push_submit_node_into_render_phase(
            RenderPhaseT::render_phase_index(),
            data,
            sort_key,
            distance,
        )
    }

    pub fn push_submit_node_into_render_phase(
        &self,
        render_phase: RenderPhaseIndex,
        data: SubmitPacketDataT::SubmitNodeData,
        sort_key: SubmitNodeSortKey,
        distance: f32,
    ) -> SubmitNodeId {
        self.submit_node_block(render_phase)
            .push_submit_node(data, sort_key, distance)
    }

    fn submit_node_block(
        &self,
        render_phase: RenderPhaseIndex,
    ) -> &SubmitNodeBlock<SubmitPacketDataT> {
        self.submit_node_phases[render_phase as usize]
            .map(|index| &self.submit_node_blocks[index as usize])
            .unwrap_or_else(|| {
                panic!(
                    "{} does not contain RenderPhase {}",
                    std::any::type_name::<ViewSubmitPacket<SubmitPacketDataT>>(),
                    render_phase
                )
            })
    }

    pub fn get_submit_node_data<RenderPhaseT: RenderPhase>(
        &self,
        index: SubmitNodeId,
    ) -> &SubmitPacketDataT::SubmitNodeData {
        self.get_submit_node_data_from_render_phase(RenderPhaseT::render_phase_index(), index)
    }

    pub fn get_submit_node_data_from_render_phase(
        &self,
        render_phase: RenderPhaseIndex,
        index: SubmitNodeId,
    ) -> &SubmitPacketDataT::SubmitNodeData {
        &self
            .submit_node_block(render_phase)
            .get_submit_node_data(index)
            .data
    }
}

impl<SubmitPacketDataT: 'static + Send + Sync + SubmitPacketData> RenderFeatureViewSubmitPacket
    for ViewSubmitPacket<SubmitPacketDataT>
{
    fn view(&self) -> &RenderView {
        &self.view
    }

    fn num_submit_nodes(
        &self,
        render_phase: RenderPhaseIndex,
    ) -> usize {
        self.submit_node_phases[render_phase as usize]
            .map(|index| self.submit_node_blocks[index as usize].num_submit_nodes())
            .unwrap_or(0)
    }

    fn get_submit_node_block(
        &self,
        render_phase: RenderPhaseIndex,
    ) -> Option<&dyn RenderFeatureSubmitNodeBlock> {
        self.submit_node_phases[render_phase as usize].map(|index| {
            let submit_node_block: &dyn RenderFeatureSubmitNodeBlock =
                &self.submit_node_blocks[index as usize];
            submit_node_block
        })
    }
}