diff options
Diffstat (limited to 'third_party/rust/naga/src/front/spv/null.rs')
-rw-r--r-- | third_party/rust/naga/src/front/spv/null.rs | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/third_party/rust/naga/src/front/spv/null.rs b/third_party/rust/naga/src/front/spv/null.rs new file mode 100644 index 0000000000..85350c563e --- /dev/null +++ b/third_party/rust/naga/src/front/spv/null.rs @@ -0,0 +1,175 @@ +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, + } => { + // If we successfully declared a matrix type, we have declared a vector type for it too. + 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()); + // copy out the types to avoid borrowing `members` + 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) +} + +/// Create a default value for an output built-in. +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, + }, + //Note: `crate::BuiltIn::ClipDistance` is intentionally left for the default path + _ => generate_null_constant(ty, type_arena, constant_arena, span)?, + }; + Ok(constant_arena.fetch_or_append( + crate::Constant { + name: None, + specialization: None, + inner, + }, + span, + )) +} |