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
//! GPU buffer allocation and data streaming.
use crate::Error;
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BufferId(pub u32);
pub struct Buffer {
pub(crate) hal_buffer: Option<lgpu_hal::vulkan::VulkanBuffer>,
pub(crate) vulkan_device: Arc<lgpu_hal::vulkan::VulkanDevice>,
pub size: u64,
pub id: Option<BufferId>,
}
impl std::fmt::Debug for Buffer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Buffer")
.field("size", &self.size)
.field("id", &self.id)
.finish()
}
}
impl Buffer {
/// Returns the optional bindless buffer identifier.
pub fn id(&self) -> Option<BufferId> {
self.id
}
/// Writes data to the beginning of the buffer.
///
/// # Example
/// ```no_run
/// use lgpu::Buffer;
///
/// # fn example(buffer: &Buffer) -> Result<(), lgpu::Error> {
/// buffer.write(&[1, 2, 3, 4])?;
/// # Ok(())
/// # }
/// ```
pub fn write(&self, data: &[u8]) -> Result<(), Error> {
self.write_at(0, data)
}
/// Writes data into the buffer at a specific byte offset.
///
/// # Example
/// ```no_run
/// use lgpu::Buffer;
///
/// # fn example(buffer: &Buffer) -> Result<(), lgpu::Error> {
/// buffer.write_at(16, &[10, 20, 30, 40])?;
/// # Ok(())
/// # }
/// ```
pub fn write_at(&self, offset: u64, data: &[u8]) -> Result<(), Error> {
let raw_buf = self.hal_buffer.as_ref().ok_or_else(|| {
Error::Hal(lgpu_hal::HalError::InvalidParameter(
"Buffer hal resource is missing or destroyed".to_string(),
))
})?;
self.vulkan_device.write_buffer(raw_buf, offset, data)?;
Ok(())
}
/// Reads data from the beginning of the buffer into a destination slice.
///
/// # Example
/// ```no_run
/// use lgpu::Buffer;
///
/// # fn example(buffer: &Buffer) -> Result<(), lgpu::Error> {
/// let mut output = [0u8; 16];
/// buffer.read(&mut output)?;
/// # Ok(())
/// # }
/// ```
pub fn read(&self, data: &mut [u8]) -> Result<(), Error> {
self.read_at(0, data)
}
/// Reads data from the buffer at a specific byte offset into a destination slice.
///
/// # Example
/// ```no_run
/// use lgpu::Buffer;
///
/// # fn example(buffer: &Buffer) -> Result<(), lgpu::Error> {
/// let mut output = [0u8; 8];
/// buffer.read_at(8, &mut output)?;
/// # Ok(())
/// # }
/// ```
pub fn read_at(&self, offset: u64, data: &mut [u8]) -> Result<(), Error> {
let raw_buf = self.hal_buffer.as_ref().ok_or_else(|| {
Error::Hal(lgpu_hal::HalError::InvalidParameter(
"Buffer hal resource is missing or destroyed".to_string(),
))
})?;
self.vulkan_device.read_buffer(raw_buf, offset, data)?;
Ok(())
}
}
impl Drop for Buffer {
fn drop(&mut self) {
if let Some(buf_id) = self.id {
self.vulkan_device.unregister_bindless_buffer(buf_id.0);
}
if let Some(buf) = self.hal_buffer.take() {
self.vulkan_device.destroy_buffer(buf);
}
}
}