vulk_ext/vkx/
buffer.rs

1use super::*;
2
3#[derive(Clone, Copy, Debug)]
4pub struct BufferCreator(vk::BufferCreateInfo);
5
6impl BufferCreator {
7    #[must_use]
8    pub fn new(size: vk::DeviceSize, usage: impl Into<vk::BufferUsageFlags> + Copy) -> Self {
9        Self(vk::BufferCreateInfo {
10            s_type: vk::StructureType::BufferCreateInfo,
11            p_next: null(),
12            flags: vk::BufferCreateFlags::empty(),
13            size,
14            usage: usage.into() | vk::BufferUsageFlagBits::ShaderDeviceAddress,
15            sharing_mode: vk::SharingMode::Exclusive,
16            queue_family_index_count: 0,
17            p_queue_family_indices: null(),
18        })
19    }
20
21    pub unsafe fn create(self, device: &Device) -> Result<(vk::Buffer, vk::BufferCreateInfo)> {
22        let buffer_create_info = self.0;
23        let buffer = device.create_buffer(&buffer_create_info)?;
24        Ok((buffer, buffer_create_info))
25    }
26}
27
28pub trait BufferOps {
29    fn buffer_handle(&self) -> vk::Buffer;
30
31    fn create_info(&self) -> &vk::BufferCreateInfo;
32
33    fn memory(&self) -> &BufferAllocation;
34
35    fn memory_mut(&mut self) -> &mut BufferAllocation;
36
37    fn size(&self) -> vk::DeviceSize {
38        self.create_info().size
39    }
40}
41
42pub trait BufferResourceOps {
43    fn descriptor(&self) -> Descriptor;
44}
45
46/// [`BufferResource`] is meant to be used by a shader.
47#[derive(Debug)]
48pub struct BufferResource {
49    buffer: vk::Buffer,
50    buffer_create_info: vk::BufferCreateInfo,
51    buffer_allocation: BufferAllocation,
52    descriptor: Descriptor,
53}
54
55impl BufferResource {
56    pub unsafe fn create(
57        physical_device: &PhysicalDevice,
58        device: &Device,
59        buffer_creators: &[BufferCreator],
60        property_flags: impl Into<vk::MemoryPropertyFlags> + Copy,
61    ) -> Result<(Vec<Self>, BufferAllocations)> {
62        // Constants.
63        const UNIFORM_BUFFER: vk::BufferUsageFlagBits = vk::BufferUsageFlagBits::UniformBuffer;
64        const STORAGE_BUFFER: vk::BufferUsageFlagBits = vk::BufferUsageFlagBits::StorageBuffer;
65        const AS_BUFFER: vk::BufferUsageFlagBits =
66            vk::BufferUsageFlagBits::AccelerationStructureStorageKHR;
67
68        // Buffers.
69        let mut buffers = Vec::with_capacity(buffer_creators.len());
70        let mut buffer_create_infos = Vec::with_capacity(buffer_creators.len());
71        for &buffer_creator in buffer_creators {
72            let (buffer, buffer_create_info) = buffer_creator.create(device)?;
73            buffers.push(buffer);
74            buffer_create_infos.push(buffer_create_info);
75        }
76
77        // Buffer allocations.
78        let buffer_allocations = BufferAllocations::allocate(
79            physical_device,
80            device,
81            &buffers,
82            &buffer_create_infos,
83            property_flags,
84        )?;
85
86        // Descriptors.
87        let mut descriptors = Vec::with_capacity(buffer_creators.len());
88        for (buffer_allocation, buffer_create_info) in buffer_allocations
89            .allocations()
90            .iter()
91            .zip(&buffer_create_infos)
92        {
93            let usage = buffer_create_info.usage;
94            let descriptor = if usage.contains(UNIFORM_BUFFER) {
95                // assert buffer_allocation == buffer_create_info.size
96                Descriptor::create(
97                    physical_device,
98                    device,
99                    DescriptorCreateInfo::UniformBuffer {
100                        address: buffer_allocation.device_address(),
101                        range: buffer_create_info.size,
102                    },
103                )
104            } else if usage.contains(STORAGE_BUFFER) {
105                Descriptor::create(
106                    physical_device,
107                    device,
108                    DescriptorCreateInfo::StorageBuffer {
109                        address: buffer_allocation.device_address(),
110                        range: buffer_create_info.size,
111                    },
112                )
113            } else if usage.contains(AS_BUFFER) {
114                Descriptor::create(
115                    physical_device,
116                    device,
117                    DescriptorCreateInfo::AccelerationStructure(buffer_allocation.device_address()),
118                )
119            } else {
120                bail!(
121                    "Buffer resource must be \
122                    {UNIFORM_BUFFER} or \
123                    {STORAGE_BUFFER} or \
124                    {AS_BUFFER}, \
125                    got {usage}"
126                );
127            };
128            descriptors.push(descriptor);
129        }
130
131        // Resources.
132        let mut buffer_resources = Vec::with_capacity(buffer_creators.len());
133        for i in 0..buffer_creators.len() {
134            let buffer = buffers[i];
135            let buffer_create_info = buffer_create_infos[i];
136            let buffer_allocation = buffer_allocations.allocations()[i];
137            let descriptor = descriptors[i];
138            buffer_resources.push(Self {
139                buffer,
140                buffer_create_info,
141                buffer_allocation,
142                descriptor,
143            });
144        }
145        Ok((buffer_resources, buffer_allocations))
146    }
147
148    pub unsafe fn destroy(self, device: &Device) {
149        device.destroy_buffer(self.buffer);
150    }
151}
152
153impl BufferOps for BufferResource {
154    fn buffer_handle(&self) -> vk::Buffer {
155        self.buffer
156    }
157
158    fn create_info(&self) -> &vk::BufferCreateInfo {
159        &self.buffer_create_info
160    }
161
162    fn memory(&self) -> &BufferAllocation {
163        &self.buffer_allocation
164    }
165
166    fn memory_mut(&mut self) -> &mut BufferAllocation {
167        &mut self.buffer_allocation
168    }
169}
170
171impl BufferResourceOps for BufferResource {
172    fn descriptor(&self) -> Descriptor {
173        self.descriptor
174    }
175}
176
177/// [`BufferDedicatedResource`] trades off allocation efficiency for ease of use.
178#[derive(Debug)]
179pub struct BufferDedicatedResource {
180    buffer_resource: BufferResource,
181    buffer_allocations: BufferAllocations,
182}
183
184impl BufferDedicatedResource {
185    pub unsafe fn create(
186        physical_device: &PhysicalDevice,
187        device: &Device,
188        buffer_creator: BufferCreator,
189        property_flags: impl Into<vk::MemoryPropertyFlags> + Copy,
190    ) -> Result<Self> {
191        let (mut buffer_resources, buffer_allocations) =
192            BufferResource::create(physical_device, device, &[buffer_creator], property_flags)?;
193        let buffer_resource = buffer_resources.swap_remove(0);
194        Ok(Self {
195            buffer_resource,
196            buffer_allocations,
197        })
198    }
199
200    pub unsafe fn destroy(self, device: &Device) {
201        self.buffer_resource.destroy(device);
202        self.buffer_allocations.free(device);
203    }
204}
205
206impl BufferOps for BufferDedicatedResource {
207    fn buffer_handle(&self) -> vk::Buffer {
208        self.buffer_resource.buffer
209    }
210
211    fn create_info(&self) -> &vk::BufferCreateInfo {
212        &self.buffer_resource.buffer_create_info
213    }
214
215    fn memory(&self) -> &BufferAllocation {
216        &self.buffer_resource.buffer_allocation
217    }
218
219    fn memory_mut(&mut self) -> &mut BufferAllocation {
220        &mut self.buffer_resource.buffer_allocation
221    }
222}
223
224impl BufferResourceOps for BufferDedicatedResource {
225    fn descriptor(&self) -> Descriptor {
226        self.buffer_resource.descriptor
227    }
228}
229
230/// [`BufferDedicatedTransfer`] is intended to be used as `TransferSrc` or
231/// `TransferDst` and it must also be `HostVisible`.
232#[derive(Debug)]
233pub struct BufferDedicatedTransfer {
234    buffer: vk::Buffer,
235    buffer_create_info: vk::BufferCreateInfo,
236    buffer_allocations: BufferAllocations,
237    buffer_allocation: BufferAllocation,
238}
239
240impl BufferDedicatedTransfer {
241    pub unsafe fn create(
242        physical_device: &PhysicalDevice,
243        device: &Device,
244        buffer_creator: BufferCreator,
245        property_flags: impl Into<vk::MemoryPropertyFlags> + Copy,
246    ) -> Result<Self> {
247        // Validation.
248        const TRANSFER_SRC: vk::BufferUsageFlagBits = vk::BufferUsageFlagBits::TransferSrc;
249        const TRANSFER_DST: vk::BufferUsageFlagBits = vk::BufferUsageFlagBits::TransferDst;
250        const AS_BUILD_ONLY: vk::BufferUsageFlagBits =
251            vk::BufferUsageFlagBits::AccelerationStructureBuildInputReadOnlyKHR;
252
253        ensure!(buffer_creator.0.size > 0);
254        ensure!(
255            buffer_creator.0.usage.contains(TRANSFER_SRC)
256                || buffer_creator.0.usage.contains(TRANSFER_DST)
257                || buffer_creator.0.usage.contains(AS_BUILD_ONLY),
258            "got {}",
259            buffer_creator.0.usage
260        );
261        ensure!(property_flags
262            .into()
263            .contains(vk::MemoryPropertyFlagBits::HostVisible));
264
265        // Buffer.
266        let (buffer, buffer_create_info) = buffer_creator.create(device)?;
267
268        // Allocation.
269        let buffer_allocations = BufferAllocations::allocate(
270            physical_device,
271            device,
272            &[buffer],
273            &[buffer_create_info],
274            property_flags,
275        )?;
276        let buffer_allocation = buffer_allocations.allocations()[0];
277
278        Ok(Self {
279            buffer,
280            buffer_create_info,
281            buffer_allocations,
282            buffer_allocation,
283        })
284    }
285
286    pub unsafe fn destroy(self, device: &Device) {
287        device.destroy_buffer(self.buffer);
288        self.buffer_allocations.free(device);
289    }
290}
291
292impl BufferOps for BufferDedicatedTransfer {
293    fn buffer_handle(&self) -> vk::Buffer {
294        self.buffer
295    }
296
297    fn create_info(&self) -> &vk::BufferCreateInfo {
298        &self.buffer_create_info
299    }
300
301    fn memory(&self) -> &BufferAllocation {
302        &self.buffer_allocation
303    }
304
305    fn memory_mut(&mut self) -> &mut BufferAllocation {
306        &mut self.buffer_allocation
307    }
308}
309
310/// [`BufferShaderBindingTable`] is used in ray tracing extensions.
311#[derive(Debug)]
312pub struct BufferShaderBindingTable {
313    buffer: vk::Buffer,
314    buffer_create_info: vk::BufferCreateInfo,
315    buffer_allocation: BufferAllocation,
316}
317
318impl BufferShaderBindingTable {
319    pub unsafe fn create(
320        buffers: &[vk::Buffer],
321        buffer_create_infos: &[vk::BufferCreateInfo],
322        buffer_allocations: &[BufferAllocation],
323    ) -> Result<Vec<Self>> {
324        // Validation.
325        ensure!(!buffers.is_empty());
326        ensure!(buffers.len() == buffer_create_infos.len());
327        ensure!(buffers.len() == buffer_allocations.len());
328
329        // Buffer shader binding tables.
330        let mut buffer_sbts = vec![];
331        for i in 0..buffers.len() {
332            let buffer = buffers[i];
333            let buffer_create_info = buffer_create_infos[i];
334            let buffer_allocation = buffer_allocations[i];
335            buffer_sbts.push(Self {
336                buffer,
337                buffer_create_info,
338                buffer_allocation,
339            });
340        }
341        Ok(buffer_sbts)
342    }
343
344    pub unsafe fn destroy(self, device: &Device) {
345        device.destroy_buffer(self.buffer);
346    }
347}
348
349impl BufferOps for BufferShaderBindingTable {
350    fn buffer_handle(&self) -> vk::Buffer {
351        self.buffer
352    }
353
354    fn create_info(&self) -> &vk::BufferCreateInfo {
355        &self.buffer_create_info
356    }
357
358    fn memory(&self) -> &BufferAllocation {
359        &self.buffer_allocation
360    }
361
362    fn memory_mut(&mut self) -> &mut BufferAllocation {
363        &mut self.buffer_allocation
364    }
365}