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