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