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> {}