mod3d_base/buffer_descriptor.rs
1//a Imports
2use std::cell::RefCell;
3
4use crate::{BufferData, Renderable, VertexDesc};
5
6//a BufferDescriptor
7//tp BufferDescriptor
8/// A descriptor of a subset of a `BufferData`, used for vertex attributes;
9/// hence for use in a vertex attribute pointer.
10///
11/// A [BufferDescriptor] allows portion of a [BufferData] to contain
12/// an array of structs with multiple fields for, e.g., Vertex, Normal
13/// and Color.
14///
15/// A [BufferDescriptor] is used within a [crate::BufferDataAccessor]
16/// to describe *just* an individual field element.
17pub struct BufferDescriptor<'a, R: Renderable> {
18 /// The `BufferData` that contains the actual vertex attribute data
19 data: &'a BufferData<'a, R>,
20
21 /// Byte offset to first data inside 'data'
22 byte_offset: u32,
23
24 /// Byte length of the data used by the descriptor
25 byte_length: u32,
26
27 // Indexed by instance - if true, instance 'n' vertex 'v' use the
28 // data from index 'n'; if false then instance 'n' vertex 'v' use
29 // the data from index 'v'.
30 //
31 // index_by_instance: bool,
32 /// Stride of data in the buffer
33 ///
34 /// This is always at least the maximum of the elements[].byte_offset() + byte_length()
35 stride: u32,
36
37 /// Description of the layout of the elements of the actual portion of buffer data
38 ///
39 /// This could become a reference to a struct that is borrowed here, with its own client ref
40 elements: Vec<VertexDesc>,
41
42 /// The client bound to data\[byte_offset\] .. + byte_length
43 ///
44 /// This must be held as a [RefCell] as the [BufferDescriptor] is
45 /// created early in the process, prior to any `BufferDataAccessor`s using
46 /// it - which then have shared references to the descriptor - but the
47 /// client is created afterwards
48 rc_client: RefCell<R::Descriptor>,
49}
50
51//ip Display for BufferDescriptor
52impl<'a, R: Renderable> std::fmt::Debug for BufferDescriptor<'a, R>
53where
54 R: Renderable,
55{
56 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
57 write!(
58 fmt,
59 "BufferDescriptor{{ {:?} @{}+*{}}}",
60 self.data,
61 self.byte_offset,
62 self.stride,
63 // self.ele_type,
64 // self.elements_per_data,
65 // self.rc_client
66 )
67 }
68}
69
70//ip AsRef<[u8]> for BufferDescriptor
71impl<'a, R> AsRef<[u8]> for BufferDescriptor<'a, R>
72where
73 R: Renderable,
74{
75 fn as_ref(&self) -> &[u8] {
76 let data: &[u8] = self.data.as_ref();
77 let start = self.byte_offset as usize;
78 let end = (self.byte_offset + self.byte_length) as usize;
79 &data[start..end]
80 }
81}
82
83//ip BufferDescriptor
84impl<'a, R: Renderable> BufferDescriptor<'a, R> {
85 //ap data
86 /// Get a reference to the underlying [BufferData]
87 pub fn data(&self) -> &BufferData<'a, R> {
88 self.data
89 }
90
91 //ap byte_offset
92 /// Get the byte offset within the underlying [BufferData] for
93 /// this descriptor
94 pub fn byte_offset(&self) -> u32 {
95 self.byte_offset
96 }
97
98 //ap byte_length
99 /// Get the byte length within the underlying [BufferData] for
100 /// this descriptor
101 pub fn byte_length(&self) -> u32 {
102 self.byte_length
103 }
104
105 //ap stride
106 /// Get the byte stride between different indices for the instances for
107 /// this descriptor
108 pub fn stride(&self) -> u32 {
109 self.stride
110 }
111
112 //ap element
113 /// Get a reference to the n'th element
114 pub fn element(&self, n: usize) -> &VertexDesc {
115 &self.elements[n]
116 }
117
118 //ap elements
119 /// Get a reference to the elements
120 pub fn elements(&self) -> &[VertexDesc] {
121 &self.elements
122 }
123
124 //fp new
125 /// Create a new view of a `BufferData`
126 pub fn new(
127 data: &'a BufferData<'a, R>,
128 byte_offset: u32,
129 byte_length: u32,
130 mut stride: u32,
131 elements: Vec<VertexDesc>,
132 ) -> Self {
133 assert!(
134 byte_offset + byte_length <= data.byte_length(),
135 "Buffer data is not large enough for data {byte_offset} + #{byte_length} [ got {}]",
136 data.byte_length()
137 );
138
139 let rc_client = RefCell::new(R::Descriptor::default());
140 for e in elements.iter() {
141 stride = stride.max(e.byte_offset() as u32 + e.byte_length());
142 }
143 Self {
144 data,
145 byte_offset,
146 byte_length,
147 stride,
148 elements,
149 rc_client,
150 }
151 }
152
153 //mp add_vertex_desc
154 /// Add a [VertexDesc] to the fields that this [BufferDescriptor] describes.
155 pub fn add_vertex_desc(&mut self, vertex_desc: VertexDesc) -> u8 {
156 let n = self.elements.len() as u8;
157 self.stride = self
158 .stride
159 .max(vertex_desc.byte_offset() as u32 + vertex_desc.byte_length());
160 self.elements.push(vertex_desc);
161 n
162 }
163
164 //mp create_client
165 /// Create the render buffer required by the BufferDescriptor
166 pub fn create_client(&self, renderable: &mut R) {
167 use std::ops::DerefMut;
168 renderable.init_buffer_desc_client(self.rc_client.borrow_mut().deref_mut(), self);
169 }
170
171 //ap borrow_client
172 /// Borrow the client
173 pub fn borrow_client(&self) -> std::cell::Ref<R::Descriptor> {
174 self.rc_client.borrow()
175 }
176
177 //zz All done
178}
179
180//ip Display for BufferDescriptor
181impl<'a, R: Renderable> std::fmt::Display for BufferDescriptor<'a, R> {
182 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
183 std::fmt::Debug::fmt(self, f)
184 }
185}
186
187//ip DefaultIndentedDisplay for BufferDescriptor
188impl<'a, R: Renderable> indent_display::DefaultIndentedDisplay for BufferDescriptor<'a, R> {}