naga/valid/
compose.rs
1use crate::arena::Handle;
2use crate::proc::TypeResolution;
3
4#[derive(Clone, Debug, thiserror::Error)]
5#[cfg_attr(test, derive(PartialEq))]
6pub enum ComposeError {
7 #[error("Composing of type {0:?} can't be done")]
8 Type(Handle<crate::Type>),
9 #[error("Composing expects {expected} components but {given} were given")]
10 ComponentCount { given: u32, expected: u32 },
11 #[error("Composing {index}'s component type is not expected")]
12 ComponentType { index: u32 },
13}
14
15pub fn validate_compose(
16 self_ty_handle: Handle<crate::Type>,
17 gctx: crate::proc::GlobalCtx,
18 component_resolutions: impl ExactSizeIterator<Item = TypeResolution>,
19) -> Result<(), ComposeError> {
20 use crate::TypeInner as Ti;
21
22 match gctx.types[self_ty_handle].inner {
23 Ti::Vector { size, scalar } => {
25 let mut total = 0;
26 for (index, comp_res) in component_resolutions.enumerate() {
27 total += match *comp_res.inner_with(gctx.types) {
28 Ti::Scalar(comp_scalar) if comp_scalar == scalar => 1,
29 Ti::Vector {
30 size: comp_size,
31 scalar: comp_scalar,
32 } if comp_scalar == scalar => comp_size as u32,
33 ref other => {
34 log::error!(
35 "Vector component[{index}] type {other:?}, building {scalar:?}"
36 );
37 return Err(ComposeError::ComponentType {
38 index: index as u32,
39 });
40 }
41 };
42 }
43 if size as u32 != total {
44 return Err(ComposeError::ComponentCount {
45 expected: size as u32,
46 given: total,
47 });
48 }
49 }
50 Ti::Matrix {
52 columns,
53 rows,
54 scalar,
55 } => {
56 let inner = Ti::Vector { size: rows, scalar };
57 if columns as usize != component_resolutions.len() {
58 return Err(ComposeError::ComponentCount {
59 expected: columns as u32,
60 given: component_resolutions.len() as u32,
61 });
62 }
63 for (index, comp_res) in component_resolutions.enumerate() {
64 if comp_res.inner_with(gctx.types) != &inner {
65 log::error!("Matrix component[{index}] type {comp_res:?}");
66 return Err(ComposeError::ComponentType {
67 index: index as u32,
68 });
69 }
70 }
71 }
72 Ti::Array {
73 base,
74 size: crate::ArraySize::Constant(count),
75 stride: _,
76 } => {
77 if count.get() as usize != component_resolutions.len() {
78 return Err(ComposeError::ComponentCount {
79 expected: count.get(),
80 given: component_resolutions.len() as u32,
81 });
82 }
83 for (index, comp_res) in component_resolutions.enumerate() {
84 if !gctx.compare_types(&TypeResolution::Handle(base), &comp_res) {
85 log::error!("Array component[{index}] type {comp_res:?}");
86 return Err(ComposeError::ComponentType {
87 index: index as u32,
88 });
89 }
90 }
91 }
92 Ti::Struct { ref members, .. } => {
93 if members.len() != component_resolutions.len() {
94 return Err(ComposeError::ComponentCount {
95 given: component_resolutions.len() as u32,
96 expected: members.len() as u32,
97 });
98 }
99 for (index, (member, comp_res)) in members.iter().zip(component_resolutions).enumerate()
100 {
101 if !gctx.compare_types(&TypeResolution::Handle(member.ty), &comp_res) {
102 log::error!("Struct component[{index}] type {comp_res:?}");
103 return Err(ComposeError::ComponentType {
104 index: index as u32,
105 });
106 }
107 }
108 }
109 ref other => {
110 log::error!("Composing of {other:?}");
111 return Err(ComposeError::Type(self_ty_handle));
112 }
113 }
114
115 Ok(())
116}