1use fnv::FnvHashMap;
2use rafx_api::{RafxFormat, RafxPrimitiveTopology, RafxVertexAttributeRate};
3use std::collections::BTreeMap;
4use std::sync::Arc;
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8pub struct VertexDataLayoutHash(u64);
9
10impl VertexDataLayoutHash {
11 fn new(
12 vertex_stride: usize,
13 members: &FnvHashMap<String, VertexDataMemberMeta>,
14 ) -> VertexDataLayoutHash {
15 let mut sorted = BTreeMap::<&String, &VertexDataMemberMeta>::default();
17 for (key, value) in members {
18 sorted.insert(key, value);
19 }
20
21 use fnv::FnvHasher;
23 use std::hash::Hash;
24 use std::hash::Hasher;
25 let mut hasher = FnvHasher::default();
26 vertex_stride.hash(&mut hasher);
27 sorted.hash(&mut hasher);
28 VertexDataLayoutHash(hasher.finish())
29 }
30}
31
32#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
34pub struct VertexDataSetLayoutHash(u64);
35
36impl VertexDataSetLayoutHash {
37 fn new(
38 layouts: &[VertexDataLayout],
39 primitive_topology: RafxPrimitiveTopology,
40 ) -> VertexDataSetLayoutHash {
41 use fnv::FnvHasher;
43 use std::hash::Hash;
44 use std::hash::Hasher;
45 let mut hasher = FnvHasher::default();
46 for layout in layouts {
47 layout.hash().0.hash(&mut hasher);
48 }
49 primitive_topology.hash(&mut hasher);
50 VertexDataSetLayoutHash(hasher.finish())
51 }
52}
53
54#[derive(Debug, Copy, Clone, PartialEq)]
55pub enum VertexCopyError {
56 VertexCountDoesNotMatch,
57 MemberFormatDoesNotMatch,
58 SizeOfSliceTypeDoesNotMatchLayout,
59 CantReinitializeFrom,
60}
61
62#[derive(Debug, Clone, PartialEq)]
63pub struct VertexMember {
64 pub semantic: String,
65 pub format: RafxFormat,
66 pub byte_offset: usize,
67}
68
69impl VertexMember {
71 pub fn new<VertexT: Copy + 'static, MemberT: Copy + 'static>(
72 vertex: &VertexT,
73 member: &MemberT,
74 semantic: String,
75 format: RafxFormat,
76 ) -> VertexMember {
77 let vertex_addr = vertex as *const _ as usize;
79 let member_addr = member as *const _ as usize;
80
81 let rust_member_size = std::mem::size_of::<MemberT>();
85 assert!(member_addr >= vertex_addr);
86 assert!((member_addr + rust_member_size) <= (vertex_addr + std::mem::size_of::<VertexT>()));
87
88 let format_size = format.block_or_pixel_size_in_bytes();
90 assert_eq!(
91 rust_member_size as u32,
92 format_size,
93 "The provided format {:?} is {} bytes but the rust type {} is {} bytes",
94 format,
95 format_size,
96 std::any::type_name::<MemberT>(),
97 rust_member_size
98 );
99
100 let offset = member_addr - vertex_addr;
101 VertexMember {
102 semantic,
103 format,
104 byte_offset: offset,
105 }
106 }
107}
108
109pub struct VertexMemberAccumulator<'a, VertexT> {
110 members: Vec<VertexMember>,
111 vertex: &'a VertexT,
112}
113
114impl<'a, VertexT: Copy + 'static> VertexMemberAccumulator<'a, VertexT> {
116 pub fn add_member<MemberT: Copy + 'static, StrT: Into<String>>(
117 &mut self,
118 member: &MemberT,
119 semantic: StrT,
120 format: RafxFormat,
121 ) {
122 self.members.push(VertexMember::new(
123 self.vertex,
124 member,
125 semantic.into(),
126 format,
127 ));
128 }
129}
130
131#[derive(Debug, Clone, PartialEq, Hash)]
132pub struct VertexDataMemberMeta {
133 pub format: RafxFormat,
134 pub byte_offset: usize,
135 pub size: usize,
136}
137
138#[derive(Debug, PartialEq)]
139pub struct VertexDataLayoutInner {
140 members: FnvHashMap<String, VertexDataMemberMeta>,
143 vertex_stride: usize,
144 vertex_rate: RafxVertexAttributeRate,
145 hash: VertexDataLayoutHash,
146}
147
148#[derive(Debug, PartialEq, Clone)]
149pub struct VertexDataLayout {
150 inner: Arc<VertexDataLayoutInner>,
153}
154
155impl VertexDataLayout {
156 pub fn new(
157 vertex_stride: usize,
158 vertex_rate: RafxVertexAttributeRate,
159 members: &[VertexMember],
160 ) -> Self {
161 let mut map = Default::default();
162 for member in members {
163 Self::add_member_to_map(vertex_stride, &mut map, member);
164 }
165
166 let hash = VertexDataLayoutHash::new(vertex_stride, &map);
167
168 let inner = VertexDataLayoutInner {
169 members: map,
170 vertex_stride,
171 vertex_rate,
172 hash,
173 };
174
175 VertexDataLayout {
176 inner: Arc::new(inner),
177 }
178 }
179
180 pub fn build_vertex_layout<
203 VertexT,
204 F: FnOnce(&mut VertexMemberAccumulator<VertexT>, &VertexT),
205 >(
206 vertex: &VertexT,
207 vertex_rate: RafxVertexAttributeRate,
208 f: F,
209 ) -> VertexDataLayout {
210 let mut accumulator = VertexMemberAccumulator {
211 members: Default::default(),
212 vertex,
213 };
214
215 (f)(&mut accumulator, vertex);
216 VertexDataLayout::new(
217 std::mem::size_of::<VertexT>(),
218 vertex_rate,
219 &accumulator.members,
220 )
221 }
222
223 fn add_member_to_map(
224 vertex_stride: usize,
225 map: &mut FnvHashMap<String, VertexDataMemberMeta>,
226 member: &VertexMember,
227 ) {
228 let size = member.format.block_or_pixel_size_in_bytes() as usize;
229 assert!(member.byte_offset + size <= vertex_stride);
230 let old = map.insert(
231 member.semantic.clone(),
232 VertexDataMemberMeta {
233 format: member.format,
234 byte_offset: member.byte_offset,
235 size,
236 },
237 );
238 assert!(old.is_none());
239 }
240
241 pub fn member(
242 &self,
243 name: &str,
244 ) -> Option<&VertexDataMemberMeta> {
245 self.inner.members.get(name)
246 }
247
248 pub fn members(&self) -> &FnvHashMap<String, VertexDataMemberMeta> {
249 &self.inner.members
250 }
251
252 pub fn hash(&self) -> VertexDataLayoutHash {
253 self.inner.hash
254 }
255
256 pub fn vertex_rate(&self) -> RafxVertexAttributeRate {
257 self.inner.vertex_rate
258 }
259
260 pub fn vertex_stride(&self) -> usize {
261 self.inner.vertex_stride
262 }
263
264 pub fn into_set(
265 self,
266 primitive_topology: RafxPrimitiveTopology,
267 ) -> VertexDataSetLayout {
268 VertexDataSetLayout::new(vec![self], primitive_topology)
269 }
270
271 pub fn intersects_with(
272 &self,
273 other: &Self,
274 ) -> bool {
275 for member_name in self.inner.members.keys() {
276 if other.inner.members.contains_key(member_name) {
277 return true;
278 }
279 }
280
281 false
282 }
283
284 pub fn is_subset_of(
285 &self,
286 other: &Self,
287 ) -> bool {
288 for member_name in self.inner.members.keys() {
289 if !other.inner.members.contains_key(member_name) {
290 return false;
291 }
292 }
293
294 true
295 }
296
297 pub fn is_subset_of_multi(
298 subsets: &[Self],
299 others: &[Self],
300 ) -> bool {
301 for subset in subsets {
302 for member_name in subset.inner.members.keys() {
303 let mut found_in_other = false;
304 for other in others {
305 if other.inner.members.contains_key(member_name) {
306 found_in_other = true;
307 break;
308 }
309 }
310
311 if !found_in_other {
312 return false;
313 }
314 }
315 }
316
317 true
318 }
319}
320
321#[derive(Debug, Clone, PartialEq)]
322pub struct VertexDataSetMemberMeta {
323 pub format: RafxFormat,
324 pub byte_offset: usize,
325 pub size: usize,
326 pub binding: usize,
327}
328
329#[derive(Debug, PartialEq)]
330pub struct VertexDataSetLayoutInner {
331 members: Arc<FnvHashMap<String, VertexDataSetMemberMeta>>,
334 layouts: Vec<VertexDataLayout>,
335 hash: VertexDataSetLayoutHash,
336 primitive_topology: RafxPrimitiveTopology,
337}
338
339#[derive(Debug, PartialEq, Clone)]
340pub struct VertexDataSetLayout {
341 inner: Arc<VertexDataSetLayoutInner>,
342}
343
344impl VertexDataSetLayout {
345 pub fn new(
346 layouts: Vec<VertexDataLayout>,
347 primitive_topology: RafxPrimitiveTopology,
348 ) -> Self {
349 let mut members = FnvHashMap::default();
350 for (binding, layout) in layouts.iter().enumerate() {
351 for (member_name, meta) in &layout.inner.members {
352 let old = members.insert(
353 member_name.clone(),
354 VertexDataSetMemberMeta {
355 format: meta.format,
356 size: meta.size,
357 byte_offset: meta.byte_offset,
358 binding,
359 },
360 );
361 assert!(old.is_none());
362 }
363 }
364
365 let hash = VertexDataSetLayoutHash::new(&layouts, primitive_topology);
366
367 let inner = VertexDataSetLayoutInner {
368 members: Arc::new(members),
369 layouts,
370 hash,
371 primitive_topology,
372 };
373
374 VertexDataSetLayout {
375 inner: Arc::new(inner),
376 }
377 }
378
379 pub fn binding(
380 &self,
381 binding: usize,
382 ) -> Option<&VertexDataLayout> {
383 self.inner.layouts.get(binding)
384 }
385
386 pub fn bindings(&self) -> &Vec<VertexDataLayout> {
387 &self.inner.layouts
388 }
389
390 pub fn member(
391 &self,
392 name: &str,
393 ) -> Option<&VertexDataSetMemberMeta> {
394 self.inner.members.get(name)
395 }
396
397 pub fn members(&self) -> &FnvHashMap<String, VertexDataSetMemberMeta> {
398 &self.inner.members
399 }
400
401 pub fn hash(&self) -> VertexDataSetLayoutHash {
402 self.inner.hash
403 }
404
405 pub fn primitive_topology(&self) -> RafxPrimitiveTopology {
406 self.inner.primitive_topology
407 }
408}
409
410#[derive(Clone)]
411pub struct VertexData {
412 layout: VertexDataLayout,
413 data: Vec<u128>,
415 vertex_count: usize,
416}
417
418impl VertexData {
419 pub fn new_memzero(
420 layout: VertexDataLayout,
421 vertex_count: usize,
422 ) -> Self {
423 let total_size = layout.vertex_stride() * vertex_count;
424
425 let data = vec![0_u128; (total_size + 15) / 16];
427
428 VertexData {
429 layout,
430 data,
431 vertex_count,
432 }
433 }
434
435 pub fn new_from_slice<T: Copy>(
436 src_layout: &VertexDataLayout,
437 src_data: &[T],
438 ) -> Self {
439 let mut data = Self::new_memzero(src_layout.clone(), src_data.len());
440 data.copy_from_slice(src_layout, src_data).unwrap();
441 data
442 }
443
444 pub fn reinitialize_from(
445 &mut self,
446 other: &Self,
447 ) -> Result<(), VertexCopyError> {
448 if !self.layout.is_subset_of(&other.layout) {
449 return Err(VertexCopyError::CantReinitializeFrom);
450 }
451
452 self.copy_from(other)
453 }
454
455 pub fn reinitialize_from_slice<T: Copy>(
456 &mut self,
457 src_layout: &VertexDataLayout,
458 src_data: &[T],
459 ) -> Result<(), VertexCopyError> {
460 if !self.layout.is_subset_of(&src_layout) {
461 return Err(VertexCopyError::CantReinitializeFrom);
462 }
463
464 self.copy_from_slice(src_layout, src_data)
465 }
466
467 pub fn copy_from(
468 &mut self,
469 other: &Self,
470 ) -> Result<(), VertexCopyError> {
471 Self::copy_between_vertex_data(other, self)
472 }
473
474 pub fn copy_to(
475 &self,
476 other: &mut Self,
477 ) -> Result<(), VertexCopyError> {
478 Self::copy_between_vertex_data(self, other)
479 }
480
481 pub fn copy_between_vertex_data(
482 src: &VertexData,
483 dst: &mut VertexData,
484 ) -> Result<(), VertexCopyError> {
485 if src.vertex_count != dst.vertex_count {
486 return Err(VertexCopyError::VertexCountDoesNotMatch);
487 }
488
489 unsafe {
490 let src_ptr = src.ptr();
491 let dst_ptr = dst.ptr_mut();
492 Self::copy_between_layouts(&src.layout, src_ptr, &dst.layout, dst_ptr, dst.vertex_count)
493 }
494 }
495
496 pub fn copy_from_slice<T: Copy>(
497 &mut self,
498 src_layout: &VertexDataLayout,
499 src_data: &[T],
500 ) -> Result<(), VertexCopyError> {
501 if src_data.len() != self.vertex_count {
502 return Err(VertexCopyError::VertexCountDoesNotMatch);
503 }
504
505 if std::mem::size_of::<T>() != src_layout.vertex_stride() {
506 return Err(VertexCopyError::SizeOfSliceTypeDoesNotMatchLayout);
507 }
508
509 unsafe {
510 let dst_data = self.ptr_mut();
511 Self::copy_between_layouts(
512 src_layout,
513 src_data.as_ptr() as *const u8,
514 &self.layout,
515 dst_data,
516 src_data.len(),
517 )
518 }
519 }
520
521 pub fn copy_to_slice<T: Copy>(
522 &self,
523 dst_layout: &VertexDataLayout,
524 dst_data: &mut [T],
525 ) -> Result<(), VertexCopyError> {
526 if dst_data.len() != self.vertex_count {
527 return Err(VertexCopyError::VertexCountDoesNotMatch);
528 }
529
530 if std::mem::size_of::<T>() != dst_layout.vertex_stride() {
531 return Err(VertexCopyError::SizeOfSliceTypeDoesNotMatchLayout);
532 }
533
534 unsafe {
535 let src_data = self.ptr();
536 Self::copy_between_layouts(
537 &self.layout,
538 src_data,
539 dst_layout,
540 dst_data.as_mut_ptr() as *mut u8,
541 dst_data.len(),
542 )
543 }
544 }
545
546 pub fn copy_between_slices<T: Copy, U: Copy>(
547 src_layout: &VertexDataLayout,
548 src_data: &[T],
549 dst_layout: &VertexDataLayout,
550 dst_data: &mut [U],
551 ) -> Result<(), VertexCopyError> {
552 if src_data.len() != dst_data.len() {
553 return Err(VertexCopyError::VertexCountDoesNotMatch);
554 }
555
556 if std::mem::size_of::<T>() != src_layout.vertex_stride() {
557 return Err(VertexCopyError::SizeOfSliceTypeDoesNotMatchLayout);
558 }
559
560 if std::mem::size_of::<U>() != dst_layout.vertex_stride() {
561 return Err(VertexCopyError::SizeOfSliceTypeDoesNotMatchLayout);
562 }
563
564 unsafe {
565 Self::copy_between_layouts(
566 src_layout,
567 src_data.as_ptr() as *const u8,
568 dst_layout,
569 dst_data.as_mut_ptr() as *mut u8,
570 dst_data.len(),
571 )
572 }
573 }
574
575 pub fn can_copy_between_layouts(
576 src_layout: &VertexDataLayout,
577 dst_layout: &VertexDataLayout,
578 ) -> Result<(), VertexCopyError> {
579 for (member_name, src_member) in src_layout.members() {
581 if let Some(dst_member) = dst_layout.members().get(member_name) {
582 if src_member.format != dst_member.format {
583 return Err(VertexCopyError::MemberFormatDoesNotMatch);
584 }
585
586 assert_eq!(src_member.size, dst_member.size);
588 }
589 }
590
591 Ok(())
592 }
593
594 pub unsafe fn copy_between_layouts(
595 src_layout: &VertexDataLayout,
596 src_data: *const u8,
597 dst_layout: &VertexDataLayout,
598 dst_data: *mut u8,
599 vertex_count: usize,
600 ) -> Result<(), VertexCopyError> {
601 if src_layout == dst_layout {
602 std::ptr::copy_nonoverlapping(
603 src_data,
604 dst_data,
605 vertex_count * src_layout.vertex_stride(),
606 );
607 return Ok(());
608 }
609
610 if !src_layout.intersects_with(dst_layout) {
611 return Ok(());
612 }
613
614 Self::can_copy_between_layouts(src_layout, dst_layout)?;
616
617 for (member_name, src_member) in src_layout.members() {
619 if let Some(dst_member) = dst_layout.members().get(member_name) {
620 for i in 0..vertex_count {
621 let src_ptr =
622 src_data.add((src_layout.vertex_stride() * i) + src_member.byte_offset);
623 let dst_ptr =
624 dst_data.add((dst_layout.vertex_stride() * i) + dst_member.byte_offset);
625
626 std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_member.size);
627 }
628 }
629 }
630
631 Ok(())
632 }
633
634 pub unsafe fn ptr(&self) -> *const u8 {
635 self.data.as_ptr() as *const u8
636 }
637
638 pub unsafe fn ptr_mut(&mut self) -> *mut u8 {
639 self.data.as_mut_ptr() as *mut u8
640 }
641}
642
643pub struct VertexDataSet {
644 layouts: Vec<VertexDataLayout>,
645 data: Vec<VertexData>,
646 vertex_count: usize,
647}
648
649impl VertexDataSet {
650 pub fn new(data: Vec<VertexData>) -> Result<Self, &'static str> {
651 if data.is_empty() {
652 Ok(VertexDataSet {
653 data: Default::default(),
654 vertex_count: 0,
655 layouts: Default::default(),
656 })
657 } else {
658 let vertex_count = data[0].vertex_count;
659 for d in &data {
660 if vertex_count != d.vertex_count {
661 return Err("vertex data does not have same number of vertices");
662 }
663 }
664
665 let layouts = data.iter().map(|x| x.layout.clone()).collect();
666
667 Ok(VertexDataSet {
668 data,
669 vertex_count,
670 layouts,
671 })
672 }
673 }
674
675 pub fn new_memzero(
676 layouts: &[VertexDataLayout],
677 vertex_count: usize,
678 ) -> Self {
679 let data = layouts
680 .iter()
681 .map(|layout| VertexData::new_memzero(layout.clone(), vertex_count))
682 .collect();
683
684 VertexDataSet {
685 data,
686 vertex_count,
687 layouts: layouts.to_vec(),
688 }
689 }
690
691 pub fn new_from_slice<T: Copy>(
692 src_layout: &VertexDataLayout,
693 src_data: &[T],
694 ) -> Self {
695 let mut data = vec![VertexData::new_memzero(src_layout.clone(), src_data.len())];
696 data[0].copy_from_slice(src_layout, src_data).unwrap();
697
698 VertexDataSet {
699 data,
700 vertex_count: src_data.len(),
701 layouts: vec![src_layout.clone()],
702 }
703 }
704
705 pub fn reinitialize_from(
706 &mut self,
707 other: &Self,
708 ) -> Result<(), VertexCopyError> {
709 if !VertexDataLayout::is_subset_of_multi(&self.layouts, &other.layouts) {
710 return Err(VertexCopyError::CantReinitializeFrom);
711 }
712
713 self.copy_from(other)
714 }
715
716 pub fn reinitialize_from_slice<T: Copy>(
717 &mut self,
718 src_layout: &VertexDataLayout,
719 src_data: &[T],
720 ) -> Result<(), VertexCopyError> {
721 for layout in &self.layouts {
722 if !layout.is_subset_of(src_layout) {
723 return Err(VertexCopyError::CantReinitializeFrom);
724 }
725 }
726
727 self.copy_from_slice(src_layout, src_data)
728 }
729
730 pub fn copy_from(
731 &mut self,
732 other: &Self,
733 ) -> Result<(), VertexCopyError> {
734 Self::copy_between_vertex_data(
735 other.vertex_count,
736 &other.data,
737 self.vertex_count,
738 &mut self.data,
739 )
740 }
741
742 pub fn copy_to(
743 &self,
744 other: &mut Self,
745 ) -> Result<(), VertexCopyError> {
746 Self::copy_between_vertex_data(
747 self.vertex_count,
748 &self.data,
749 other.vertex_count,
750 &mut other.data,
751 )
752 }
753
754 pub fn copy_from_single(
755 &mut self,
756 other: &VertexData,
757 ) -> Result<(), VertexCopyError> {
758 Self::copy_between_vertex_data(
759 other.vertex_count,
760 std::slice::from_ref(other),
761 self.vertex_count,
762 &mut self.data,
763 )
764 }
765
766 pub fn copy_to_single(
767 &self,
768 other: &mut VertexData,
769 ) -> Result<(), VertexCopyError> {
770 Self::copy_between_vertex_data(
771 self.vertex_count,
772 &self.data,
773 other.vertex_count,
774 std::slice::from_mut(other),
775 )
776 }
777
778 pub fn copy_between_vertex_data(
779 src_vertex_count: usize,
780 src_data: &[VertexData],
781 dst_vertex_count: usize,
782 dst_data: &mut [VertexData],
783 ) -> Result<(), VertexCopyError> {
784 if src_vertex_count != dst_vertex_count {
785 return Err(VertexCopyError::VertexCountDoesNotMatch);
786 }
787
788 for src in src_data {
789 for dst in &mut *dst_data {
790 VertexData::can_copy_between_layouts(&src.layout, &dst.layout)?;
791 }
792 }
793
794 for src in src_data {
795 for dst in &mut *dst_data {
796 dst.copy_from(src)?;
797 }
798 }
799
800 Ok(())
801 }
802
803 pub fn copy_from_slice<T: Copy>(
804 &mut self,
805 src_layout: &VertexDataLayout,
806 src_data: &[T],
807 ) -> Result<(), VertexCopyError> {
808 if src_data.len() != self.vertex_count {
809 return Err(VertexCopyError::VertexCountDoesNotMatch);
810 }
811
812 if std::mem::size_of::<T>() != src_layout.vertex_stride() {
813 return Err(VertexCopyError::SizeOfSliceTypeDoesNotMatchLayout);
814 }
815
816 for layout in &self.layouts {
817 VertexData::can_copy_between_layouts(src_layout, layout)?;
818 }
819
820 for data in &mut self.data {
821 data.copy_from_slice(src_layout, src_data)?;
822 }
823
824 Ok(())
825 }
826
827 pub fn copy_to_slice<T: Copy>(
828 &self,
829 dst_layout: &VertexDataLayout,
830 dst_data: &mut [T],
831 ) -> Result<(), VertexCopyError> {
832 if dst_data.len() != self.vertex_count {
833 return Err(VertexCopyError::VertexCountDoesNotMatch);
834 }
835
836 if std::mem::size_of::<T>() != dst_layout.vertex_stride() {
837 return Err(VertexCopyError::SizeOfSliceTypeDoesNotMatchLayout);
838 }
839
840 for layout in &self.layouts {
841 VertexData::can_copy_between_layouts(layout, dst_layout)?;
842 }
843
844 for data in &self.data {
845 data.copy_to_slice(dst_layout, dst_data)?;
846 }
847
848 Ok(())
849 }
850
851 pub unsafe fn data(&self) -> &[VertexData] {
852 &self.data
853 }
854
855 pub unsafe fn data_mut(&mut self) -> &mut [VertexData] {
856 &mut self.data
857 }
858}
859
860#[cfg(test)]
861mod test {
862 use super::*;
863 use rafx_api::RafxFormat;
864
865 #[derive(Default, Clone, Copy, Debug)]
866 #[repr(C)]
867 pub struct MediumVertex {
868 pub position: [f32; 3],
869 pub normal: [f32; 3],
870 pub color: [f32; 4],
871 pub tangent: [f32; 3],
872 pub tex_coord: [f32; 2],
873 }
874
875 impl MediumVertex {
876 fn get_layout() -> VertexDataLayout {
877 VertexDataLayout::build_vertex_layout(
878 &Self::default(),
879 RafxVertexAttributeRate::Vertex,
880 |builder, vertex| {
881 builder.add_member(&vertex.position, "POSITION", RafxFormat::R32G32B32_SFLOAT);
882 builder.add_member(&vertex.normal, "NORMAL", RafxFormat::R32G32B32_SFLOAT);
883 builder.add_member(&vertex.color, "COLOR", RafxFormat::R32G32B32A32_SFLOAT);
884 builder.add_member(&vertex.tangent, "TANGENT", RafxFormat::R32G32B32_SFLOAT);
885 builder.add_member(&vertex.tex_coord, "TEXCOORD", RafxFormat::R32G32_SFLOAT);
886 },
887 )
888 }
889
890 fn create_empty_data() -> Vec<MediumVertex> {
891 (0..100).map(|_| MediumVertex::default()).collect()
892 }
893
894 fn create_test_data() -> Vec<MediumVertex> {
895 (0..100)
896 .map(|x| {
897 let x = x as f32;
898 MediumVertex {
899 position: [1.0, x, x],
900 normal: [2.0, x, x],
901 color: [3.0, x, x, x],
902 tangent: [4.0, x, x],
903 tex_coord: [5.0, x],
904 }
905 })
906 .collect()
907 }
908 }
909
910 #[derive(Default, Clone, Copy, Debug)]
911 #[repr(C)]
912 pub struct SmallVertex {
913 pub normal: [f32; 3],
914 pub position: [f32; 3],
915 }
916
917 impl SmallVertex {
918 fn get_layout() -> VertexDataLayout {
919 VertexDataLayout::build_vertex_layout(
920 &Self::default(),
921 RafxVertexAttributeRate::Vertex,
922 |builder, vertex| {
923 builder.add_member(&vertex.position, "POSITION", RafxFormat::R32G32B32_SFLOAT);
924 builder.add_member(&vertex.normal, "NORMAL", RafxFormat::R32G32B32_SFLOAT);
925 },
926 )
927 }
928
929 fn create_empty_data() -> Vec<SmallVertex> {
930 (0..100).map(|_| SmallVertex::default()).collect()
931 }
932
933 fn create_test_data() -> Vec<SmallVertex> {
934 (0..100)
935 .map(|x| {
936 let x = x as f32;
937 SmallVertex {
938 position: [1.0, x, x],
939 normal: [2.0, x, x],
940 }
941 })
942 .collect()
943 }
944 }
945
946 #[derive(Default, Clone, Copy, Debug)]
947 #[repr(C)]
948 pub struct TinyVertex {
949 pub color: [f32; 4],
950 }
951
952 impl TinyVertex {
953 fn get_layout() -> VertexDataLayout {
954 VertexDataLayout::build_vertex_layout(
955 &Self::default(),
956 RafxVertexAttributeRate::Vertex,
957 |builder, vertex| {
958 builder.add_member(&vertex.color, "COLOR", RafxFormat::R32G32B32A32_SFLOAT);
959 },
960 )
961 }
962 }
963
964 #[test]
965 fn test_to_smaller() {
966 let from_layout = MediumVertex::get_layout();
967 let from_data = MediumVertex::create_test_data();
968
969 let to_layout = SmallVertex::get_layout();
970 let mut to_data = SmallVertex::create_empty_data();
971
972 let data = VertexData::new_from_slice(&from_layout, &from_data);
973 data.copy_to_slice(&to_layout, &mut to_data).unwrap();
974
975 assert!((from_data[4].position[1] - 4.0).abs() < 0.1);
976 assert!((to_data[4].position[1] - 4.0).abs() < 0.1);
977
978 assert!((from_data[4].position[0] - 1.0).abs() < 0.1);
979 assert!((to_data[4].position[0] - 1.0).abs() < 0.1);
980
981 assert!((from_data[4].normal[0] - 2.0).abs() < 0.1);
982 assert!((to_data[4].normal[0] - 2.0).abs() < 0.1);
983 }
984
985 #[test]
986 fn test_to_larger() {
987 let from_layout = SmallVertex::get_layout();
988 let from_data = SmallVertex::create_test_data();
989
990 let to_layout = MediumVertex::get_layout();
991 let mut to_data = MediumVertex::create_empty_data();
992
993 let data = VertexData::new_from_slice(&from_layout, &from_data);
994 data.copy_to_slice(&to_layout, &mut to_data).unwrap();
995
996 assert!((from_data[4].position[1] - 4.0).abs() < 0.1);
997 assert!((to_data[4].position[1] - 4.0).abs() < 0.1);
998
999 assert!((from_data[4].position[0] - 1.0).abs() < 0.1);
1000 assert!((to_data[4].position[0] - 1.0).abs() < 0.1);
1001
1002 assert!((from_data[4].normal[0] - 2.0).abs() < 0.1);
1003 assert!((to_data[4].normal[0] - 2.0).abs() < 0.1);
1004 }
1005
1006 #[test]
1007 fn test_copy_from() {
1008 let from_layout = MediumVertex::get_layout();
1009 let from_data = MediumVertex::create_test_data();
1010 let from = VertexData::new_from_slice(&from_layout, &from_data);
1011
1012 let to_layout = SmallVertex::get_layout();
1013 let to_data = SmallVertex::create_empty_data();
1014 let mut to = VertexData::new_from_slice(&to_layout, &to_data);
1015
1016 to.copy_from(&from).unwrap();
1017
1018 let mut to_data = SmallVertex::create_empty_data();
1019 to.copy_to_slice(&to_layout, &mut to_data).unwrap();
1020
1021 assert!((from_data[4].position[1] - 4.0).abs() < 0.1);
1022 assert!((to_data[4].position[1] - 4.0).abs() < 0.1);
1023
1024 assert!((from_data[4].position[0] - 1.0).abs() < 0.1);
1025 assert!((to_data[4].position[0] - 1.0).abs() < 0.1);
1026
1027 assert!((from_data[4].normal[0] - 2.0).abs() < 0.1);
1028 assert!((to_data[4].normal[0] - 2.0).abs() < 0.1);
1029 }
1030
1031 #[test]
1032 fn test_into_data_set() {
1033 let from_layout = MediumVertex::get_layout();
1034 let from_data = MediumVertex::create_test_data();
1035 let from = VertexData::new_from_slice(&from_layout, &from_data);
1036
1037 let mut data_set = VertexDataSet::new(vec![
1038 VertexData::new_memzero(SmallVertex::get_layout(), 100),
1039 VertexData::new_memzero(TinyVertex::get_layout(), 100),
1040 ])
1041 .unwrap();
1042
1043 data_set.copy_from_single(&from).unwrap();
1044
1045 let mut to_data = SmallVertex::create_empty_data();
1046 data_set
1047 .copy_to_slice(&SmallVertex::get_layout(), &mut to_data)
1048 .unwrap();
1049
1050 assert!((from_data[4].position[1] - 4.0).abs() < 0.1);
1051 assert!((to_data[4].position[1] - 4.0).abs() < 0.1);
1052
1053 assert!((from_data[4].position[0] - 1.0).abs() < 0.1);
1054 assert!((to_data[4].position[0] - 1.0).abs() < 0.1);
1055
1056 assert!((from_data[4].normal[0] - 2.0).abs() < 0.1);
1057 assert!((to_data[4].normal[0] - 2.0).abs() < 0.1);
1058 }
1059}