Skip to main content

ursus_core/render/resource/
layout_tracker.rs

1use crate::render::resource::desc::ResourceHandle;
2use crate::render::resource::make_barrier;
3use crate::render::resource::pool::ResourcePool;
4use ash::vk;
5use std::collections::HashMap;
6
7pub struct LayoutTracker {
8    layouts: HashMap<ResourceHandle, vk::ImageLayout>,
9    scratch: Vec<vk::ImageMemoryBarrier2<'static>>,
10}
11
12impl LayoutTracker {
13    pub fn new() -> Self {
14        Self { layouts: HashMap::new(), scratch: Vec::new() }
15    }
16
17    pub fn current(&self, handle: ResourceHandle) -> vk::ImageLayout {
18        self.layouts.get(&handle).copied().unwrap_or(vk::ImageLayout::UNDEFINED)
19    }
20
21    pub fn set(&mut self, handle: ResourceHandle, layout: vk::ImageLayout) {
22        self.layouts.insert(handle, layout);
23    }
24
25    /// Computes the list of required barriers for transitioning to the new layouts
26    /// and records the new state in the tracker. Does not record GPU commands itself -
27    /// the caller must pass the returned slice to `cmd_pipeline_barrier2`
28    /// (see `RenderGraph::execute`), or ignore it if it decides to skip the transition.
29    pub fn plan_transition(
30        &mut self,
31        pool: &ResourcePool,
32        transitions: impl IntoIterator<Item = (ResourceHandle, vk::ImageLayout)>,
33    ) -> &[vk::ImageMemoryBarrier2<'static>] {
34        self.scratch.clear();
35        for (handle, new_layout) in transitions {
36            let old_layout = self.current(handle);
37            if old_layout == new_layout {
38                continue;
39            }
40            let img = pool.image(handle);
41            self.scratch.push(make_barrier(img.image, img.kind, old_layout, new_layout));
42            self.layouts.insert(handle, new_layout);
43        }
44        &self.scratch
45    }
46
47    pub fn invalidate(&mut self, handles: &[ResourceHandle]) {
48        for h in handles {
49            self.layouts.insert(*h, vk::ImageLayout::UNDEFINED);
50        }
51    }
52}
53
54impl Default for LayoutTracker {
55    fn default() -> Self {
56        Self::new()
57    }
58}