mod3d_base/
buffer_data.rs

1//a Imports
2use std::cell::RefCell;
3
4use crate::{ByteBuffer, Renderable};
5
6//a BufferData
7//tp BufferData
8/// A data buffer for use with vertex data. It may be indices
9/// or vertex coordinates etc.
10///
11/// A data buffer may contain a lot of data per vertex, such as
12/// position, normal, tangent, color etc.  a GPU `BufferView` on the data is
13/// then a subset of this data - perhaps picking out just the
14/// position, for example, for a set of vertices
15///
16/// The data buffer may, indeed, contain data for more than one object
17/// - and the objects may have different data per vertex.
18///
19/// A data buffer may then be used by many GPU `BufferView`s. Each
20/// `BufferView` may be used by many primitives for a single model;
21/// alternatively, primitives may have their own individual
22/// `BufferViews`.
23///
24/// To allow a [Renderable] to use the [BufferData] for multiple
25/// views, it supports a 'client' field that can be initialized using
26/// the 'init_buffer_data_client' method of the Renderable, and then
27/// borrowed as required during render programming.
28pub struct BufferData<'a, R: Renderable> {
29    /// Data buffer itself
30    data: &'a [u8],
31
32    ///
33    /// byte_offset..(byte_offset+byte_length) is guaranteed to be within the data field
34    ///
35    /// This value cannot be public without breaking the validity
36    byte_offset: u32,
37
38    /// Length of data used in the buffer
39    ///
40    /// byte_offset..(byte_offset+byte_length) is guaranteed to be within the data field
41    ///
42    /// This value cannot be public without breaking the validity
43    byte_length: u32,
44
45    /// The client bound to data\[byte_offset\] .. + byte_length
46    ///
47    /// This must be held as a [RefCell] as the [BufferData] is
48    /// created early in the process, prior to any `BufferView`s using
49    /// it - which then have shared references to the data - but the
50    /// client is created afterwards
51    rc_client: RefCell<R::Buffer>,
52}
53
54//ip Debug for BufferData
55impl<'a, R: Renderable> std::fmt::Debug for BufferData<'a, R> {
56    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
57        let (data, cont) = {
58            if self.data.len() < 8 {
59                (self.data, "")
60            } else {
61                (&self.data[0..8], "...")
62            }
63        };
64        write!(
65            fmt,
66            "BufferData {{{0:?}{cont}#{4}, byte_offset:{1}, byte_length:{2}, client:{3:?}}}",
67            data,
68            self.byte_offset,
69            self.byte_length,
70            self.rc_client,
71            self.data.len(),
72        )
73    }
74}
75
76//ip BufferData
77impl<'a, R: Renderable> BufferData<'a, R> {
78    //ap byte_length
79    /// Get the byte length of the [BufferData]
80    #[inline]
81    pub fn byte_length(&self) -> u32 {
82        self.byte_length
83    }
84
85    //ap byte_offset
86    /// Get the byte offset within the underlying data of the [BufferData]
87    #[inline]
88    pub fn byte_offset(&self) -> u32 {
89        self.byte_offset
90    }
91
92    //fp new
93    /// Create a new [BufferData] given a buffer, offset and length; if the
94    /// length is zero then the whole of the data buffer post offset
95    /// is used
96    ///
97    /// If offset and length are both zero, then all the data is used
98    pub fn new<B: ByteBuffer + ?Sized>(data: &'a B, byte_offset: u32, byte_length: u32) -> Self {
99        let byte_length = {
100            if byte_length == 0 {
101                (data.byte_length() as u32) - byte_offset
102            } else {
103                byte_length
104            }
105        };
106        let rc_client = RefCell::new(R::Buffer::default());
107        let data = data.borrow_bytes();
108        assert!(
109            byte_offset + byte_length <= data.len() as u32,
110            "Buffer is not large enough for data {byte_offset} + #{byte_length} [ got {}]",
111            data.len()
112        );
113        Self {
114            data,
115            byte_offset,
116            byte_length,
117            rc_client,
118        }
119    }
120
121    //mp create_client
122    /// Replace the client data with one of this data
123    pub fn create_client(&self, renderable: &mut R) {
124        use std::ops::DerefMut;
125        renderable.init_buffer_data_client(self.rc_client.borrow_mut().deref_mut(), self);
126    }
127
128    //ap borrow_client
129    /// Borrow the client immutably
130    pub fn borrow_client(&self) -> std::cell::Ref<R::Buffer> {
131        self.rc_client.borrow()
132    }
133
134    //zz All done
135}
136
137//ip AsRef<[u8]> for BufferData
138impl<'a, R> AsRef<[u8]> for BufferData<'a, R>
139where
140    R: Renderable,
141{
142    fn as_ref(&self) -> &[u8] {
143        let start = self.byte_offset as usize;
144        let end = (self.byte_offset + self.byte_length) as usize;
145        &self.data[start..end]
146    }
147}
148
149//ip Display for BufferData
150impl<'a, R: Renderable> std::fmt::Display for BufferData<'a, R> {
151    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
152        let data_ptr = self.data.as_ptr();
153        write!(
154            f,
155            "BufferData[{:?}+{}#{}]:",
156            data_ptr, self.byte_offset, self.byte_length,
157        )?;
158        use crate::BufferClient;
159        (*self.rc_client.borrow()).fmt(f)
160    }
161}
162
163//ip DefaultIndentedDisplay for BufferData
164impl<'a, R: Renderable> indent_display::DefaultIndentedDisplay for BufferData<'a, R> {}