[naga] Introduce ScalarKind::AbstractInt and AbstractFloat.

Introduce new variants of `naga::ScalarKind`, `AbstractInt` and
`AbstractFloat`, for representing WGSL abstract types.
This commit is contained in:
Jim Blandy 2023-11-09 09:23:15 -08:00 committed by Teodor Tanasoaia
parent 723b8baf2a
commit 276c978b70
13 changed files with 95 additions and 16 deletions

View File

@ -3555,6 +3555,9 @@ impl<'a, W: Write> Writer<'a, W> {
(Sk::Sint | Sk::Uint | Sk::Float, Sk::Bool, None) => { (Sk::Sint | Sk::Uint | Sk::Float, Sk::Bool, None) => {
write!(self.out, "bool")? write!(self.out, "bool")?
} }
(Sk::AbstractInt | Sk::AbstractFloat, _, _)
| (_, Sk::AbstractInt | Sk::AbstractFloat, _) => unreachable!(),
}; };
write!(self.out, "(")?; write!(self.out, "(")?;
@ -4117,6 +4120,11 @@ impl<'a, W: Write> Writer<'a, W> {
crate::ScalarKind::Uint => write!(self.out, "0u")?, crate::ScalarKind::Uint => write!(self.out, "0u")?,
crate::ScalarKind::Float => write!(self.out, "0.0")?, crate::ScalarKind::Float => write!(self.out, "0.0")?,
crate::ScalarKind::Sint => write!(self.out, "0")?, crate::ScalarKind::Sint => write!(self.out, "0")?,
crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat => {
return Err(Error::Custom(
"Abstract types should not appear in IR presented to backends".to_string(),
))
}
} }
Ok(()) Ok(())
@ -4345,6 +4353,9 @@ const fn glsl_scalar(scalar: crate::Scalar) -> Result<ScalarString<'static>, Err
prefix: "b", prefix: "b",
full: "bool", full: "bool",
}, },
Sk::AbstractInt | Sk::AbstractFloat => {
return Err(Error::UnsupportedScalar(scalar));
}
}) })
} }

View File

@ -10,7 +10,7 @@ impl crate::ScalarKind {
Self::Float => "asfloat", Self::Float => "asfloat",
Self::Sint => "asint", Self::Sint => "asint",
Self::Uint => "asuint", Self::Uint => "asuint",
Self::Bool => unreachable!(), Self::Bool | Self::AbstractInt | Self::AbstractFloat => unreachable!(),
} }
} }
} }
@ -30,6 +30,9 @@ impl crate::Scalar {
_ => Err(Error::UnsupportedScalar(self)), _ => Err(Error::UnsupportedScalar(self)),
}, },
crate::ScalarKind::Bool => Ok("bool"), crate::ScalarKind::Bool => Ok("bool"),
crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat => {
Err(Error::UnsupportedScalar(self))
}
} }
} }
} }

View File

@ -338,6 +338,10 @@ impl crate::Scalar {
kind: Sk::Bool, kind: Sk::Bool,
width: _, width: _,
} => "bool", } => "bool",
Self {
kind: Sk::AbstractInt | Sk::AbstractFloat,
width: _,
} => unreachable!(),
} }
} }
} }

View File

