use super::Error;
use crate::arena::{Arena, Handle, UniqueArena};
const fn make_scalar_inner(kind: crate::ScalarKind, width: crate::Bytes) -> crate::ConstantInner {
crate::ConstantInner::Scalar {
width,
value: match kind {
crate::ScalarKind::Uint => crate::ScalarValue::Uint(0),
crate::ScalarKind::Sint => crate::ScalarValue::Sint(0),
crate::ScalarKind::Float => crate::ScalarValue::Float(0.0),
crate::ScalarKind::Bool => crate::ScalarValue::Bool(false),
},
}
}
pub fn generate_null_constant(
ty: Handle<crate::Type>,
type_arena: &UniqueArena<crate::Type>,
constant_arena: &mut Arena<crate::Constant>,
span: crate::Span,
) -> Result<crate::ConstantInner, Error> {
let inner = match type_arena[ty].inner {
crate::TypeInner::Scalar { kind, width } => make_scalar_inner(kind, width),
crate::TypeInner::Vector { size, kind, width } => {
let mut components = Vec::with_capacity(size as usize);
for _ in 0..size as usize {
components.push(constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner: make_scalar_inner(kind, width),
},
span,
));
}
crate::ConstantInner::Composite { ty, components }
}
crate::TypeInner::Matrix {
columns,
rows,
width,
} => {
let vector_ty = type_arena
.get(&crate::Type {
name: None,
inner: crate::TypeInner::Vector {
kind: crate::ScalarKind::Float,
size: rows,
width,
},
})
.unwrap();
let vector_inner = generate_null_constant(vector_ty, type_arena, constant_arena, span)?;
let vector_handle = constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner: vector_inner,
},
span,
);
crate::ConstantInner::Composite {
ty,
components: vec![vector_handle; columns as usize],
}
}
crate::TypeInner::Struct { ref members, .. } => {
let mut components = Vec::with_capacity(members.len());
let member_tys = members.iter().map(|member| member.ty).collect::<Vec<_>>();
for member_ty in member_tys {
let inner = generate_null_constant(member_ty, type_arena, constant_arena, span)?;
components.push(constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner,
},
span,
));
}
crate::ConstantInner::Composite { ty, components }
}
crate::TypeInner::Array {
base,
size: crate::ArraySize::Constant(handle),
..
} => {
let size = constant_arena[handle]
.to_array_length()
.ok_or(Error::InvalidArraySize(handle))?;
let inner = generate_null_constant(base, type_arena, constant_arena, span)?;
let value = constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner,
},
span,
);
crate::ConstantInner::Composite {
ty,
components: vec![value; size as usize],
}
}
ref other => {
log::warn!("null constant type {:?}", other);
return Err(Error::UnsupportedType(ty));
}
};
Ok(inner)
}
pub fn generate_default_built_in(
built_in: Option<crate::BuiltIn>,
ty: Handle<crate::Type>,
type_arena: &UniqueArena<crate::Type>,
constant_arena: &mut Arena<crate::Constant>,
span: crate::Span,
) -> Result<Handle<crate::Constant>, Error> {
let inner = match built_in {
Some(crate::BuiltIn::Position { .. }) => {
let zero = constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(0.0),
width: 4,
},
},
span,
);
let one = constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(1.0),
width: 4,
},
},
span,
);
crate::ConstantInner::Composite {
ty,
components: vec![zero, zero, zero, one],
}
}
Some(crate::BuiltIn::PointSize) => crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(1.0),
width: 4,
},
Some(crate::BuiltIn::FragDepth) => crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(0.0),
width: 4,
},
Some(crate::BuiltIn::SampleMask) => crate::ConstantInner::Scalar {
value: crate::ScalarValue::Uint(u64::MAX),
width: 4,
},
_ => generate_null_constant(ty, type_arena, constant_arena, span)?,
};
Ok(constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner,
},
span,
))
}