demo_vk/graphics/vulkan/allocator/
owned_block.rs

1use {
2    crate::{
3        graphics::vulkan::{raii, Allocator, Block},
4        trace,
5    },
6    anyhow::{Context, Result},
7    ash::vk,
8    std::sync::Arc,
9};
10
11/// A block allocation that frees itself when dropped.
12#[derive(Debug)]
13pub struct OwnedBlock {
14    block: Block,
15    allocator: Arc<Allocator>,
16}
17
18impl OwnedBlock {
19    /// Creates an image and allocates memory to back it.
20    ///
21    /// The image is bound to the memory prior to return, so the caller can use
22    /// it right away.
23    pub fn allocate_image(
24        allocator: Arc<Allocator>,
25        image_create_info: &vk::ImageCreateInfo,
26        memory_property_flags: vk::MemoryPropertyFlags,
27    ) -> Result<(Self, raii::Image)> {
28        let image = raii::Image::new(
29            "Allocated Image",
30            allocator.logical_device.clone(),
31            image_create_info,
32        )
33        .with_context(trace!("Unable to create image!"))?;
34
35        let (requirements, dedicated) = {
36            let mut dedicated = vk::MemoryDedicatedRequirements::default();
37            let requirements = unsafe {
38                let mut out = vk::MemoryRequirements2::default()
39                    .push_next(&mut dedicated);
40
41                allocator.logical_device.get_image_memory_requirements2(
42                    &vk::ImageMemoryRequirementsInfo2 {
43                        image: image.raw,
44                        ..Default::default()
45                    },
46                    &mut out,
47                );
48
49                out.memory_requirements
50            };
51            (
52                requirements,
53                dedicated.prefers_dedicated_allocation == vk::TRUE
54                    || dedicated.requires_dedicated_allocation == vk::TRUE,
55            )
56        };
57
58        let block = allocator
59            .allocate_memory(
60                &requirements,
61                memory_property_flags,
62                vk::MemoryAllocateFlags::empty(),
63                dedicated,
64            )
65            .with_context(trace!("Unable to allocate memory for image!"))?;
66
67        unsafe {
68            allocator
69                .logical_device
70                .bind_image_memory(image.raw, block.memory(), block.offset())
71                .with_context(trace!("Unable to bind image memory!"))?;
72        };
73
74        Ok((Self { block, allocator }, image))
75    }
76
77    /// Creates a buffer and allocates memory to back it.
78    ///
79    /// The buffer is bound to the memory prior to return, so the caller can use
80    /// it right away.
81    pub fn allocate_buffer(
82        allocator: Arc<Allocator>,
83        buffer_create_info: &vk::BufferCreateInfo,
84        memory_property_flags: vk::MemoryPropertyFlags,
85    ) -> Result<(OwnedBlock, raii::Buffer)> {
86        let buffer = raii::Buffer::new(
87            "Allocated Buffer",
88            allocator.logical_device.clone(),
89            buffer_create_info,
90        )
91        .with_context(trace!("Unable to create buffer!"))?;
92
93        let (requirements, dedicated) = {
94            let mut dedicated = vk::MemoryDedicatedRequirements::default();
95            let requirements = unsafe {
96                let mut out = vk::MemoryRequirements2::default()
97                    .push_next(&mut dedicated);
98
99                allocator.logical_device.get_buffer_memory_requirements2(
100                    &vk::BufferMemoryRequirementsInfo2 {
101                        buffer: buffer.raw,
102                        ..Default::default()
103                    },
104                    &mut out,
105                );
106
107                out.memory_requirements
108            };
109            (
110                requirements,
111                dedicated.prefers_dedicated_allocation == vk::TRUE
112                    || dedicated.requires_dedicated_allocation == vk::TRUE,
113            )
114        };
115
116        let memory_allocate_flags = if buffer_create_info
117            .usage
118            .contains(vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS)
119        {
120            vk::MemoryAllocateFlags::DEVICE_ADDRESS
121        } else {
122            vk::MemoryAllocateFlags::empty()
123        };
124
125        let block = allocator
126            .allocate_memory(
127                &requirements,
128                memory_property_flags,
129                memory_allocate_flags,
130                dedicated,
131            )
132            .with_context(trace!("Unable to allocate memory for buffer!"))?;
133
134        unsafe {
135            allocator
136                .logical_device
137                .bind_buffer_memory(buffer.raw, block.memory(), block.offset())
138                .with_context(trace!("Unable to bind buffer to memory!"))?;
139        };
140
141        Ok((Self { block, allocator }, buffer))
142    }
143}
144
145impl std::ops::Deref for OwnedBlock {
146    type Target = Block;
147
148    fn deref(&self) -> &Self::Target {
149        &self.block
150    }
151}
152
153impl Drop for OwnedBlock {
154    fn drop(&mut self) {
155        self.allocator.free(&self.block);
156    }
157}