@ -1175,7 +1175,7 @@ impl<'w> BlockContext<'w> {
let op = match src_scalar.kind { let op = match src_scalar.kind {
Sk::Sint | Sk::Uint => spirv::Op::INotEqual, Sk::Sint | Sk::Uint => spirv::Op::INotEqual,
Sk::Float => spirv::Op::FUnordNotEqual, Sk::Float => spirv::Op::FUnordNotEqual,
Sk::Bool => unreachable!(), Sk::Bool | Sk::AbstractInt | Sk::AbstractFloat => unreachable!(),
}; };
let zero_scalar_id = let zero_scalar_id =
self.writer.get_constant_scalar_with(0, src_scalar)?; self.writer.get_constant_scalar_with(0, src_scalar)?;

View File

@ -334,6 +334,10 @@ impl<'w> BlockContext<'w> {
(_, crate::ScalarKind::Bool | crate::ScalarKind::Float) => { (_, crate::ScalarKind::Bool | crate::ScalarKind::Float) => {
unreachable!("we don't allow bool or float for array index") unreachable!("we don't allow bool or float for array index")
} }
(crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat, _)
| (_, crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat) => {
unreachable!("abstract types should never reach backends")
}
}; };
let reconciled_array_index_id = if let Some(cast) = cast { let reconciled_array_index_id = if let Some(cast) = cast {
let component_ty_id = self.get_type_id(LookupType::Local(LocalType::Value { let component_ty_id = self.get_type_id(LookupType::Local(LocalType::Value {

View File

@ -824,6 +824,9 @@ impl Writer {
Instruction::type_float(id, bits) Instruction::type_float(id, bits)
} }
Sk::Bool => Instruction::type_bool(id), Sk::Bool => Instruction::type_bool(id),
Sk::AbstractInt | Sk::AbstractFloat => {
unreachable!("abstract types should never reach the backend");
}
} }
} }
@ -1591,6 +1594,11 @@ impl Writer {
| crate::TypeInner::Vector { scalar, .. } => match scalar.kind { | crate::TypeInner::Vector { scalar, .. } => match scalar.kind {
Sk::Uint | Sk::Sint | Sk::Bool => true, Sk::Uint | Sk::Sint | Sk::Bool => true,
Sk::Float => false, Sk::Float => false,
Sk::AbstractInt | Sk::AbstractFloat => {
return Err(Error::Validation(
"Abstract types should not appear in IR presented to backends",
))
}
}, },
_ => false, _ => false,
}; };

View File

@ -205,7 +205,7 @@ pub const fn type_power(scalar: Scalar) -> Option<u32> {
ScalarKind::Uint => 1, ScalarKind::Uint => 1,
ScalarKind::Float if scalar.width == 4 => 2, ScalarKind::Float if scalar.width == 4 => 2,
ScalarKind::Float => 3, ScalarKind::Float => 3,
ScalarKind::Bool => return None, ScalarKind::Bool | ScalarKind::AbstractInt | ScalarKind::AbstractFloat => return None,
}) })
} }

View File

@ -140,6 +140,8 @@ impl crate::Scalar {
crate::ScalarKind::Uint => "u", crate::ScalarKind::Uint => "u",
crate::ScalarKind::Float => "f", crate::ScalarKind::Float => "f",
crate::ScalarKind::Bool => return "bool".to_string(), crate::ScalarKind::Bool => return "bool".to_string(),
crate::ScalarKind::AbstractInt => return "{AbstractInt}".to_string(),
crate::ScalarKind::AbstractFloat => return "{AbstractFloat}".to_string(),
}; };
format!("{}{}", prefix, self.width * 8) format!("{}{}", prefix, self.width * 8)
} }

View File

@ -470,6 +470,16 @@ pub enum ScalarKind {
Float, Float,
/// Boolean type. /// Boolean type.
Bool, Bool,
/// WGSL abstract integer type.
///
/// These are forbidden by validation, and should never reach backends.
AbstractInt,
/// Abstract floating-point type.
///
/// These are forbidden by validation, and should never reach backends.
AbstractFloat,
} }
/// Characteristics of a scalar type. /// Characteristics of a scalar type.

View File

