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
use crate::render_features::render_features_prelude::*;
use crate::visibility::{ViewFrustumId, VisibilityConfig};
use crate::RenderResources;
use fnv::{FnvHashMap, FnvHashSet};
use rafx_base::owned_pool::{OwnedPool, Pooled};

pub type ExtractResources<'extract> = rafx_base::resource_ref_map::ResourceRefMap<'extract>;
pub type RenderObjectInstanceObjectIds = FnvHashSet<RenderObjectInstance>;

#[derive(Clone)]
pub struct ViewPacketSize {
    pub view: RenderView,
    pub num_render_object_instances: usize,
    pub num_volumes: usize,
}

impl ViewPacketSize {
    pub fn size_of(view_packet: &dyn RenderFeatureViewPacket) -> Self {
        Self {
            view: view_packet.view().clone(),
            num_render_object_instances: view_packet.num_render_object_instances(),
            num_volumes: 0,
        }
    }
}

#[derive(Default, Clone)]
pub struct FramePacketSize {
    pub num_render_object_instances: usize,
    pub view_packet_sizes: Vec<ViewPacketSize>,
}

#[derive(Default, Clone)]
pub struct FramePacketMetadata {
    pub feature_index: RenderFeatureIndex,
    pub is_relevant: bool,
    pub frame_packet_size: FramePacketSize,
}

pub type VisibilityVecs = Vec<Vec<RenderObjectInstance>>;

pub struct RenderJobExtractAllocationContext {
    pub frame_packet_metadata: Vec<TrustCell<FramePacketMetadata>>,
    pub frame_packets: Vec<TrustCell<Option<Box<dyn RenderFeatureFramePacket>>>>,
    pub render_object_instances: Vec<TrustCell<RenderObjectInstanceObjectIds>>,
    visibility_vecs: Mutex<FnvHashMap<ViewFrustumId, OwnedPool<VisibilityVecs>>>,
    num_features: usize,
}

impl RenderJobExtractAllocationContext {
    pub fn new(num_features: usize) -> Self {
        let mut allocation_context = Self {
            frame_packet_metadata: Vec::with_capacity(num_features),
            frame_packets: Vec::with_capacity(num_features),
            render_object_instances: Vec::with_capacity(num_features),
            visibility_vecs: Default::default(),
            num_features,
        };

        allocation_context.clear();
        allocation_context
    }

    pub fn clear(&mut self) {
        self.frame_packet_metadata.clear();
        self.frame_packets.clear();
        self.render_object_instances.clear();

        for _ in 0..self.num_features {
            self.frame_packet_metadata
                .push(TrustCell::new(FramePacketMetadata::default()));
            self.frame_packets.push(TrustCell::new(None));
            self.render_object_instances
                .push(TrustCell::new(RenderObjectInstanceObjectIds::default()));
        }

        self.visibility_vecs.lock().clear();
    }

    pub fn query_visibility_vecs(
        &self,
        view: &RenderView,
    ) -> Pooled<VisibilityVecs> {
        let id = view.view_frustum().view_frustum_id();

        let mut visibility_vecs = self.visibility_vecs.lock();
        let pool = visibility_vecs.entry(id).or_insert_with(|| {
            OwnedPool::with_capacity(
                1,
                || vec![Vec::default(); RenderRegistry::registered_feature_count() as usize],
                |val| {
                    for feature in val.iter_mut() {
                        feature.clear();
                    }
                },
            )
        });

        pool.try_recv();
        pool.borrow()
    }
}

/// Holds references to resources valid for the entirety of the `extract` step as
/// represented by the `'extract` lifetime. `RenderFeatureExtractJob`s should cache
/// any resources needed from the `RenderJobExtractContext` during their `new` function.
#[derive(Clone)]
pub struct RenderJobExtractContext<'extract> {
    pub allocation_context: &'extract RenderJobExtractAllocationContext,
    pub extract_resources: &'extract ExtractResources<'extract>,
    pub render_resources: &'extract RenderResources,
    pub visibility_config: &'extract VisibilityConfig,
}

impl<'extract> RenderJobExtractContext<'extract> {
    pub fn new(
        allocation_context: &'extract RenderJobExtractAllocationContext,
        extract_resources: &'extract ExtractResources<'extract>,
        render_resources: &'extract RenderResources,
        visibility_config: &'extract VisibilityConfig,
    ) -> Self {
        RenderJobExtractContext {
            allocation_context,
            extract_resources,
            render_resources,
            visibility_config,
        }
    }
}