ursus_core/vulkan/core/
memory.rs1use crate::vulkan::core::DeviceContext;
2use ash::vk;
3
4pub struct AllocatedImage {
5 pub image: vk::Image,
6 pub view: vk::ImageView,
7 pub memory: vk::DeviceMemory,
8}
9
10pub struct ImageDesc {
11 pub format: vk::Format,
12 pub width: u32,
13 pub height: u32,
14 pub usage: vk::ImageUsageFlags,
15 pub aspect_mask: vk::ImageAspectFlags,
16 pub mip_levels: u32,
17}
18
19impl ImageDesc {
20 pub fn color(format: vk::Format, width: u32, height: u32, usage: vk::ImageUsageFlags) -> Self {
21 Self { format, width, height, usage, aspect_mask: vk::ImageAspectFlags::COLOR, mip_levels: 1 }
22 }
23
24 pub fn depth(format: vk::Format, width: u32, height: u32, usage: vk::ImageUsageFlags) -> Self {
25 Self { format, width, height, usage, aspect_mask: vk::ImageAspectFlags::DEPTH, mip_levels: 1 }
26 }
27}
28
29pub fn alloc_image(ctx: DeviceContext, desc: &ImageDesc) -> anyhow::Result<AllocatedImage> {
30 let image_info = vk::ImageCreateInfo::default()
31 .image_type(vk::ImageType::TYPE_2D)
32 .format(desc.format)
33 .extent(vk::Extent3D { width: desc.width, height: desc.height, depth: 1 })
34 .mip_levels(desc.mip_levels)
35 .array_layers(1)
36 .samples(vk::SampleCountFlags::TYPE_1)
37 .tiling(vk::ImageTiling::OPTIMAL)
38 .usage(desc.usage)
39 .sharing_mode(vk::SharingMode::EXCLUSIVE)
40 .initial_layout(vk::ImageLayout::UNDEFINED);
41
42 let image = unsafe { ctx.device.create_image(&image_info, None)? };
43 let req = unsafe { ctx.device.get_image_memory_requirements(image) };
44
45 let mem_type = find_memory_type(
46 ctx.instance,
47 ctx.physical_device,
48 req.memory_type_bits,
49 vk::MemoryPropertyFlags::DEVICE_LOCAL,
50 )?;
51
52 let memory = unsafe {
53 ctx.device.allocate_memory(
54 &vk::MemoryAllocateInfo::default().allocation_size(req.size).memory_type_index(mem_type),
55 None,
56 )?
57 };
58 unsafe { ctx.device.bind_image_memory(image, memory, 0)? };
59
60 let view = unsafe {
61 ctx.device.create_image_view(
62 &vk::ImageViewCreateInfo::default()
63 .image(image)
64 .view_type(vk::ImageViewType::TYPE_2D)
65 .format(desc.format)
66 .subresource_range(vk::ImageSubresourceRange {
67 aspect_mask: desc.aspect_mask,
68 base_mip_level: 0,
69 level_count: desc.mip_levels,
70 base_array_layer: 0,
71 layer_count: 1,
72 }),
73 None,
74 )?
75 };
76
77 Ok(AllocatedImage { image, view, memory })
78}
79
80pub fn find_memory_type(
81 instance: &ash::Instance,
82 physical_device: vk::PhysicalDevice,
83 type_filter: u32,
84 required: vk::MemoryPropertyFlags,
85) -> anyhow::Result<u32> {
86 let mem_props = unsafe { instance.get_physical_device_memory_properties(physical_device) };
87 for i in 0..mem_props.memory_type_count {
88 if (type_filter & (1 << i)) != 0 && mem_props.memory_types[i as usize].property_flags.contains(required) {
89 return Ok(i);
90 }
91 }
92
93 anyhow::bail!("Не найден тип памяти с флагами {:?}, type_filter={:#034b}", required, type_filter)
94}
95
96pub fn alloc_buffer(
97 ctx: DeviceContext,
98 size: vk::DeviceSize,
99 usage: vk::BufferUsageFlags,
100 props: vk::MemoryPropertyFlags,
101) -> anyhow::Result<(vk::Buffer, vk::DeviceMemory)> {
102 let buf_info = vk::BufferCreateInfo::default().size(size).usage(usage).sharing_mode(vk::SharingMode::EXCLUSIVE);
103 let buf = unsafe { ctx.device.create_buffer(&buf_info, None)? };
104 let req = unsafe { ctx.device.get_buffer_memory_requirements(buf) };
105 let alloc = vk::MemoryAllocateInfo::default().allocation_size(req.size).memory_type_index(find_memory_type(
106 ctx.instance,
107 ctx.physical_device,
108 req.memory_type_bits,
109 props,
110 )?);
111 let mem = unsafe { ctx.device.allocate_memory(&alloc, None)? };
112 unsafe { ctx.device.bind_buffer_memory(buf, mem, 0)? };
113 Ok((buf, mem))
114}
115
116pub unsafe fn destroy_image_resources(
124 device: &ash::Device,
125 image: vk::Image,
126 view: vk::ImageView,
127 memory: vk::DeviceMemory,
128) {
129 device.destroy_image_view(view, None);
130 device.destroy_image(image, None);
131 device.free_memory(memory, None);
132}