@ -71,7 +71,11 @@ impl From<super::StorageFormat> for super::ScalarKind {
impl super::ScalarKind { impl super::ScalarKind {
pub const fn is_numeric(self) -> bool { pub const fn is_numeric(self) -> bool {
match self { match self {
crate::ScalarKind::Sint | crate::ScalarKind::Uint | crate::ScalarKind::Float => true, crate::ScalarKind::Sint
| crate::ScalarKind::Uint
| crate::ScalarKind::Float
| crate::ScalarKind::AbstractInt
| crate::ScalarKind::AbstractFloat => true,
crate::ScalarKind::Bool => false, crate::ScalarKind::Bool => false,
} }
} }

View File

@ -670,7 +670,11 @@ impl super::Validator {
let good = match op { let good = match op {
Bo::Add | Bo::Subtract => match *left_inner { Bo::Add | Bo::Subtract => match *left_inner {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner, Sk::Uint
| Sk::Sint
| Sk::Float
| Sk::AbstractInt
| Sk::AbstractFloat => left_inner == right_inner,
Sk::Bool => false, Sk::Bool => false,
}, },
Ti::Matrix { .. } => left_inner == right_inner, Ti::Matrix { .. } => left_inner == right_inner,
@ -678,14 +682,24 @@ impl super::Validator {
}, },
Bo::Divide | Bo::Modulo => match *left_inner { Bo::Divide | Bo::Modulo => match *left_inner {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner, Sk::Uint
| Sk::Sint
| Sk::Float
| Sk::AbstractInt
| Sk::AbstractFloat => left_inner == right_inner,
Sk::Bool => false, Sk::Bool => false,
}, },
_ => false, _ => false,
}, },
Bo::Multiply => { Bo::Multiply => {
let kind_allowed = match left_inner.scalar_kind() { let kind_allowed = match left_inner.scalar_kind() {
Some(Sk::Uint | Sk::Sint | Sk::Float) => true, Some(
Sk::Uint
| Sk::Sint
| Sk::Float
| Sk::AbstractInt
| Sk::AbstractFloat,
) => true,
Some(Sk::Bool) | None => false, Some(Sk::Bool) | None => false,
}; };
let types_match = match (left_inner, right_inner) { let types_match = match (left_inner, right_inner) {
@ -762,7 +776,11 @@ impl super::Validator {
Bo::Less | Bo::LessEqual | Bo::Greater | Bo::GreaterEqual => { Bo::Less | Bo::LessEqual | Bo::Greater | Bo::GreaterEqual => {
match *left_inner { match *left_inner {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner, Sk::Uint
| Sk::Sint
| Sk::Float
| Sk::AbstractInt
| Sk::AbstractFloat => left_inner == right_inner,
Sk::Bool => false, Sk::Bool => false,
}, },
ref other => { ref other => {
@ -784,8 +802,10 @@ impl super::Validator {
}, },
Bo::And | Bo::InclusiveOr => match *left_inner { Bo::And | Bo::InclusiveOr => match *left_inner {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Bool | Sk::Sint | Sk::Uint => left_inner == right_inner, Sk::Bool | Sk::Sint | Sk::Uint | Sk::AbstractInt => {
Sk::Float => false, left_inner == right_inner
}
Sk::Float | Sk::AbstractFloat => false,
}, },
ref other => { ref other => {
log::error!("Op {:?} left type {:?}", op, other); log::error!("Op {:?} left type {:?}", op, other);
@ -794,8 +814,8 @@ impl super::Validator {
}, },
Bo::ExclusiveOr => match *left_inner { Bo::ExclusiveOr => match *left_inner {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Sint | Sk::Uint => left_inner == right_inner, Sk::Sint | Sk::Uint | Sk::AbstractInt => left_inner == right_inner,
Sk::Bool | Sk::Float => false, Sk::Bool | Sk::Float | Sk::AbstractFloat => false,
}, },
ref other => { ref other => {
log::error!("Op {:?} left type {:?}", op, other); log::error!("Op {:?} left type {:?}", op, other);
@ -823,8 +843,10 @@ impl super::Validator {
} }
}; };
match base_scalar.kind { match base_scalar.kind {
Sk::Sint | Sk::Uint => base_size.is_ok() && base_size == shift_size, Sk::Sint | Sk::Uint | Sk::AbstractInt => {
Sk::Float | Sk::Bool => false, base_size.is_ok() && base_size == shift_size
}
Sk::Float | Sk::AbstractFloat | Sk::Bool => false,
} }
} }
}; };

View File

@ -143,6 +143,9 @@ pub enum WidthError {
#[error("64-bit integers are not yet supported")] #[error("64-bit integers are not yet supported")]
Unsupported64Bit, Unsupported64Bit,
#[error("Abstract types may only appear in constant expressions")]
Abstract,
} }
// Only makes sense if `flags.contains(HOST_SHAREABLE)` // Only makes sense if `flags.contains(HOST_SHAREABLE)`
@ -248,6 +251,9 @@ impl super::Validator {
} }
scalar.width == 4 scalar.width == 4
} }
crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat => {
return Err(WidthError::Abstract);
}
}; };
if good { if good {
Ok(()) Ok(())
@ -325,7 +331,10 @@ impl super::Validator {
} }
Ti::Atomic(crate::Scalar { kind, width }) => { Ti::Atomic(crate::Scalar { kind, width }) => {
let good = match kind { let good = match kind {
crate::ScalarKind::Bool | crate::ScalarKind::Float => false, crate::ScalarKind::Bool
| crate::ScalarKind::Float
| crate::ScalarKind::AbstractInt
| crate::ScalarKind::AbstractFloat => false,
crate::ScalarKind::Sint | crate::ScalarKind::Uint => width == 4, crate::ScalarKind::Sint | crate::ScalarKind::Uint => width == 4,
}; };
if !good { if !good {

View File

@ -560,7 +560,9 @@ impl Resource {
} }
naga::ScalarKind::Sint => wgt::TextureSampleType::Sint, naga::ScalarKind::Sint => wgt::TextureSampleType::Sint,
naga::ScalarKind::Uint => wgt::TextureSampleType::Uint, naga::ScalarKind::Uint => wgt::TextureSampleType::Uint,
naga::ScalarKind::Bool => unreachable!(), naga::ScalarKind::AbstractInt
| naga::ScalarKind::AbstractFloat
| naga::ScalarKind::Bool => unreachable!(),
}, },
view_dimension, view_dimension,
multisampled: multi, multisampled: multi,