[naga] Introduce Scalar type to IR.

Introduce a new struct type, `Scalar`, combining a `ScalarKind` and a
`Bytes` width, and use this whenever such pairs of values are passed
around.

In particular, use `Scalar` in `TypeInner` variants `Scalar`, `Vector`,
`Atomic`, and `ValuePointer`.

Introduce associated `Scalar` constants `I32`, `U32`, `F32`, `BOOL`
and `F64`, for common cases.

Introduce a helper function `Scalar::float` for constructing `Float`
scalars of a given width, for dealing with `TypeInner::Matrix`, which
only supplies the scalar width of its elements, not a kind.

Introduce helper functions on `Literal` and `TypeInner`, to produce
the `Scalar` describing elements' values.

Use `Scalar` in `wgpu_core::validation::NumericType` as well.
This commit is contained in:
Jim Blandy 2023-11-10 12:31:29 -08:00 committed by Teodor Tanasoaia
parent 049cb75976
commit 9f91c95c24
55 changed files with 2350 additions and 2319 deletions

View File

@ -49,6 +49,10 @@ For naga changelogs at or before v0.14.0. See [naga's changelog](naga/CHANGELOG.
- Log vulkan validation layer messages during instance creation and destruction: By @exrook in [#4586](https://github.com/gfx-rs/wgpu/pull/4586)
- `TextureFormat::block_size` is deprecated, use `TextureFormat::block_copy_size` instead: By @wumpf in [#4647](https://github.com/gfx-rs/wgpu/pull/4647)
#### Naga
- Introduce a new `Scalar` struct type for use in Naga's IR, and update all frontend, middle, and backend code appropriately. By @jimblandy in [#4673](https://github.com/gfx-rs/wgpu/pull/4673).
### Bug Fixes
#### WGL

View File

@ -1,7 +1,7 @@
use super::{BackendResult, Error, Version, Writer};
use crate::{
AddressSpace, Binding, Bytes, Expression, Handle, ImageClass, ImageDimension, Interpolation,
Sampling, ScalarKind, ShaderStage, StorageFormat, Type, TypeInner,
AddressSpace, Binding, Expression, Handle, ImageClass, ImageDimension, Interpolation, Sampling,
Scalar, ScalarKind, ShaderStage, StorageFormat, Type, TypeInner,
};
use std::fmt::Write;
@ -275,10 +275,10 @@ impl<'a, W> Writer<'a, W> {
for (ty_handle, ty) in self.module.types.iter() {
match ty.inner {
TypeInner::Scalar { kind, width } => self.scalar_required_features(kind, width),
TypeInner::Vector { kind, width, .. } => self.scalar_required_features(kind, width),
TypeInner::Scalar(scalar) => self.scalar_required_features(scalar),
TypeInner::Vector { scalar, .. } => self.scalar_required_features(scalar),
TypeInner::Matrix { width, .. } => {
self.scalar_required_features(ScalarKind::Float, width)
self.scalar_required_features(Scalar::float(width))
}
TypeInner::Array { base, size, .. } => {
if let TypeInner::Array { .. } = self.module.types[base].inner {
@ -463,8 +463,8 @@ impl<'a, W> Writer<'a, W> {
}
/// Helper method that checks the [`Features`] needed by a scalar
fn scalar_required_features(&mut self, kind: ScalarKind, width: Bytes) {
if kind == ScalarKind::Float && width == 8 {
fn scalar_required_features(&mut self, scalar: Scalar) {
if scalar.kind == ScalarKind::Float && scalar.width == 8 {
self.features.request(Features::DOUBLE_TYPE);
}
}

View File

@ -471,8 +471,8 @@ pub enum Error {
#[error("A call was made to an unsupported external: {0}")]
UnsupportedExternal(String),
/// A scalar with an unsupported width was requested.
#[error("A scalar with an unsupported width was requested: {0:?} {1:?}")]
UnsupportedScalar(crate::ScalarKind, crate::Bytes),
#[error("A scalar with an unsupported width was requested: {0:?}")]
UnsupportedScalar(crate::Scalar),
/// A image was used with multiple samplers, which isn't supported.
#[error("A image was used with multiple samplers")]
ImageMultipleSamplers,
@ -963,27 +963,20 @@ impl<'a, W: Write> Writer<'a, W> {
fn write_value_type(&mut self, inner: &TypeInner) -> BackendResult {
match *inner {
// Scalars are simple we just get the full name from `glsl_scalar`
TypeInner::Scalar { kind, width }
| TypeInner::Atomic { kind, width }
TypeInner::Scalar(scalar)
| TypeInner::Atomic(scalar)
| TypeInner::ValuePointer {
size: None,
kind,
width,
scalar,
space: _,
} => write!(self.out, "{}", glsl_scalar(kind, width)?.full)?,
} => write!(self.out, "{}", glsl_scalar(scalar)?.full)?,
// Vectors are just `gvecN` where `g` is the scalar prefix and `N` is the vector size
TypeInner::Vector { size, kind, width }
TypeInner::Vector { size, scalar }
| TypeInner::ValuePointer {
size: Some(size),
kind,
width,
scalar,
space: _,
} => write!(
self.out,
"{}vec{}",
glsl_scalar(kind, width)?.prefix,
size as u8
)?,
} => write!(self.out, "{}vec{}", glsl_scalar(scalar)?.prefix, size as u8)?,
// Matrices are written with `gmatMxN` where `g` is the scalar prefix (only floats and
// doubles are allowed), `M` is the columns count and `N` is the rows count
//
@ -996,7 +989,7 @@ impl<'a, W: Write> Writer<'a, W> {
} => write!(
self.out,
"{}mat{}x{}",
glsl_scalar(crate::ScalarKind::Float, width)?.prefix,
glsl_scalar(crate::Scalar::float(width))?.prefix,
columns as u8,
rows as u8
)?,
@ -1083,7 +1076,7 @@ impl<'a, W: Write> Writer<'a, W> {
self.out,
"{}{}{}{}{}{}{}",
precision,
glsl_scalar(kind, 4)?.prefix,
glsl_scalar(crate::Scalar { kind, width: 4 })?.prefix,
base,
glsl_dimension(dim),
ms,
@ -1278,7 +1271,7 @@ impl<'a, W: Write> Writer<'a, W> {
crate::MathFunction::Dot => {
// if the expression is a Dot product with integer arguments,
// then the args needs baking as well
if let TypeInner::Scalar { kind, .. } = *inner {
if let TypeInner::Scalar(crate::Scalar { kind, .. }) = *inner {
match kind {
crate::ScalarKind::Sint | crate::ScalarKind::Uint => {
self.need_bake_expressions.insert(arg);
@ -2802,10 +2795,10 @@ impl<'a, W: Write> Writer<'a, W> {
if let Some(expr) = level {
let cast_to_int = matches!(
*ctx.resolve_type(expr, &self.module.types),
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Uint,
..
}
})
);
write!(self.out, ", ")?;
@ -2906,19 +2899,19 @@ impl<'a, W: Write> Writer<'a, W> {
let right_inner = ctx.resolve_type(right, &self.module.types);
let function = match (left_inner, right_inner) {
(&Ti::Vector { kind, .. }, &Ti::Vector { .. }) => match op {
(&Ti::Vector { scalar, .. }, &Ti::Vector { .. }) => match op {
Bo::Less
| Bo::LessEqual
| Bo::Greater
| Bo::GreaterEqual
| Bo::Equal
| Bo::NotEqual => BinaryOperation::VectorCompare,
Bo::Modulo if kind == Sk::Float => BinaryOperation::Modulo,
Bo::And if kind == Sk::Bool => {
Bo::Modulo if scalar.kind == Sk::Float => BinaryOperation::Modulo,
Bo::And if scalar.kind == Sk::Bool => {
op = crate::BinaryOperator::LogicalAnd;
BinaryOperation::VectorComponentWise
}
Bo::InclusiveOr if kind == Sk::Bool => {
Bo::InclusiveOr if scalar.kind == Sk::Bool => {
op = crate::BinaryOperator::LogicalOr;
BinaryOperation::VectorComponentWise
}
@ -3171,7 +3164,11 @@ impl<'a, W: Write> Writer<'a, W> {
// geometry
Mf::Dot => match *ctx.resolve_type(arg, &self.module.types) {
crate::TypeInner::Vector {
kind: crate::ScalarKind::Float,
scalar:
crate::Scalar {
kind: crate::ScalarKind::Float,
..
},
..
} => "dot",
crate::TypeInner::Vector { size, .. } => {
@ -3226,9 +3223,9 @@ impl<'a, W: Write> Writer<'a, W> {
// bits
Mf::CountTrailingZeros => {
match *ctx.resolve_type(arg, &self.module.types) {
crate::TypeInner::Vector { size, kind, .. } => {
crate::TypeInner::Vector { size, scalar, .. } => {
let s = back::vector_size_str(size);
if let crate::ScalarKind::Uint = kind {
if let crate::ScalarKind::Uint = scalar.kind {
write!(self.out, "min(uvec{s}(findLSB(")?;
self.write_expr(arg, ctx)?;
write!(self.out, ")), uvec{s}(32u))")?;
@ -3238,8 +3235,8 @@ impl<'a, W: Write> Writer<'a, W> {
write!(self.out, ")), uvec{s}(32u)))")?;
}
}
crate::TypeInner::Scalar { kind, .. } => {
if let crate::ScalarKind::Uint = kind {
crate::TypeInner::Scalar(scalar) => {
if let crate::ScalarKind::Uint = scalar.kind {
write!(self.out, "min(uint(findLSB(")?;
self.write_expr(arg, ctx)?;
write!(self.out, ")), 32u)")?;
@ -3256,10 +3253,10 @@ impl<'a, W: Write> Writer<'a, W> {
Mf::CountLeadingZeros => {
if self.options.version.supports_integer_functions() {
match *ctx.resolve_type(arg, &self.module.types) {
crate::TypeInner::Vector { size, kind, .. } => {
crate::TypeInner::Vector { size, scalar } => {
let s = back::vector_size_str(size);
if let crate::ScalarKind::Uint = kind {
if let crate::ScalarKind::Uint = scalar.kind {
write!(self.out, "uvec{s}(ivec{s}(31) - findMSB(")?;
self.write_expr(arg, ctx)?;
write!(self.out, "))")?;
@ -3271,8 +3268,8 @@ impl<'a, W: Write> Writer<'a, W> {
write!(self.out, ", ivec{s}(0)))")?;
}
}
crate::TypeInner::Scalar { kind, .. } => {
if let crate::ScalarKind::Uint = kind {
crate::TypeInner::Scalar(scalar) => {
if let crate::ScalarKind::Uint = scalar.kind {
write!(self.out, "uint(31 - findMSB(")?;
} else {
write!(self.out, "(")?;
@ -3287,10 +3284,10 @@ impl<'a, W: Write> Writer<'a, W> {
};
} else {
match *ctx.resolve_type(arg, &self.module.types) {
crate::TypeInner::Vector { size, kind, .. } => {
crate::TypeInner::Vector { size, scalar } => {
let s = back::vector_size_str(size);
if let crate::ScalarKind::Uint = kind {
if let crate::ScalarKind::Uint = scalar.kind {
write!(self.out, "uvec{s}(")?;
write!(self.out, "vec{s}(31.0) - floor(log2(vec{s}(")?;
self.write_expr(arg, ctx)?;
@ -3305,8 +3302,8 @@ impl<'a, W: Write> Writer<'a, W> {
write!(self.out, ", ivec{s}(0u))))")?;
}
}
crate::TypeInner::Scalar { kind, .. } => {
if let crate::ScalarKind::Uint = kind {
crate::TypeInner::Scalar(scalar) => {
if let crate::ScalarKind::Uint = scalar.kind {
write!(self.out, "uint(31.0 - floor(log2(float(")?;
self.write_expr(arg, ctx)?;
write!(self.out, ") + 0.5)))")?;
@ -3360,14 +3357,17 @@ impl<'a, W: Write> Writer<'a, W> {
// Check if the argument is an unsigned integer and return the vector size
// in case it's a vector
let maybe_uint_size = match *ctx.resolve_type(arg, &self.module.types) {
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Uint,
..
} => Some(None),
}) => Some(None),
crate::TypeInner::Vector {
kind: crate::ScalarKind::Uint,
scalar:
crate::Scalar {
kind: crate::ScalarKind::Uint,
..
},
size,
..
} => Some(Some(size)),
_ => None,
};
@ -3450,7 +3450,10 @@ impl<'a, W: Write> Writer<'a, W> {
match convert {
Some(width) => {
// this is similar to `write_type`, but with the target kind
let scalar = glsl_scalar(target_kind, width)?;
let scalar = glsl_scalar(crate::Scalar {
kind: target_kind,
width,
})?;
match *inner {
TypeInner::Matrix { columns, rows, .. } => write!(
self.out,
@ -3471,10 +3474,12 @@ impl<'a, W: Write> Writer<'a, W> {
use crate::ScalarKind as Sk;
let target_vector_type = match *inner {
TypeInner::Vector { size, width, .. } => Some(TypeInner::Vector {
TypeInner::Vector { size, scalar } => Some(TypeInner::Vector {
size,
width,
kind: target_kind,
scalar: crate::Scalar {
kind: target_kind,
width: scalar.width,
},
}),
_ => None,
};
@ -3613,14 +3618,17 @@ impl<'a, W: Write> Writer<'a, W> {
// Otherwise write just the expression (and the 1D hack if needed)
None => {
let uvec_size = match *ctx.resolve_type(coordinate, &self.module.types) {
TypeInner::Scalar {
TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Uint,
..
} => Some(None),
}) => Some(None),
TypeInner::Vector {
size,
kind: crate::ScalarKind::Uint,
..
scalar:
crate::Scalar {
kind: crate::ScalarKind::Uint,
..
},
} => Some(Some(size as u32)),
_ => None,
};
@ -3953,7 +3961,11 @@ impl<'a, W: Write> Writer<'a, W> {
// End the first branch
write!(self.out, " : ")?;
// Write the 0 value
write!(self.out, "{}vec4(", glsl_scalar(kind, 4)?.prefix,)?;
write!(
self.out,
"{}vec4(",
glsl_scalar(crate::Scalar { kind, width: 4 })?.prefix,
)?;
self.write_zero_init_scalar(kind)?;
// Close the zero value constructor
write!(self.out, ")")?;
@ -4006,13 +4018,13 @@ impl<'a, W: Write> Writer<'a, W> {
fn write_zero_init_value(&mut self, ty: Handle<crate::Type>) -> BackendResult {
let inner = &self.module.types[ty].inner;
match *inner {
TypeInner::Scalar { kind, .. } | TypeInner::Atomic { kind, .. } => {
self.write_zero_init_scalar(kind)?;
TypeInner::Scalar(scalar) | TypeInner::Atomic(scalar) => {
self.write_zero_init_scalar(scalar.kind)?;
}
TypeInner::Vector { kind, .. } => {
TypeInner::Vector { scalar, .. } => {
self.write_value_type(inner)?;
write!(self.out, "(")?;
self.write_zero_init_scalar(kind)?;
self.write_zero_init_scalar(scalar.kind)?;
write!(self.out, ")")?;
}
TypeInner::Matrix { .. } => {
@ -4265,13 +4277,10 @@ struct ScalarString<'a> {
///
/// # Errors
/// If a [`Float`](crate::ScalarKind::Float) with an width that isn't 4 or 8
const fn glsl_scalar(
kind: crate::ScalarKind,
width: crate::Bytes,
) -> Result<ScalarString<'static>, Error> {
const fn glsl_scalar(scalar: crate::Scalar) -> Result<ScalarString<'static>, Error> {
use crate::ScalarKind as Sk;
Ok(match kind {
Ok(match scalar.kind {
Sk::Sint => ScalarString {
prefix: "i",
full: "int",
@ -4280,7 +4289,7 @@ const fn glsl_scalar(
prefix: "u",
full: "uint",
},
Sk::Float => match width {
Sk::Float => match scalar.width {
4 => ScalarString {
prefix: "",
full: "float",
@ -4289,7 +4298,7 @@ const fn glsl_scalar(
prefix: "d",
full: "double",
},
_ => return Err(Error::UnsupportedScalar(kind, width)),
_ => return Err(Error::UnsupportedScalar(scalar)),
},
Sk::Bool => ScalarString {
prefix: "b",

View File

@ -13,21 +13,23 @@ impl crate::ScalarKind {
Self::Bool => unreachable!(),
}
}
}
impl crate::Scalar {
/// Helper function that returns scalar related strings
///
/// <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-scalar>
pub(super) const fn to_hlsl_str(self, width: crate::Bytes) -> Result<&'static str, Error> {
match self {
Self::Sint => Ok("int"),
Self::Uint => Ok("uint"),
Self::Float => match width {
pub(super) const fn to_hlsl_str(self) -> Result<&'static str, Error> {
match self.kind {
crate::ScalarKind::Sint => Ok("int"),
crate::ScalarKind::Uint => Ok("uint"),
crate::ScalarKind::Float => match self.width {
2 => Ok("half"),
4 => Ok("float"),
8 => Ok("double"),
_ => Err(Error::UnsupportedScalar(self, width)),
_ => Err(Error::UnsupportedScalar(self)),
},
Self::Bool => Ok("bool"),
crate::ScalarKind::Bool => Ok("bool"),
}
}
}
@ -71,10 +73,10 @@ impl crate::TypeInner {
names: &'a crate::FastHashMap<crate::proc::NameKey, String>,
) -> Result<Cow<'a, str>, Error> {
Ok(match gctx.types[base].inner {
crate::TypeInner::Scalar { kind, width } => Cow::Borrowed(kind.to_hlsl_str(width)?),
crate::TypeInner::Vector { size, kind, width } => Cow::Owned(format!(
crate::TypeInner::Scalar(scalar) => Cow::Borrowed(scalar.to_hlsl_str()?),
crate::TypeInner::Vector { size, scalar } => Cow::Owned(format!(
"{}{}",
kind.to_hlsl_str(width)?,
scalar.to_hlsl_str()?,
crate::back::vector_size_str(size)
)),
crate::TypeInner::Matrix {
@ -83,7 +85,7 @@ impl crate::TypeInner {
width,
} => Cow::Owned(format!(
"{}{}x{}",
crate::ScalarKind::Float.to_hlsl_str(width)?,
crate::Scalar::float(width).to_hlsl_str()?,
crate::back::vector_size_str(columns),
crate::back::vector_size_str(rows),
)),

View File

@ -133,7 +133,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
}
crate::ImageClass::Sampled { kind, multi } => {
let multi_str = if multi { "MS" } else { "" };
let scalar_kind_str = kind.to_hlsl_str(4)?;
let scalar_kind_str = crate::Scalar { kind, width: 4 }.to_hlsl_str()?;
write!(self.out, "{multi_str}<{scalar_kind_str}4>")?
}
crate::ImageClass::Storage { format, .. } => {
@ -658,8 +658,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
let vec_ty = match module.types[member.ty].inner {
crate::TypeInner::Matrix { rows, width, .. } => crate::TypeInner::Vector {
size: rows,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
},
_ => unreachable!(),
};
@ -737,10 +736,9 @@ impl<'a, W: Write> super::Writer<'a, W> {
_ => unreachable!(),
};
let scalar_ty = match module.types[member.ty].inner {
crate::TypeInner::Matrix { width, .. } => crate::TypeInner::Scalar {
kind: crate::ScalarKind::Float,
width,
},
crate::TypeInner::Matrix { width, .. } => {
crate::TypeInner::Scalar(crate::Scalar::float(width))
}
_ => unreachable!(),
};
self.write_value_type(module, &scalar_ty)?;

View File

@ -241,8 +241,8 @@ pub struct ReflectionInfo {
pub enum Error {
#[error(transparent)]
IoError(#[from] FmtError),
#[error("A scalar with an unsupported width was requested: {0:?} {1:?}")]
UnsupportedScalar(crate::ScalarKind, crate::Bytes),
#[error("A scalar with an unsupported width was requested: {0:?}")]
UnsupportedScalar(crate::Scalar),
#[error("{0}")]
Unimplemented(String), // TODO: Error used only during development
#[error("{0}")]

View File

@ -157,25 +157,21 @@ impl<W: fmt::Write> super::Writer<'_, W> {
func_ctx: &FunctionCtx,
) -> BackendResult {
match *result_ty.inner_with(&module.types) {
crate::TypeInner::Scalar { kind, width: _ } => {
crate::TypeInner::Scalar(scalar) => {
// working around the borrow checker in `self.write_expr`
let chain = mem::take(&mut self.temp_access_chain);
let var_name = &self.names[&NameKey::GlobalVariable(var_handle)];
let cast = kind.to_hlsl_cast();
let cast = scalar.kind.to_hlsl_cast();
write!(self.out, "{cast}({var_name}.Load(")?;
self.write_storage_address(module, &chain, func_ctx)?;
write!(self.out, "))")?;
self.temp_access_chain = chain;
}
crate::TypeInner::Vector {
size,
kind,
width: _,
} => {
crate::TypeInner::Vector { size, scalar } => {
// working around the borrow checker in `self.write_expr`
let chain = mem::take(&mut self.temp_access_chain);
let var_name = &self.names[&NameKey::GlobalVariable(var_handle)];
let cast = kind.to_hlsl_cast();
let cast = scalar.kind.to_hlsl_cast();
write!(self.out, "{}({}.Load{}(", cast, var_name, size as u8)?;
self.write_storage_address(module, &chain, func_ctx)?;
write!(self.out, "))")?;
@ -189,7 +185,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
write!(
self.out,
"{}{}x{}(",
crate::ScalarKind::Float.to_hlsl_str(width)?,
crate::Scalar::float(width).to_hlsl_str()?,
columns as u8,
rows as u8,
)?;
@ -199,8 +195,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
let iter = (0..columns as u32).map(|i| {
let ty_inner = crate::TypeInner::Vector {
size: rows,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
};
(TypeResolution::Value(ty_inner), i * row_stride)
});
@ -296,7 +291,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
}
};
match *ty_resolution.inner_with(&module.types) {
crate::TypeInner::Scalar { .. } => {
crate::TypeInner::Scalar(_) => {
// working around the borrow checker in `self.write_expr`
let chain = mem::take(&mut self.temp_access_chain);
let var_name = &self.names[&NameKey::GlobalVariable(var_handle)];
@ -330,7 +325,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
self.out,
"{}{}{}x{} {}{} = ",
level.next(),
crate::ScalarKind::Float.to_hlsl_str(width)?,
crate::Scalar::float(width).to_hlsl_str()?,
columns as u8,
rows as u8,
STORE_TEMP_NAME,
@ -348,8 +343,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
.push(SubAccess::Offset(i * row_stride));
let ty_inner = crate::TypeInner::Vector {
size: rows,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
};
let sv = StoreValue::TempIndex {
depth,
@ -470,8 +464,8 @@ impl<W: fmt::Write> super::Writer<'_, W> {
crate::TypeInner::Pointer { base, .. } => match module.types[base].inner {
crate::TypeInner::Struct { ref members, .. } => Parent::Struct(members),
crate::TypeInner::Array { stride, .. } => Parent::Array { stride },
crate::TypeInner::Vector { width, .. } => Parent::Array {
stride: width as u32,
crate::TypeInner::Vector { scalar, .. } => Parent::Array {
stride: scalar.width as u32,
},
crate::TypeInner::Matrix { rows, width, .. } => Parent::Array {
// The stride between matrices is the count of rows as this is how
@ -480,8 +474,8 @@ impl<W: fmt::Write> super::Writer<'_, W> {
},
_ => unreachable!(),
},
crate::TypeInner::ValuePointer { width, .. } => Parent::Array {
stride: width as u32,
crate::TypeInner::ValuePointer { scalar, .. } => Parent::Array {
stride: scalar.width as u32,
},
_ => unreachable!(),
};

View File

@ -912,8 +912,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
} if member.binding.is_none() && rows == crate::VectorSize::Bi => {
let vec_ty = crate::TypeInner::Vector {
size: rows,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
};
let field_name_key = NameKey::StructMember(handle, index as u32);
@ -1024,14 +1023,14 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
/// Adds no trailing or leading whitespace
pub(super) fn write_value_type(&mut self, module: &Module, inner: &TypeInner) -> BackendResult {
match *inner {
TypeInner::Scalar { kind, width } | TypeInner::Atomic { kind, width } => {
write!(self.out, "{}", kind.to_hlsl_str(width)?)?;
TypeInner::Scalar(scalar) | TypeInner::Atomic(scalar) => {
write!(self.out, "{}", scalar.to_hlsl_str()?)?;
}
TypeInner::Vector { size, kind, width } => {
TypeInner::Vector { size, scalar } => {
write!(
self.out,
"{}{}",
kind.to_hlsl_str(width)?,
scalar.to_hlsl_str()?,
back::vector_size_str(size)
)?;
}
@ -1047,7 +1046,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
write!(
self.out,
"{}{}x{}",
crate::ScalarKind::Float.to_hlsl_str(width)?,
crate::Scalar::float(width).to_hlsl_str()?,
back::vector_size_str(columns),
back::vector_size_str(rows),
)?;
@ -2484,7 +2483,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
write!(self.out, ")")?;
// return x component if return type is scalar
if let TypeInner::Scalar { .. } = *func_ctx.resolve_type(expr, &module.types) {
if let TypeInner::Scalar(_) = *func_ctx.resolve_type(expr, &module.types) {
write!(self.out, ".x")?;
}
}
@ -2567,23 +2566,27 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
let inner = func_ctx.resolve_type(expr, &module.types);
match convert {
Some(dst_width) => {
let scalar = crate::Scalar {
kind,
width: dst_width,
};
match *inner {
TypeInner::Vector { size, .. } => {
write!(
self.out,
"{}{}(",
kind.to_hlsl_str(dst_width)?,
scalar.to_hlsl_str()?,
back::vector_size_str(size)
)?;
}
TypeInner::Scalar { .. } => {
write!(self.out, "{}(", kind.to_hlsl_str(dst_width)?,)?;
TypeInner::Scalar(_) => {
write!(self.out, "{}(", scalar.to_hlsl_str()?,)?;
}
TypeInner::Matrix { columns, rows, .. } => {
write!(
self.out,
"{}{}x{}(",
kind.to_hlsl_str(dst_width)?,
scalar.to_hlsl_str()?,
back::vector_size_str(columns),
back::vector_size_str(rows)
)?;
@ -2964,14 +2967,14 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
Function::CountTrailingZeros => {
match *func_ctx.resolve_type(arg, &module.types) {
TypeInner::Vector { size, kind, .. } => {
TypeInner::Vector { size, scalar } => {
let s = match size {
crate::VectorSize::Bi => ".xx",
crate::VectorSize::Tri => ".xxx",
crate::VectorSize::Quad => ".xxxx",
};
if let ScalarKind::Uint = kind {
if let ScalarKind::Uint = scalar.kind {
write!(self.out, "min((32u){s}, firstbitlow(")?;
self.write_expr(module, arg, func_ctx)?;
write!(self.out, "))")?;
@ -2981,8 +2984,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
write!(self.out, ")))")?;
}
}
TypeInner::Scalar { kind, .. } => {
if let ScalarKind::Uint = kind {
TypeInner::Scalar(scalar) => {
if let ScalarKind::Uint = scalar.kind {
write!(self.out, "min(32u, firstbitlow(")?;
self.write_expr(module, arg, func_ctx)?;
write!(self.out, "))")?;
@ -2999,14 +3002,14 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
Function::CountLeadingZeros => {
match *func_ctx.resolve_type(arg, &module.types) {
TypeInner::Vector { size, kind, .. } => {
TypeInner::Vector { size, scalar } => {
let s = match size {
crate::VectorSize::Bi => ".xx",
crate::VectorSize::Tri => ".xxx",
crate::VectorSize::Quad => ".xxxx",
};
if let ScalarKind::Uint = kind {
if let ScalarKind::Uint = scalar.kind {
write!(self.out, "((31u){s} - firstbithigh(")?;
self.write_expr(module, arg, func_ctx)?;
write!(self.out, "))")?;
@ -3021,8 +3024,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
write!(self.out, ")))")?;
}
}
TypeInner::Scalar { kind, .. } => {
if let ScalarKind::Uint = kind {
TypeInner::Scalar(scalar) => {
if let ScalarKind::Uint = scalar.kind {
write!(self.out, "(31u - firstbithigh(")?;
self.write_expr(module, arg, func_ctx)?;
write!(self.out, "))")?;

View File

@ -45,28 +45,28 @@ pub(crate) const FREXP_FUNCTION: &str = "naga_frexp";
/// - A two element slice `[ROWS COLUMNS]` produces a matrix of the given size.
fn put_numeric_type(
out: &mut impl Write,
kind: crate::ScalarKind,
scalar: crate::Scalar,
sizes: &[crate::VectorSize],
) -> Result<(), FmtError> {
match (kind, sizes) {
(kind, &[]) => {
write!(out, "{}", kind.to_msl_name())
match (scalar, sizes) {
(scalar, &[]) => {
write!(out, "{}", scalar.to_msl_name())
}
(kind, &[rows]) => {
(scalar, &[rows]) => {
write!(
out,
"{}::{}{}",
NAMESPACE,
kind.to_msl_name(),
scalar.to_msl_name(),
back::vector_size_str(rows)
)
}
(kind, &[rows, columns]) => {
(scalar, &[rows, columns]) => {
write!(
out,
"{}::{}{}x{}",
NAMESPACE,
kind.to_msl_name(),
scalar.to_msl_name(),
back::vector_size_str(columns),
back::vector_size_str(rows)
)
@ -96,13 +96,13 @@ impl<'a> Display for TypeContext<'a> {
}
match ty.inner {
crate::TypeInner::Scalar { kind, .. } => put_numeric_type(out, kind, &[]),
crate::TypeInner::Atomic { kind, .. } => {
write!(out, "{}::atomic_{}", NAMESPACE, kind.to_msl_name())
crate::TypeInner::Scalar(scalar) => put_numeric_type(out, scalar, &[]),
crate::TypeInner::Atomic(scalar) => {
write!(out, "{}::atomic_{}", NAMESPACE, scalar.to_msl_name())
}
crate::TypeInner::Vector { size, kind, .. } => put_numeric_type(out, kind, &[size]),
crate::TypeInner::Vector { size, scalar } => put_numeric_type(out, scalar, &[size]),
crate::TypeInner::Matrix { columns, rows, .. } => {
put_numeric_type(out, crate::ScalarKind::Float, &[rows, columns])
put_numeric_type(out, crate::Scalar::F32, &[rows, columns])
}
crate::TypeInner::Pointer { base, space } => {
let sub = Self {
@ -118,8 +118,7 @@ impl<'a> Display for TypeContext<'a> {
}
crate::TypeInner::ValuePointer {
size,
kind,
width: _,
scalar,
space,
} => {
match space.to_msl_name() {
@ -127,8 +126,8 @@ impl<'a> Display for TypeContext<'a> {
None => return Ok(()),
};
match size {
Some(rows) => put_numeric_type(out, kind, &[rows])?,
None => put_numeric_type(out, kind, &[])?,
Some(rows) => put_numeric_type(out, scalar, &[rows])?,
None => put_numeric_type(out, scalar, &[])?,
};
write!(out, "&")
@ -194,7 +193,7 @@ impl<'a> Display for TypeContext<'a> {
("texture", "", format.into(), access)
}
};
let base_name = kind.to_msl_name();
let base_name = crate::Scalar { kind, width: 4 }.to_msl_name();
let array_str = if arrayed { "_array" } else { "" };
write!(
out,
@ -319,13 +318,26 @@ pub struct Writer<W> {
struct_member_pads: FastHashSet<(Handle<crate::Type>, u32)>,
}
impl crate::ScalarKind {
impl crate::Scalar {
const fn to_msl_name(self) -> &'static str {
use crate::ScalarKind as Sk;
match self {
Self::Float => "float",
Self::Sint => "int",
Self::Uint => "uint",
Self::Bool => "bool",
Self {
kind: Sk::Float,
width: _,
} => "float",
Self {
kind: Sk::Sint,
width: _,
} => "int",
Self {
kind: Sk::Uint,
width: _,
} => "uint",
Self {
kind: Sk::Bool,
width: _,
} => "bool",
}
}
}
@ -343,7 +355,7 @@ fn should_pack_struct_member(
span: u32,
index: usize,
module: &crate::Module,
) -> Option<crate::ScalarKind> {
) -> Option<crate::Scalar> {
let member = &members[index];
//Note: this is imperfect - the same structure can be used for host-shared
// things, where packed float would matter.
@ -362,9 +374,8 @@ fn should_pack_struct_member(
match *ty_inner {
crate::TypeInner::Vector {
size: crate::VectorSize::Tri,
width: 4,
kind,
} if member.offset & 0xF != 0 || is_tight => Some(kind),
scalar: scalar @ crate::Scalar { width: 4, .. },
} if member.offset & 0xF != 0 || is_tight => Some(scalar),
_ => None,
}
}
@ -442,10 +453,10 @@ impl crate::Type {
match self.inner {
// value types are concise enough, we only alias them if they are named
Ti::Scalar { .. }
Ti::Scalar(_)
| Ti::Vector { .. }
| Ti::Matrix { .. }
| Ti::Atomic { .. }
| Ti::Atomic(_)
| Ti::Pointer { .. }
| Ti::ValuePointer { .. } => self.name.is_some(),
// composite types are better to be aliased, regardless of the name
@ -549,10 +560,7 @@ impl<'a> ExpressionContext<'a> {
index::access_needs_check(base, index, self.module, self.function, self.info)
}
fn get_packed_vec_kind(
&self,
expr_handle: Handle<crate::Expression>,
) -> Option<crate::ScalarKind> {
fn get_packed_vec_kind(&self, expr_handle: Handle<crate::Expression>) -> Option<crate::Scalar> {
match self.function.expressions[expr_handle] {
crate::Expression::AccessIndex { base, index } => {
let ty = match *self.resolve_type(base) {
@ -673,7 +681,8 @@ impl<W: Write> Writer<W> {
crate::TypeInner::Image { dim, .. } => dim,
ref other => unreachable!("Unexpected type {:?}", other),
};
let coordinate_type = kind.to_msl_name();
let scalar = crate::Scalar { kind, width: 4 };
let coordinate_type = scalar.to_msl_name();
match dim {
crate::ImageDimension::D1 => {
// Since 1D textures never have mipmaps, MSL requires that the
@ -721,11 +730,11 @@ impl<W: Write> Writer<W> {
) -> BackendResult {
// coordinates in IR are int, but Metal expects uint
match *context.resolve_type(expr) {
crate::TypeInner::Scalar { .. } => {
put_numeric_type(&mut self.out, crate::ScalarKind::Uint, &[])?
crate::TypeInner::Scalar(_) => {
put_numeric_type(&mut self.out, crate::Scalar::U32, &[])?
}
crate::TypeInner::Vector { size, .. } => {
put_numeric_type(&mut self.out, crate::ScalarKind::Uint, &[size])?
put_numeric_type(&mut self.out, crate::Scalar::U32, &[size])?
}
_ => return Err(Error::Validation),
};
@ -1299,7 +1308,7 @@ impl<W: Write> Writer<W> {
};
write!(self.out, "{ty_name}")?;
match module.types[ty].inner {
crate::TypeInner::Scalar { .. }
crate::TypeInner::Scalar(_)
| crate::TypeInner::Vector { .. }
| crate::TypeInner::Matrix { .. } => {
self.put_call_parameters_impl(
@ -1326,11 +1335,11 @@ impl<W: Write> Writer<W> {
}
}
crate::Expression::Splat { size, value } => {
let scalar_kind = match *get_expr_ty(ctx, value).inner_with(&module.types) {
crate::TypeInner::Scalar { kind, .. } => kind,
let scalar = match *get_expr_ty(ctx, value).inner_with(&module.types) {
crate::TypeInner::Scalar(scalar) => scalar,
_ => return Err(Error::Validation),
};
put_numeric_type(&mut self.out, scalar_kind, &[size])?;
put_numeric_type(&mut self.out, scalar, &[size])?;
write!(self.out, "(")?;
put_expression(self, ctx, value)?;
write!(self.out, ")")?;
@ -1626,10 +1635,10 @@ impl<W: Write> Writer<W> {
accept,
reject,
} => match *context.resolve_type(condition) {
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Bool,
..
} => {
}) => {
if !is_scoped {
write!(self.out, "(")?;
}
@ -1643,7 +1652,11 @@ impl<W: Write> Writer<W> {
}
}
crate::TypeInner::Vector {
kind: crate::ScalarKind::Bool,
scalar:
crate::Scalar {
kind: crate::ScalarKind::Bool,
..
},
..
} => {
write!(self.out, "{NAMESPACE}::select(")?;
@ -1687,7 +1700,7 @@ impl<W: Write> Writer<W> {
let arg_type = context.resolve_type(arg);
let scalar_argument = match arg_type {
&crate::TypeInner::Scalar { .. } => true,
&crate::TypeInner::Scalar(_) => true,
_ => false,
};
@ -1732,7 +1745,11 @@ impl<W: Write> Writer<W> {
// geometry
Mf::Dot => match *context.resolve_type(arg) {
crate::TypeInner::Vector {
kind: crate::ScalarKind::Float,
scalar:
crate::Scalar {
kind: crate::ScalarKind::Float,
..
},
..
} => "dot",
crate::TypeInner::Vector { size, .. } => {
@ -1838,16 +1855,16 @@ impl<W: Write> Writer<W> {
// or metal will complain that select is ambiguous
match *inner {
crate::TypeInner::Vector { size, kind, .. } => {
crate::TypeInner::Vector { size, scalar } => {
let size = back::vector_size_str(size);
if let crate::ScalarKind::Sint = kind {
if let crate::ScalarKind::Sint = scalar.kind {
write!(self.out, "int{size}")?;
} else {
write!(self.out, "uint{size}")?;
}
}
crate::TypeInner::Scalar { kind, .. } => {
if let crate::ScalarKind::Sint = kind {
crate::TypeInner::Scalar(scalar) => {
if let crate::ScalarKind::Sint = scalar.kind {
write!(self.out, "int")?;
} else {
write!(self.out, "uint")?;
@ -1893,19 +1910,15 @@ impl<W: Write> Writer<W> {
kind,
convert,
} => match *context.resolve_type(expr) {
crate::TypeInner::Scalar {
kind: src_kind,
width: src_width,
}
| crate::TypeInner::Vector {
kind: src_kind,
width: src_width,
..
} => {
crate::TypeInner::Scalar(src) | crate::TypeInner::Vector { scalar: src, .. } => {
let target_scalar = crate::Scalar {
kind,
width: convert.unwrap_or(src.width),
};
let is_bool_cast =
kind == crate::ScalarKind::Bool || src_kind == crate::ScalarKind::Bool;
kind == crate::ScalarKind::Bool || src.kind == crate::ScalarKind::Bool;
let op = match convert {
Some(w) if w == src_width || is_bool_cast => "static_cast",
Some(w) if w == src.width || is_bool_cast => "static_cast",
Some(8) if kind == crate::ScalarKind::Float => {
return Err(Error::CapabilityNotSupported(valid::Capabilities::FLOAT64))
}
@ -1915,16 +1928,24 @@ impl<W: Write> Writer<W> {
write!(self.out, "{op}<")?;
match *context.resolve_type(expr) {
crate::TypeInner::Vector { size, .. } => {
put_numeric_type(&mut self.out, kind, &[size])?
put_numeric_type(&mut self.out, target_scalar, &[size])?
}
_ => put_numeric_type(&mut self.out, kind, &[])?,
_ => put_numeric_type(&mut self.out, target_scalar, &[])?,
};
write!(self.out, ">(")?;
self.put_expression(expr, context, true)?;
write!(self.out, ")")?;
}
crate::TypeInner::Matrix { columns, rows, .. } => {
put_numeric_type(&mut self.out, kind, &[rows, columns])?;
crate::TypeInner::Matrix {
columns,
rows,
width,
} => {
let target_scalar = crate::Scalar {
kind,
width: convert.unwrap_or(width),
};
put_numeric_type(&mut self.out, target_scalar, &[rows, columns])?;
write!(self.out, "(")?;
self.put_expression(expr, context, true)?;
write!(self.out, ")")?;
@ -2008,8 +2029,8 @@ impl<W: Write> Writer<W> {
context: &ExpressionContext,
is_scoped: bool,
) -> BackendResult {
if let Some(scalar_kind) = context.get_packed_vec_kind(expr_handle) {
write!(self.out, "{}::{}3(", NAMESPACE, scalar_kind.to_msl_name())?;
if let Some(scalar) = context.get_packed_vec_kind(expr_handle) {
write!(self.out, "{}::{}3(", NAMESPACE, scalar.to_msl_name())?;
self.put_expression(expr_handle, context, is_scoped)?;
write!(self.out, ")")?;
} else {
@ -2475,8 +2496,8 @@ impl<W: Write> Writer<W> {
// check what kind of product this is depending
// on the resolve type of the Dot function itself
let inner = context.resolve_type(expr_handle);
if let crate::TypeInner::Scalar { kind, .. } = *inner {
match kind {
if let crate::TypeInner::Scalar(scalar) = *inner {
match scalar.kind {
crate::ScalarKind::Sint | crate::ScalarKind::Uint => {
self.need_bake_expressions.insert(arg);
self.need_bake_expressions.insert(arg1.unwrap());
@ -2522,14 +2543,19 @@ impl<W: Write> Writer<W> {
};
write!(self.out, "{ty_name}")?;
}
TypeResolution::Value(crate::TypeInner::Scalar { kind, .. }) => {
put_numeric_type(&mut self.out, kind, &[])?;
TypeResolution::Value(crate::TypeInner::Scalar(scalar)) => {
put_numeric_type(&mut self.out, scalar, &[])?;
}
TypeResolution::Value(crate::TypeInner::Vector { size, kind, .. }) => {
put_numeric_type(&mut self.out, kind, &[size])?;
TypeResolution::Value(crate::TypeInner::Vector { size, scalar }) => {
put_numeric_type(&mut self.out, scalar, &[size])?;
}
TypeResolution::Value(crate::TypeInner::Matrix { columns, rows, .. }) => {
put_numeric_type(&mut self.out, crate::ScalarKind::Float, &[rows, columns])?;
TypeResolution::Value(crate::TypeInner::Matrix {
columns,
rows,
width,
}) => {
let element = crate::Scalar::float(width);
put_numeric_type(&mut self.out, element, &[rows, columns])?;
}
TypeResolution::Value(ref other) => {
log::warn!("Type {:?} isn't a known local", other); //TEMP!
@ -3292,13 +3318,13 @@ impl<W: Write> Writer<W> {
// If the member should be packed (as is the case for a misaligned vec3) issue a packed vector
match should_pack_struct_member(members, span, index, module) {
Some(kind) => {
Some(scalar) => {
writeln!(
self.out,
"{}{}::packed_{}3 {};",
back::INDENT,
NAMESPACE,
kind.to_msl_name(),
scalar.to_msl_name(),
member_name
)?;
}
@ -3322,11 +3348,10 @@ impl<W: Write> Writer<W> {
// for 3-component vectors, add one component
if let crate::TypeInner::Vector {
size: crate::VectorSize::Tri,
kind: _,
width,
scalar,
} = *ty_inner
{
last_offset += width as u32;
last_offset += scalar.width as u32;
}
}
}

View File

@ -12,7 +12,7 @@ use spirv::Word;
fn get_dimension(type_inner: &crate::TypeInner) -> Dimension {
match *type_inner {
crate::TypeInner::Scalar { .. } => Dimension::Scalar,
crate::TypeInner::Scalar(_) => Dimension::Scalar,
crate::TypeInner::Vector { .. } => Dimension::Vector,
crate::TypeInner::Matrix { .. } => Dimension::Matrix,
_ => unreachable!(),
@ -78,8 +78,7 @@ impl Writer {
) -> Result<(), Error> {
let float_ptr_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Float,
width: 4,
scalar: crate::Scalar::F32,
pointer_space: Some(spirv::StorageClass::Output),
}));
let index_y_id = self.get_index_constant(1);
@ -93,8 +92,7 @@ impl Writer {
let float_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Float,
width: 4,
scalar: crate::Scalar::F32,
pointer_space: None,
}));
let load_id = self.id_gen.next();
@ -120,8 +118,7 @@ impl Writer {
) -> Result<(), Error> {
let float_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Float,
width: 4,
scalar: crate::Scalar::F32,
pointer_space: None,
}));
let zero_scalar_id = self.get_constant_scalar(crate::Literal::F32(0.0));
@ -489,8 +486,8 @@ impl<'w> BlockContext<'w> {
let spirv_op = match op {
crate::BinaryOperator::Add => match *left_ty_inner {
crate::TypeInner::Scalar { kind, .. }
| crate::TypeInner::Vector { kind, .. } => match kind {
crate::TypeInner::Scalar(scalar)
| crate::TypeInner::Vector { scalar, .. } => match scalar.kind {
crate::ScalarKind::Float => spirv::Op::FAdd,
_ => spirv::Op::IAdd,
},
@ -517,8 +514,8 @@ impl<'w> BlockContext<'w> {
_ => unimplemented!(),
},
crate::BinaryOperator::Subtract => match *left_ty_inner {
crate::TypeInner::Scalar { kind, .. }
| crate::TypeInner::Vector { kind, .. } => match kind {
crate::TypeInner::Scalar(scalar)
| crate::TypeInner::Vector { scalar, .. } => match scalar.kind {
crate::ScalarKind::Float => spirv::Op::FSub,
_ => spirv::Op::ISub,
},
@ -741,20 +738,19 @@ impl<'w> BlockContext<'w> {
other => unimplemented!("Unexpected max({:?})", other),
}),
Mf::Saturate => {
let (maybe_size, width) = match *arg_ty {
crate::TypeInner::Vector { size, width, .. } => (Some(size), width),
crate::TypeInner::Scalar { width, .. } => (None, width),
let (maybe_size, scalar) = match *arg_ty {
crate::TypeInner::Vector { size, scalar } => (Some(size), scalar),
crate::TypeInner::Scalar(scalar) => (None, scalar),
ref other => unimplemented!("Unexpected saturate({:?})", other),
};
let kind = crate::ScalarKind::Float;
let mut arg1_id = self.writer.get_constant_scalar_with(0, kind, width)?;
let mut arg2_id = self.writer.get_constant_scalar_with(1, kind, width)?;
let scalar = crate::Scalar::float(scalar.width);
let mut arg1_id = self.writer.get_constant_scalar_with(0, scalar)?;
let mut arg2_id = self.writer.get_constant_scalar_with(1, scalar)?;
if let Some(size) = maybe_size {
let ty = LocalType::Value {
vector_size: Some(size),
kind,
width,
scalar,
pointer_space: None,
}
.into();
@ -805,7 +801,11 @@ impl<'w> BlockContext<'w> {
// geometry
Mf::Dot => match *self.fun_info[arg].ty.inner_with(&self.ir_module.types) {
crate::TypeInner::Vector {
kind: crate::ScalarKind::Float,
scalar:
crate::Scalar {
kind: crate::ScalarKind::Float,
..
},
..
} => MathOp::Custom(Instruction::binary(
spirv::Op::Dot,
@ -866,13 +866,12 @@ impl<'w> BlockContext<'w> {
// if the selector is a scalar, we need to splat it
(
&crate::TypeInner::Vector { size, .. },
&crate::TypeInner::Scalar { kind, width },
&crate::TypeInner::Scalar(scalar),
) => {
let selector_type_id =
self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: Some(size),
kind,
width,
scalar,
pointer_space: None,
}));
self.temp_list.clear();
@ -915,14 +914,12 @@ impl<'w> BlockContext<'w> {
arg0_id,
)),
Mf::CountTrailingZeros => {
let kind = crate::ScalarKind::Uint;
let uint_id = match *arg_ty {
crate::TypeInner::Vector { size, width, .. } => {
crate::TypeInner::Vector { size, mut scalar } => {
scalar.kind = crate::ScalarKind::Uint;
let ty = LocalType::Value {
vector_size: Some(size),
kind,
width,
scalar,
pointer_space: None,
}
.into();
@ -930,13 +927,14 @@ impl<'w> BlockContext<'w> {
self.temp_list.clear();
self.temp_list.resize(
size as _,
self.writer.get_constant_scalar_with(32, kind, width)?,
self.writer.get_constant_scalar_with(32, scalar)?,
);
self.writer.get_constant_composite(ty, &self.temp_list)
}
crate::TypeInner::Scalar { width, .. } => {
self.writer.get_constant_scalar_with(32, kind, width)?
crate::TypeInner::Scalar(mut scalar) => {
scalar.kind = crate::ScalarKind::Uint;
self.writer.get_constant_scalar_with(32, scalar)?
}
_ => unreachable!(),
};
@ -959,14 +957,12 @@ impl<'w> BlockContext<'w> {
))
}
Mf::CountLeadingZeros => {
let kind = crate::ScalarKind::Sint;
let (int_type_id, int_id) = match *arg_ty {
crate::TypeInner::Vector { size, width, .. } => {
crate::TypeInner::Vector { size, mut scalar } => {
scalar.kind = crate::ScalarKind::Sint;
let ty = LocalType::Value {
vector_size: Some(size),
kind,
width,
scalar,
pointer_space: None,
}
.into();
@ -974,7 +970,7 @@ impl<'w> BlockContext<'w> {
self.temp_list.clear();
self.temp_list.resize(
size as _,
self.writer.get_constant_scalar_with(31, kind, width)?,
self.writer.get_constant_scalar_with(31, scalar)?,
);
(
@ -982,15 +978,17 @@ impl<'w> BlockContext<'w> {
self.writer.get_constant_composite(ty, &self.temp_list),
)
}
crate::TypeInner::Scalar { width, .. } => (
self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind,
width,
pointer_space: None,
})),
self.writer.get_constant_scalar_with(31, kind, width)?,
),
crate::TypeInner::Scalar(mut scalar) => {
scalar.kind = crate::ScalarKind::Sint;
(
self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
scalar,
pointer_space: None,
})),
self.writer.get_constant_scalar_with(31, scalar)?,
)
}
_ => unreachable!(),
};
@ -1139,13 +1137,13 @@ impl<'w> BlockContext<'w> {
use crate::ScalarKind as Sk;
let expr_id = self.cached[expr];
let (src_kind, src_size, src_width, is_matrix) =
let (src_scalar, src_size, is_matrix) =
match *self.fun_info[expr].ty.inner_with(&self.ir_module.types) {
crate::TypeInner::Scalar { kind, width } => (kind, None, width, false),
crate::TypeInner::Vector { kind, width, size } => {
(kind, Some(size), width, false)
crate::TypeInner::Scalar(scalar) => (scalar, None, false),
crate::TypeInner::Vector { scalar, size } => (scalar, Some(size), false),
crate::TypeInner::Matrix { width, .. } => {
(crate::Scalar::float(width), None, true)
}
crate::TypeInner::Matrix { width, .. } => (kind, None, width, true),
ref other => {
log::error!("As source {:?}", other);
return Err(Error::Validation("Unexpected Expression::As source"));
@ -1163,11 +1161,12 @@ impl<'w> BlockContext<'w> {
// we only support identity casts for matrices
Cast::Unary(spirv::Op::CopyObject)
} else {
match (src_kind, kind, convert) {
match (src_scalar.kind, kind, convert) {
// Filter out identity casts. Some Adreno drivers are
// confused by no-op OpBitCast instructions.
(src_kind, kind, convert)
if src_kind == kind && convert.unwrap_or(src_width) == src_width =>
if src_kind == kind
&& convert.filter(|&width| width != src_scalar.width).is_none() =>
{
Cast::Identity
}
@ -1175,20 +1174,18 @@ impl<'w> BlockContext<'w> {
(_, _, None) => Cast::Unary(spirv::Op::Bitcast),
// casting to a bool - generate `OpXxxNotEqual`
(_, Sk::Bool, Some(_)) => {
let op = match src_kind {
let op = match src_scalar.kind {
Sk::Sint | Sk::Uint => spirv::Op::INotEqual,
Sk::Float => spirv::Op::FUnordNotEqual,
Sk::Bool => unreachable!(),
};
let zero_scalar_id = self
.writer
.get_constant_scalar_with(0, src_kind, src_width)?;
let zero_scalar_id =
self.writer.get_constant_scalar_with(0, src_scalar)?;
let zero_id = match src_size {
Some(size) => {
let ty = LocalType::Value {
vector_size: Some(size),
kind: src_kind,
width: src_width,
scalar: src_scalar,
pointer_space: None,
}
.into();
@ -1205,16 +1202,19 @@ impl<'w> BlockContext<'w> {
}
// casting from a bool - generate `OpSelect`
(Sk::Bool, _, Some(dst_width)) => {
let dst_scalar = crate::Scalar {
kind,
width: dst_width,
};
let zero_scalar_id =
self.writer.get_constant_scalar_with(0, kind, dst_width)?;
self.writer.get_constant_scalar_with(0, dst_scalar)?;
let one_scalar_id =
self.writer.get_constant_scalar_with(1, kind, dst_width)?;
self.writer.get_constant_scalar_with(1, dst_scalar)?;
let (accept_id, reject_id) = match src_size {
Some(size) => {
let ty = LocalType::Value {
vector_size: Some(size),
kind,
width: dst_width,
scalar: dst_scalar,
pointer_space: None,
}
.into();
@ -1239,15 +1239,17 @@ impl<'w> BlockContext<'w> {
}
(Sk::Float, Sk::Uint, Some(_)) => Cast::Unary(spirv::Op::ConvertFToU),
(Sk::Float, Sk::Sint, Some(_)) => Cast::Unary(spirv::Op::ConvertFToS),
(Sk::Float, Sk::Float, Some(dst_width)) if src_width != dst_width => {
(Sk::Float, Sk::Float, Some(dst_width))
if src_scalar.width != dst_width =>
{
Cast::Unary(spirv::Op::FConvert)
}
(Sk::Sint, Sk::Float, Some(_)) => Cast::Unary(spirv::Op::ConvertSToF),
(Sk::Sint, Sk::Sint, Some(dst_width)) if src_width != dst_width => {
(Sk::Sint, Sk::Sint, Some(dst_width)) if src_scalar.width != dst_width => {
Cast::Unary(spirv::Op::SConvert)
}
(Sk::Uint, Sk::Float, Some(_)) => Cast::Unary(spirv::Op::ConvertUToF),
(Sk::Uint, Sk::Uint, Some(dst_width)) if src_width != dst_width => {
(Sk::Uint, Sk::Uint, Some(dst_width)) if src_scalar.width != dst_width => {
Cast::Unary(spirv::Op::UConvert)
}
// We assume it's either an identity cast, or int-uint.
@ -1334,10 +1336,12 @@ impl<'w> BlockContext<'w> {
let object_ty = self.fun_info[accept].ty.inner_with(&self.ir_module.types);
if let (
&crate::TypeInner::Scalar {
kind: crate::ScalarKind::Bool,
width,
},
&crate::TypeInner::Scalar(
condition_scalar @ crate::Scalar {
kind: crate::ScalarKind::Bool,
..
},
),
&crate::TypeInner::Vector { size, .. },
) = (condition_ty, object_ty)
{
@ -1347,8 +1351,7 @@ impl<'w> BlockContext<'w> {
let bool_vector_type_id =
self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: Some(size),
kind: crate::ScalarKind::Bool,
width,
scalar: condition_scalar,
pointer_space: None,
}));
@ -1598,8 +1601,7 @@ impl<'w> BlockContext<'w> {
let vector_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: Some(rows),
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
pointer_space: None,
}));
@ -1649,7 +1651,10 @@ impl<'w> BlockContext<'w> {
vector: &crate::TypeInner,
) {
let (size, kind) = match *vector {
crate::TypeInner::Vector { size, kind, .. } => (size, kind),
crate::TypeInner::Vector {
size,
scalar: crate::Scalar { kind, .. },
} => (size, kind),
_ => unreachable!(),
};
@ -2193,14 +2198,14 @@ impl<'w> BlockContext<'w> {
),
crate::AtomicFunction::Min => {
let spirv_op = match *value_inner {
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Sint,
width: _,
} => spirv::Op::AtomicSMin,
crate::TypeInner::Scalar {
}) => spirv::Op::AtomicSMin,
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Uint,
width: _,
} => spirv::Op::AtomicUMin,
}) => spirv::Op::AtomicUMin,
_ => unimplemented!(),
};
Instruction::atomic_binary(
@ -2215,14 +2220,14 @@ impl<'w> BlockContext<'w> {
}
crate::AtomicFunction::Max => {
let spirv_op = match *value_inner {
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Sint,
width: _,
} => spirv::Op::AtomicSMax,
crate::TypeInner::Scalar {
}) => spirv::Op::AtomicSMax,
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Uint,
width: _,
} => spirv::Op::AtomicUMax,
}) => spirv::Op::AtomicUMax,
_ => unimplemented!(),
};
Instruction::atomic_binary(
@ -2248,11 +2253,10 @@ impl<'w> BlockContext<'w> {
}
crate::AtomicFunction::Exchange { compare: Some(cmp) } => {
let scalar_type_id = match *value_inner {
crate::TypeInner::Scalar { kind, width } => {
crate::TypeInner::Scalar(scalar) => {
self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind,
width,
scalar,
pointer_space: None,
}))
}
@ -2261,8 +2265,7 @@ impl<'w> BlockContext<'w> {
let bool_type_id =
self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
scalar: crate::Scalar::BOOL,
pointer_space: None,
}));

View File

@ -128,8 +128,7 @@ impl Load {
crate::ImageClass::Depth { .. } => {
ctx.get_type_id(LookupType::Local(LocalType::Value {
vector_size: Some(crate::VectorSize::Quad),
kind: crate::ScalarKind::Float,
width: 4,
scalar: crate::Scalar::F32,
pointer_space: None,
}))
}
@ -292,18 +291,16 @@ impl<'w> BlockContext<'w> {
// Find the component type of `coordinates`, and figure out the size the
// combined coordinate vector will have.
let (component_kind, size) = match *inner_ty {
Ti::Scalar { kind, width: 4 } => (kind, Some(Vs::Bi)),
let (component_scalar, size) = match *inner_ty {
Ti::Scalar(scalar @ crate::Scalar { width: 4, .. }) => (scalar, Some(Vs::Bi)),
Ti::Vector {
kind,
width: 4,
scalar: scalar @ crate::Scalar { width: 4, .. },
size: Vs::Bi,
} => (kind, Some(Vs::Tri)),
} => (scalar, Some(Vs::Tri)),
Ti::Vector {
kind,
width: 4,
scalar: scalar @ crate::Scalar { width: 4, .. },
size: Vs::Tri,
} => (kind, Some(Vs::Quad)),
} => (scalar, Some(Vs::Quad)),
Ti::Vector { size: Vs::Quad, .. } => {
return Err(Error::Validation("extending vec4 coordinate"));
}
@ -317,16 +314,16 @@ impl<'w> BlockContext<'w> {
let array_index_id = self.cached[array_index];
let ty = &self.fun_info[array_index].ty;
let inner_ty = ty.inner_with(&self.ir_module.types);
let array_index_kind = if let Ti::Scalar { kind, width: 4 } = *inner_ty {
debug_assert!(matches!(
kind,
crate::ScalarKind::Sint | crate::ScalarKind::Uint
));
kind
} else {
unreachable!("we only allow i32 and u32");
let array_index_scalar = match *inner_ty {
Ti::Scalar(
scalar @ crate::Scalar {
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
width: 4,
},
) => scalar,
_ => unreachable!("we only allow i32 and u32"),
};
let cast = match (component_kind, array_index_kind) {
let cast = match (component_scalar.kind, array_index_scalar.kind) {
(crate::ScalarKind::Sint, crate::ScalarKind::Sint)
| (crate::ScalarKind::Uint, crate::ScalarKind::Uint) => None,
(crate::ScalarKind::Sint, crate::ScalarKind::Uint)
@ -341,8 +338,7 @@ impl<'w> BlockContext<'w> {
let reconciled_array_index_id = if let Some(cast) = cast {
let component_ty_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: component_kind,
width: 4,
scalar: component_scalar,
pointer_space: None,
}));
let reconciled_id = self.gen_id();
@ -360,8 +356,7 @@ impl<'w> BlockContext<'w> {
// Find the SPIR-V type for the combined coordinates/index vector.
let type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: size,
kind: component_kind,
width: 4,
scalar: component_scalar,
pointer_space: None,
}));
@ -532,8 +527,7 @@ impl<'w> BlockContext<'w> {
let i32_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Sint,
width: 4,
scalar: crate::Scalar::I32,
pointer_space: None,
}));
@ -620,8 +614,7 @@ impl<'w> BlockContext<'w> {
let bool_type_id = self.writer.get_bool_type_id();
let i32_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Sint,
width: 4,
scalar: crate::Scalar::I32,
pointer_space: None,
}));
@ -688,8 +681,7 @@ impl<'w> BlockContext<'w> {
// Compare the coordinates against the bounds.
let coords_bool_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: coordinates.size,
kind: crate::ScalarKind::Bool,
width: 1,
scalar: crate::Scalar::BOOL,
pointer_space: None,
}));
let coords_conds_id = self.gen_id();
@ -844,8 +836,7 @@ impl<'w> BlockContext<'w> {
let sample_result_type_id = if needs_sub_access {
self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: Some(crate::VectorSize::Quad),
kind: crate::ScalarKind::Float,
width: 4,
scalar: crate::Scalar::F32,
pointer_space: None,
}))
} else {
@ -1045,8 +1036,7 @@ impl<'w> BlockContext<'w> {
};
let extended_size_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size,
kind: crate::ScalarKind::Uint,
width: 4,
scalar: crate::Scalar::U32,
pointer_space: None,
}));
@ -1116,8 +1106,7 @@ impl<'w> BlockContext<'w> {
};
let extended_size_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: Some(vec_size),
kind: crate::ScalarKind::Uint,
width: 4,
scalar: crate::Scalar::U32,
pointer_space: None,
}));
let id_extended = self.gen_id();

View File

@ -276,8 +276,7 @@ enum LocalType {
/// If `None`, this represents a scalar type. If `Some`, this represents
/// a vector type of the given size.
vector_size: Option<crate::VectorSize>,
kind: crate::ScalarKind,
width: crate::Bytes,
scalar: crate::Scalar,
pointer_space: Option<spirv::StorageClass>,
},
/// A matrix of floating-point values.
@ -355,18 +354,14 @@ struct LookupFunctionType {
fn make_local(inner: &crate::TypeInner) -> Option<LocalType> {
Some(match *inner {
crate::TypeInner::Scalar { kind, width } | crate::TypeInner::Atomic { kind, width } => {
LocalType::Value {
vector_size: None,
kind,
width,
pointer_space: None,
}
}
crate::TypeInner::Vector { size, kind, width } => LocalType::Value {
crate::TypeInner::Scalar(scalar) | crate::TypeInner::Atomic(scalar) => LocalType::Value {
vector_size: None,
scalar,
pointer_space: None,
},
crate::TypeInner::Vector { size, scalar } => LocalType::Value {
vector_size: Some(size),
kind,
width,
scalar,
pointer_space: None,
},
crate::TypeInner::Matrix {
@ -384,13 +379,11 @@ fn make_local(inner: &crate::TypeInner) -> Option<LocalType> {
},
crate::TypeInner::ValuePointer {
size,
kind,
width,
scalar,
space,
} => LocalType::Value {
vector_size: size,
kind,
width,
scalar,
pointer_space: Some(helpers::map_storage_class(space)),
},
crate::TypeInner::Image {

View File

@ -21,12 +21,10 @@ impl<'w> BlockContext<'w> {
//Note: composite extract indices and types must match `generate_ray_desc_type`
let desc_id = self.cached[descriptor];
let acc_struct_id = self.get_handle_id(acceleration_structure);
let width = 4;
let flag_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Uint,
width,
scalar: crate::Scalar::U32,
pointer_space: None,
}));
let ray_flags_id = self.gen_id();
@ -46,8 +44,7 @@ impl<'w> BlockContext<'w> {
let scalar_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::F32,
pointer_space: None,
}));
let tmin_id = self.gen_id();
@ -67,8 +64,7 @@ impl<'w> BlockContext<'w> {
let vector_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: Some(crate::VectorSize::Tri),
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::F32,
pointer_space: None,
}));
let ray_origin_id = self.gen_id();
@ -115,7 +111,6 @@ impl<'w> BlockContext<'w> {
query: Handle<crate::Expression>,
block: &mut Block,
) -> spirv::Word {
let width = 4;
let query_id = self.cached[query];
let intersection_id = self.writer.get_constant_scalar(crate::Literal::U32(
spirv::RayQueryIntersection::RayQueryCommittedIntersectionKHR as _,
@ -123,8 +118,7 @@ impl<'w> BlockContext<'w> {
let flag_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Uint,
width,
scalar: crate::Scalar::U32,
pointer_space: None,
}));
let kind_id = self.gen_id();
@ -178,8 +172,7 @@ impl<'w> BlockContext<'w> {
let scalar_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::F32,
pointer_space: None,
}));
let t_id = self.gen_id();
@ -193,8 +186,7 @@ impl<'w> BlockContext<'w> {
let barycentrics_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: Some(crate::VectorSize::Bi),
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::F32,
pointer_space: None,
}));
let barycentrics_id = self.gen_id();
@ -208,8 +200,7 @@ impl<'w> BlockContext<'w> {
let bool_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
scalar: crate::Scalar::BOOL,
pointer_space: None,
}));
let front_face_id = self.gen_id();
@ -224,7 +215,7 @@ impl<'w> BlockContext<'w> {
let transform_type_id = self.get_type_id(LookupType::Local(LocalType::Matrix {
columns: crate::VectorSize::Quad,
rows: crate::VectorSize::Tri,
width,
width: 4,
}));
let object_to_world_id = self.gen_id();
block.body.push(Instruction::ray_query_get_intersection(

View File

@ -238,8 +238,7 @@ impl Writer {
pub(super) fn get_uint_type_id(&mut self) -> Word {
let local_type = LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Uint,
width: 4,
scalar: crate::Scalar::U32,
pointer_space: None,
};
self.get_type_id(local_type.into())
@ -248,8 +247,7 @@ impl Writer {
pub(super) fn get_float_type_id(&mut self) -> Word {
let local_type = LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Float,
width: 4,
scalar: crate::Scalar::F32,
pointer_space: None,
};
self.get_type_id(local_type.into())
@ -258,8 +256,7 @@ impl Writer {
pub(super) fn get_uint3_type_id(&mut self) -> Word {
let local_type = LocalType::Value {
vector_size: Some(crate::VectorSize::Tri),
kind: crate::ScalarKind::Uint,
width: 4,
scalar: crate::Scalar::U32,
pointer_space: None,
};
self.get_type_id(local_type.into())
@ -268,8 +265,7 @@ impl Writer {
pub(super) fn get_float_pointer_type_id(&mut self, class: spirv::StorageClass) -> Word {
let lookup_type = LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Float,
width: 4,
scalar: crate::Scalar::F32,
pointer_space: Some(class),
});
if let Some(&id) = self.lookup_type.get(&lookup_type) {
@ -287,8 +283,7 @@ impl Writer {
pub(super) fn get_uint3_pointer_type_id(&mut self, class: spirv::StorageClass) -> Word {
let lookup_type = LookupType::Local(LocalType::Value {
vector_size: Some(crate::VectorSize::Tri),
kind: crate::ScalarKind::Uint,
width: 4,
scalar: crate::Scalar::U32,
pointer_space: Some(class),
});
if let Some(&id) = self.lookup_type.get(&lookup_type) {
@ -306,8 +301,7 @@ impl Writer {
pub(super) fn get_bool_type_id(&mut self) -> Word {
let local_type = LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Bool,
width: 1,
scalar: crate::Scalar::BOOL,
pointer_space: None,
};
self.get_type_id(local_type.into())
@ -316,8 +310,7 @@ impl Writer {
pub(super) fn get_bool3_type_id(&mut self) -> Word {
let local_type = LocalType::Value {
vector_size: Some(crate::VectorSize::Tri),
kind: crate::ScalarKind::Bool,
width: 1,
scalar: crate::Scalar::BOOL,
pointer_space: None,
};
self.get_type_id(local_type.into())
@ -802,18 +795,13 @@ impl Writer {
))
}
fn make_scalar(
&mut self,
id: Word,
kind: crate::ScalarKind,
width: crate::Bytes,
) -> Instruction {
fn make_scalar(&mut self, id: Word, scalar: crate::Scalar) -> Instruction {
use crate::ScalarKind as Sk;
let bits = (width * BITS_PER_BYTE) as u32;
match kind {
let bits = (scalar.width * BITS_PER_BYTE) as u32;
match scalar.kind {
Sk::Sint | Sk::Uint => {
let signedness = if kind == Sk::Sint {
let signedness = if scalar.kind == Sk::Sint {
super::instructions::Signedness::Signed
} else {
super::instructions::Signedness::Unsigned
@ -894,20 +882,17 @@ impl Writer {
let instruction = match local_ty {
LocalType::Value {
vector_size: None,
kind,
width,
scalar,
pointer_space: None,
} => self.make_scalar(id, kind, width),
} => self.make_scalar(id, scalar),
LocalType::Value {
vector_size: Some(size),
kind,
width,
scalar,
pointer_space: None,
} => {
let scalar_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind,
width,
scalar,
pointer_space: None,
}));
Instruction::type_vector(id, scalar_id, size)
@ -919,8 +904,7 @@ impl Writer {
} => {
let vector_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: Some(rows),
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
pointer_space: None,
}));
Instruction::type_matrix(id, vector_id, columns)
@ -931,14 +915,12 @@ impl Writer {
}
LocalType::Value {
vector_size,
kind,
width,
scalar,
pointer_space: Some(class),
} => {
let type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size,
kind,
width,
scalar,
pointer_space: None,
}));
Instruction::type_pointer(id, class, type_id)
@ -946,8 +928,10 @@ impl Writer {
LocalType::Image(image) => {
let local_type = LocalType::Value {
vector_size: None,
kind: image.sampled_type,
width: 4,
scalar: crate::Scalar {
kind: image.sampled_type,
width: 4,
},
pointer_space: None,
};
let type_id = self.get_type_id(LookupType::Local(local_type));
@ -1060,8 +1044,8 @@ impl Writer {
// These all have TypeLocal representations, so they should have been
// handled by `write_type_declaration_local` above.
crate::TypeInner::Scalar { .. }
| crate::TypeInner::Atomic { .. }
crate::TypeInner::Scalar(_)
| crate::TypeInner::Atomic(_)
| crate::TypeInner::Vector { .. }
| crate::TypeInner::Matrix { .. }
| crate::TypeInner::Pointer { .. }
@ -1151,11 +1135,10 @@ impl Writer {
pub(super) fn get_constant_scalar_with(
&mut self,
value: u8,
kind: crate::ScalarKind,
width: crate::Bytes,
scalar: crate::Scalar,
) -> Result<Word, Error> {
Ok(
self.get_constant_scalar(crate::Literal::new(value, kind, width).ok_or(
self.get_constant_scalar(crate::Literal::new(value, scalar).ok_or(
Error::Validation("Unexpected kind and/or width for Literal"),
)?),
)
@ -1185,8 +1168,7 @@ impl Writer {
}
let type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: value.scalar_kind(),
width: value.width(),
scalar: value.scalar(),
pointer_space: None,
}));
let instruction = match *value {
@ -1602,8 +1584,8 @@ impl Writer {
// > shader, must be decorated Flat
if class == spirv::StorageClass::Input && stage == crate::ShaderStage::Fragment {
let is_flat = match ir_module.types[ty].inner {
crate::TypeInner::Scalar { kind, .. }
| crate::TypeInner::Vector { kind, .. } => match kind {
crate::TypeInner::Scalar(scalar)
| crate::TypeInner::Vector { scalar, .. } => match scalar.kind {
Sk::Uint | Sk::Sint | Sk::Bool => true,
Sk::Float => false,
},

View File

@ -426,11 +426,11 @@ impl<W: Write> Writer<W> {
/// Adds no trailing or leading whitespace
fn write_value_type(&mut self, module: &Module, inner: &TypeInner) -> BackendResult {
match *inner {
TypeInner::Vector { size, kind, width } => write!(
TypeInner::Vector { size, scalar } => write!(
self.out,
"vec{}<{}>",
back::vector_size_str(size),
scalar_kind_str(kind, width),
scalar_kind_str(scalar),
)?,
TypeInner::Sampler { comparison: false } => {
write!(self.out, "sampler")?;
@ -452,7 +452,7 @@ impl<W: Write> Writer<W> {
Ic::Sampled { kind, multi } => (
"",
if multi { "multisampled_" } else { "" },
scalar_kind_str(kind, 4),
scalar_kind_str(crate::Scalar { kind, width: 4 }),
"",
),
Ic::Depth { multi } => {
@ -481,11 +481,11 @@ impl<W: Write> Writer<W> {
write!(self.out, "<{format_str}{storage_str}>")?;
}
}
TypeInner::Scalar { kind, width } => {
write!(self.out, "{}", scalar_kind_str(kind, width))?;
TypeInner::Scalar(scalar) => {
write!(self.out, "{}", scalar_kind_str(scalar))?;
}
TypeInner::Atomic { kind, width } => {
write!(self.out, "atomic<{}>", scalar_kind_str(kind, width))?;
TypeInner::Atomic(scalar) => {
write!(self.out, "atomic<{}>", scalar_kind_str(scalar))?;
}
TypeInner::Array {
base,
@ -552,13 +552,12 @@ impl<W: Write> Writer<W> {
}
TypeInner::ValuePointer {
size: None,
kind,
width,
scalar,
space,
} => {
let (address, maybe_access) = address_space_str(space);
if let Some(space) = address {
write!(self.out, "ptr<{}, {}", space, scalar_kind_str(kind, width))?;
write!(self.out, "ptr<{}, {}", space, scalar_kind_str(scalar))?;
if let Some(access) = maybe_access {
write!(self.out, ", {access}")?;
}
@ -571,8 +570,7 @@ impl<W: Write> Writer<W> {
}
TypeInner::ValuePointer {
size: Some(size),
kind,
width,
scalar,
space,
} => {
let (address, maybe_access) = address_space_str(space);
@ -582,7 +580,7 @@ impl<W: Write> Writer<W> {
"ptr<{}, vec{}<{}>",
space,
back::vector_size_str(size),
scalar_kind_str(kind, width)
scalar_kind_str(scalar)
)?;
if let Some(access) = maybe_access {
write!(self.out, ", {access}")?;
@ -1414,7 +1412,11 @@ impl<W: Write> Writer<W> {
width,
..
} => {
let scalar_kind_str = scalar_kind_str(kind, convert.unwrap_or(width));
let scalar = crate::Scalar {
kind,
width: convert.unwrap_or(width),
};
let scalar_kind_str = scalar_kind_str(scalar);
write!(
self.out,
"mat{}x{}<{}>",
@ -1423,17 +1425,28 @@ impl<W: Write> Writer<W> {
scalar_kind_str
)?;
}
TypeInner::Vector { size, width, .. } => {
TypeInner::Vector {
size,
scalar: crate::Scalar { width, .. },
} => {
let scalar = crate::Scalar {
kind,
width: convert.unwrap_or(width),
};
let vector_size_str = back::vector_size_str(size);
let scalar_kind_str = scalar_kind_str(kind, convert.unwrap_or(width));
let scalar_kind_str = scalar_kind_str(scalar);
if convert.is_some() {
write!(self.out, "vec{vector_size_str}<{scalar_kind_str}>")?;
} else {
write!(self.out, "bitcast<vec{vector_size_str}<{scalar_kind_str}>>")?;
}
}
TypeInner::Scalar { width, .. } => {
let scalar_kind_str = scalar_kind_str(kind, convert.unwrap_or(width));
TypeInner::Scalar(crate::Scalar { width, .. }) => {
let scalar = crate::Scalar {
kind,
width: convert.unwrap_or(width),
};
let scalar_kind_str = scalar_kind_str(scalar);
if convert.is_some() {
write!(self.out, "{scalar_kind_str}")?
} else {
@ -1783,15 +1796,31 @@ const fn image_dimension_str(dim: crate::ImageDimension) -> &'static str {
}
}
const fn scalar_kind_str(kind: crate::ScalarKind, width: u8) -> &'static str {
const fn scalar_kind_str(scalar: crate::Scalar) -> &'static str {
use crate::Scalar;
use crate::ScalarKind as Sk;
match (kind, width) {
(Sk::Float, 8) => "f64",
(Sk::Float, 4) => "f32",
(Sk::Sint, 4) => "i32",
(Sk::Uint, 4) => "u32",
(Sk::Bool, 1) => "bool",
match scalar {
Scalar {
kind: Sk::Float,
width: 8,
} => "f64",
Scalar {
kind: Sk::Float,
width: 4,
} => "f32",
Scalar {
kind: Sk::Sint,
width: 4,
} => "i32",
Scalar {
kind: Sk::Uint,
width: 4,
} => "u32",
Scalar {
kind: Sk::Bool,
width: 1,
} => "bool",
_ => unreachable!(),
}
}

View File

@ -54,10 +54,10 @@ impl ModuleMap {
use crate::TypeInner as Ti;
match ty.inner {
// Types that do not contain handles.
Ti::Scalar { .. }
Ti::Scalar(_)
| Ti::Vector { .. }
| Ti::Matrix { .. }
| Ti::Atomic { .. }
| Ti::Atomic(_)
| Ti::ValuePointer { .. }
| Ti::Image { .. }
| Ti::Sampler { .. }

View File

@ -9,7 +9,7 @@ use super::{
use crate::{
BinaryOperator, DerivativeAxis as Axis, DerivativeControl as Ctrl, Expression, Handle,
ImageClass, ImageDimension as Dim, ImageQuery, MathFunction, Module, RelationalFunction,
SampleLevel, ScalarKind as Sk, Span, Type, TypeInner, UnaryOperator, VectorSize,
SampleLevel, Scalar, ScalarKind as Sk, Span, Type, TypeInner, UnaryOperator, VectorSize,
};
impl crate::ScalarKind {
@ -54,18 +54,17 @@ impl Module {
}
const fn make_coords_arg(number_of_components: usize, kind: Sk) -> TypeInner {
let width = 4;
let scalar = Scalar { kind, width: 4 };
match number_of_components {
1 => TypeInner::Scalar { kind, width },
1 => TypeInner::Scalar(scalar),
_ => TypeInner::Vector {
size: match number_of_components {
2 => VectorSize::Bi,
3 => VectorSize::Tri,
_ => VectorSize::Quad,
},
kind,
width,
scalar,
},
}
}
@ -98,7 +97,6 @@ pub fn inject_builtin(
inject_double_builtin(declaration, module, name)
}
let width = 4;
match name {
"texture"
| "textureGrad"
@ -235,18 +233,12 @@ pub fn inject_builtin(
let mut args = vec![image, vector];
if num_coords == 5 {
args.push(TypeInner::Scalar {
kind: Sk::Float,
width,
});
args.push(TypeInner::Scalar(Scalar::F32));
}
match level_type {
TextureLevelType::Lod => {
args.push(TypeInner::Scalar {
kind: Sk::Float,
width,
});
args.push(TypeInner::Scalar(Scalar::F32));
}
TextureLevelType::Grad => {
args.push(make_coords_arg(num_coords_from_dim, Sk::Float));
@ -260,10 +252,7 @@ pub fn inject_builtin(
}
if bias {
args.push(TypeInner::Scalar {
kind: Sk::Float,
width,
});
args.push(TypeInner::Scalar(Scalar::F32));
}
declaration
@ -290,10 +279,7 @@ pub fn inject_builtin(
let mut args = vec![image];
if !multi {
args.push(TypeInner::Scalar {
kind: Sk::Sint,
width,
})
args.push(TypeInner::Scalar(Scalar::I32))
}
declaration
@ -323,14 +309,7 @@ pub fn inject_builtin(
let dim_value = image_dims_to_coords_size(dim);
let coordinates = make_coords_arg(dim_value + arrayed as usize, Sk::Sint);
let mut args = vec![
image,
coordinates,
TypeInner::Scalar {
kind: Sk::Sint,
width,
},
];
let mut args = vec![image, coordinates, TypeInner::Scalar(Scalar::I32)];
if offset {
args.push(make_coords_arg(dim_value, Sk::Sint));
@ -441,8 +420,7 @@ pub fn inject_builtin(
coordinates,
TypeInner::Vector {
size: VectorSize::Quad,
kind,
width,
scalar: Scalar { kind, width: 4 },
},
];
@ -464,7 +442,6 @@ fn inject_standard_builtins(
module: &mut Module,
name: &str,
) {
let width = 4;
match name {
"sampler1D" | "sampler1DArray" | "sampler2D" | "sampler2DArray" | "sampler2DMS"
| "sampler2DMSArray" | "sampler3D" | "samplerCube" | "samplerCubeArray" => {
@ -544,12 +521,12 @@ fn inject_standard_builtins(
0b10 => Some(VectorSize::Tri),
_ => Some(VectorSize::Quad),
};
let kind = Sk::Float;
let scalar = Scalar::F32;
declaration.overloads.push(module.add_builtin(
vec![match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
}],
match name {
"sin" => MacroCall::MathFunction(MathFunction::Sin),
@ -595,15 +572,15 @@ fn inject_standard_builtins(
0b10 => Some(VectorSize::Tri),
_ => Some(VectorSize::Quad),
};
let kind = match name {
"intBitsToFloat" => Sk::Sint,
_ => Sk::Uint,
let scalar = match name {
"intBitsToFloat" => Scalar::I32,
_ => Scalar::U32,
};
declaration.overloads.push(module.add_builtin(
vec![match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
}],
MacroCall::BitCast(Sk::Float),
))
@ -619,10 +596,10 @@ fn inject_standard_builtins(
0b10 => Some(VectorSize::Tri),
_ => Some(VectorSize::Quad),
};
let kind = Sk::Float;
let scalar = Scalar::F32;
let ty = || match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
};
declaration.overloads.push(
@ -642,14 +619,14 @@ fn inject_standard_builtins(
0b10 => Some(VectorSize::Tri),
_ => Some(VectorSize::Quad),
};
let kind = match bits >> 2 {
0b0 => Sk::Float,
_ => Sk::Sint,
let scalar = match bits >> 2 {
0b0 => Scalar::F32,
_ => Scalar::I32,
};
let args = vec![match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
}];
declaration.overloads.push(module.add_builtin(
@ -684,9 +661,9 @@ fn inject_standard_builtins(
// bit 0 - int/uint
// bit 1 through 2 - dims
for bits in 0..0b1000 {
let kind = match bits & 0b1 {
0b0 => Sk::Sint,
_ => Sk::Uint,
let scalar = match bits & 0b1 {
0b0 => Scalar::I32,
_ => Scalar::U32,
};
let size = match bits >> 1 {
0b00 => None,
@ -696,39 +673,27 @@ fn inject_standard_builtins(
};
let ty = || match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
};
let mut args = vec![ty()];
match fun {
MathFunction::ExtractBits => {
args.push(TypeInner::Scalar {
kind: Sk::Sint,
width: 4,
});
args.push(TypeInner::Scalar {
kind: Sk::Sint,
width: 4,
});
args.push(TypeInner::Scalar(Scalar::I32));
args.push(TypeInner::Scalar(Scalar::I32));
}
MathFunction::InsertBits => {
args.push(ty());
args.push(TypeInner::Scalar {
kind: Sk::Sint,
width: 4,
});
args.push(TypeInner::Scalar {
kind: Sk::Sint,
width: 4,
});
args.push(TypeInner::Scalar(Scalar::I32));
args.push(TypeInner::Scalar(Scalar::I32));
}
_ => {}
}
// we need to cast the return type of findLsb / findMsb
let mc = if kind == Sk::Uint {
let mc = if scalar.kind == Sk::Uint {
match mc {
MacroCall::MathFunction(MathFunction::FindLsb) => MacroCall::FindLsbUint,
MacroCall::MathFunction(MathFunction::FindMsb) => MacroCall::FindMsbUint,
@ -754,15 +719,13 @@ fn inject_standard_builtins(
let ty = match fun {
MathFunction::Pack4x8snorm | MathFunction::Pack4x8unorm => TypeInner::Vector {
size: crate::VectorSize::Quad,
kind: Sk::Float,
width: 4,
scalar: Scalar::F32,
},
MathFunction::Pack2x16unorm
| MathFunction::Pack2x16snorm
| MathFunction::Pack2x16float => TypeInner::Vector {
size: crate::VectorSize::Bi,
kind: Sk::Float,
width: 4,
scalar: Scalar::F32,
},
_ => unreachable!(),
};
@ -784,10 +747,7 @@ fn inject_standard_builtins(
_ => unreachable!(),
};
let args = vec![TypeInner::Scalar {
kind: Sk::Uint,
width: 4,
}];
let args = vec![TypeInner::Scalar(Scalar::U32)];
declaration
.overloads
@ -808,10 +768,10 @@ fn inject_standard_builtins(
0b10 => Some(VectorSize::Tri),
_ => Some(VectorSize::Quad),
};
let kind = Sk::Float;
let scalar = Scalar::F32;
let ty = || match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
};
let mut args = vec![ty()];
@ -837,8 +797,7 @@ fn inject_standard_builtins(
let args = vec![TypeInner::Vector {
size,
kind: Sk::Bool,
width: crate::BOOL_WIDTH,
scalar: Scalar::BOOL,
}];
let fun = match name {
@ -853,19 +812,19 @@ fn inject_standard_builtins(
}
"lessThan" | "greaterThan" | "lessThanEqual" | "greaterThanEqual" => {
for bits in 0..0b1001 {
let (size, kind) = match bits {
0b0000 => (VectorSize::Bi, Sk::Float),
0b0001 => (VectorSize::Tri, Sk::Float),
0b0010 => (VectorSize::Quad, Sk::Float),
0b0011 => (VectorSize::Bi, Sk::Sint),
0b0100 => (VectorSize::Tri, Sk::Sint),
0b0101 => (VectorSize::Quad, Sk::Sint),
0b0110 => (VectorSize::Bi, Sk::Uint),
0b0111 => (VectorSize::Tri, Sk::Uint),
_ => (VectorSize::Quad, Sk::Uint),
let (size, scalar) = match bits {
0b0000 => (VectorSize::Bi, Scalar::F32),
0b0001 => (VectorSize::Tri, Scalar::F32),
0b0010 => (VectorSize::Quad, Scalar::F32),
0b0011 => (VectorSize::Bi, Scalar::I32),
0b0100 => (VectorSize::Tri, Scalar::I32),
0b0101 => (VectorSize::Quad, Scalar::I32),
0b0110 => (VectorSize::Bi, Scalar::U32),
0b0111 => (VectorSize::Tri, Scalar::U32),
_ => (VectorSize::Quad, Scalar::U32),
};
let ty = || TypeInner::Vector { size, kind, width };
let ty = || TypeInner::Vector { size, scalar };
let args = vec![ty(), ty()];
let fun = MacroCall::Binary(match name {
@ -881,28 +840,22 @@ fn inject_standard_builtins(
}
"equal" | "notEqual" => {
for bits in 0..0b1100 {
let (size, kind) = match bits {
0b0000 => (VectorSize::Bi, Sk::Float),
0b0001 => (VectorSize::Tri, Sk::Float),
0b0010 => (VectorSize::Quad, Sk::Float),
0b0011 => (VectorSize::Bi, Sk::Sint),
0b0100 => (VectorSize::Tri, Sk::Sint),
0b0101 => (VectorSize::Quad, Sk::Sint),
0b0110 => (VectorSize::Bi, Sk::Uint),
0b0111 => (VectorSize::Tri, Sk::Uint),
0b1000 => (VectorSize::Quad, Sk::Uint),
0b1001 => (VectorSize::Bi, Sk::Bool),
0b1010 => (VectorSize::Tri, Sk::Bool),
_ => (VectorSize::Quad, Sk::Bool),
let (size, scalar) = match bits {
0b0000 => (VectorSize::Bi, Scalar::F32),
0b0001 => (VectorSize::Tri, Scalar::F32),
0b0010 => (VectorSize::Quad, Scalar::F32),
0b0011 => (VectorSize::Bi, Scalar::I32),
0b0100 => (VectorSize::Tri, Scalar::I32),
0b0101 => (VectorSize::Quad, Scalar::I32),
0b0110 => (VectorSize::Bi, Scalar::U32),
0b0111 => (VectorSize::Tri, Scalar::U32),
0b1000 => (VectorSize::Quad, Scalar::U32),
0b1001 => (VectorSize::Bi, Scalar::BOOL),
0b1010 => (VectorSize::Tri, Scalar::BOOL),
_ => (VectorSize::Quad, Scalar::BOOL),
};
let width = if let Sk::Bool = kind {
crate::BOOL_WIDTH
} else {
width
};
let ty = || TypeInner::Vector { size, kind, width };
let ty = || TypeInner::Vector { size, scalar };
let args = vec![ty(), ty()];
let fun = MacroCall::Binary(match name {
@ -919,10 +872,10 @@ fn inject_standard_builtins(
// bit 0 through 1 - scalar kind
// bit 2 through 4 - dims
for bits in 0..0b11100 {
let kind = match bits & 0b11 {
0b00 => Sk::Float,
0b01 => Sk::Sint,
0b10 => Sk::Uint,
let scalar = match bits & 0b11 {
0b00 => Scalar::F32,
0b01 => Scalar::I32,
0b10 => Scalar::U32,
_ => continue,
};
let (size, second_size) = match bits >> 2 {
@ -937,12 +890,12 @@ fn inject_standard_builtins(
let args = vec![
match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
},
match second_size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
},
];
@ -969,25 +922,25 @@ fn inject_standard_builtins(
0b10 => Some(VectorSize::Quad),
_ => None,
};
let (kind, splatted, boolean) = match bits >> 2 {
0b000 => (Sk::Sint, false, true),
0b001 => (Sk::Uint, false, true),
0b010 => (Sk::Float, false, true),
0b011 => (Sk::Float, false, false),
_ => (Sk::Float, true, false),
let (scalar, splatted, boolean) = match bits >> 2 {
0b000 => (Scalar::I32, false, true),
0b001 => (Scalar::U32, false, true),
0b010 => (Scalar::F32, false, true),
0b011 => (Scalar::F32, false, false),
_ => (Scalar::F32, true, false),
};
let ty = |kind, width| match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
let ty = |scalar| match size {
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
};
let args = vec![
ty(kind, width),
ty(kind, width),
ty(scalar),
ty(scalar),
match (boolean, splatted) {
(true, _) => ty(Sk::Bool, crate::BOOL_WIDTH),
(_, false) => TypeInner::Scalar { kind, width },
_ => ty(kind, width),
(true, _) => ty(Scalar::BOOL),
(_, false) => TypeInner::Scalar(scalar),
_ => ty(scalar),
},
];
@ -1009,10 +962,10 @@ fn inject_standard_builtins(
// 0b11010 is the last element since splatted single elements
// were already added
for bits in 0..0b11011 {
let kind = match bits & 0b11 {
0b00 => Sk::Float,
0b01 => Sk::Sint,
0b10 => Sk::Uint,
let scalar = match bits & 0b11 {
0b00 => Scalar::F32,
0b01 => Scalar::I32,
0b10 => Scalar::U32,
_ => continue,
};
let size = match (bits >> 2) & 0b11 {
@ -1024,11 +977,11 @@ fn inject_standard_builtins(
let splatted = bits & 0b10000 == 0b10000;
let base_ty = || match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
};
let limit_ty = || match splatted {
true => TypeInner::Scalar { kind, width },
true => TypeInner::Scalar(scalar),
false => base_ty(),
};
@ -1049,7 +1002,6 @@ fn inject_standard_builtins(
/// Injects the builtins into declaration that need doubles
fn inject_double_builtin(declaration: &mut FunctionDeclaration, module: &mut Module, name: &str) {
let width = 8;
match name {
"abs" | "sign" => {
// bits layout
@ -1061,11 +1013,11 @@ fn inject_double_builtin(declaration: &mut FunctionDeclaration, module: &mut Mod
0b10 => Some(VectorSize::Tri),
_ => Some(VectorSize::Quad),
};
let kind = Sk::Float;
let scalar = Scalar::F64;
let args = vec![match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
}];
declaration.overloads.push(module.add_builtin(
@ -1091,16 +1043,16 @@ fn inject_double_builtin(declaration: &mut FunctionDeclaration, module: &mut Mod
0b101 => (Some(VectorSize::Tri), Some(VectorSize::Tri)),
_ => (Some(VectorSize::Quad), Some(VectorSize::Quad)),
};
let kind = Sk::Float;
let scalar = Scalar::F64;
let args = vec![
match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
},
match second_size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
},
];
@ -1127,24 +1079,24 @@ fn inject_double_builtin(declaration: &mut FunctionDeclaration, module: &mut Mod
0b10 => Some(VectorSize::Tri),
_ => None,
};
let kind = Sk::Float;
let scalar = Scalar::F64;
let (splatted, boolean) = match bits >> 2 {
0b00 => (false, false),
0b01 => (false, true),
_ => (true, false),
};
let ty = |kind, width| match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
let ty = |scalar| match size {
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
};
let args = vec![
ty(kind, width),
ty(kind, width),
ty(scalar),
ty(scalar),
match (boolean, splatted) {
(true, _) => ty(Sk::Bool, crate::BOOL_WIDTH),
(_, false) => TypeInner::Scalar { kind, width },
_ => ty(kind, width),
(true, _) => ty(Scalar::BOOL),
(_, false) => TypeInner::Scalar(scalar),
_ => ty(scalar),
},
];
@ -1165,7 +1117,7 @@ fn inject_double_builtin(declaration: &mut FunctionDeclaration, module: &mut Mod
// 0b110 is the last element since splatted with single elements
// is equal to normal single elements
for bits in 0..0b111 {
let kind = Sk::Float;
let scalar = Scalar::F64;
let size = match bits & 0b11 {
0b00 => Some(VectorSize::Bi),
0b01 => Some(VectorSize::Tri),
@ -1175,11 +1127,11 @@ fn inject_double_builtin(declaration: &mut FunctionDeclaration, module: &mut Mod
let splatted = bits & 0b100 == 0b100;
let base_ty = || match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
};
let limit_ty = || match splatted {
true => TypeInner::Scalar { kind, width },
true => TypeInner::Scalar(scalar),
false => base_ty(),
};
@ -1192,14 +1144,15 @@ fn inject_double_builtin(declaration: &mut FunctionDeclaration, module: &mut Mod
}
"lessThan" | "greaterThan" | "lessThanEqual" | "greaterThanEqual" | "equal"
| "notEqual" => {
let scalar = Scalar::F64;
for bits in 0..0b11 {
let (size, kind) = match bits {
0b00 => (VectorSize::Bi, Sk::Float),
0b01 => (VectorSize::Tri, Sk::Float),
_ => (VectorSize::Quad, Sk::Float),
let size = match bits {
0b00 => VectorSize::Bi,
0b01 => VectorSize::Tri,
_ => VectorSize::Quad,
};
let ty = || TypeInner::Vector { size, kind, width };
let ty = || TypeInner::Vector { size, scalar };
let args = vec![ty(), ty()];
let fun = MacroCall::Binary(match name {
@ -1227,6 +1180,10 @@ fn inject_common_builtin(
name: &str,
float_width: crate::Bytes,
) {
let float_scalar = Scalar {
kind: Sk::Float,
width: float_width,
};
match name {
"ceil" | "round" | "roundEven" | "floor" | "fract" | "trunc" | "sqrt" | "inversesqrt"
| "normalize" | "length" | "isinf" | "isnan" => {
@ -1243,13 +1200,9 @@ fn inject_common_builtin(
let args = vec![match size {
Some(size) => TypeInner::Vector {
size,
kind: Sk::Float,
width: float_width,
},
None => TypeInner::Scalar {
kind: Sk::Float,
width: float_width,
scalar: float_scalar,
},
None => TypeInner::Scalar(float_scalar),
}];
let fun = match name {
@ -1280,16 +1233,9 @@ fn inject_common_builtin(
0b10 => Some(VectorSize::Tri),
_ => Some(VectorSize::Quad),
};
let ty = |kind| match size {
Some(size) => TypeInner::Vector {
size,
kind,
width: float_width,
},
None => TypeInner::Scalar {
kind,
width: float_width,
},
let ty = |scalar| match size {
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
};
let fun = match name {
@ -1300,15 +1246,18 @@ fn inject_common_builtin(
_ => unreachable!(),
};
let second_kind = if fun == MacroCall::MathFunction(MathFunction::Ldexp) {
Sk::Sint
let second_scalar = if fun == MacroCall::MathFunction(MathFunction::Ldexp) {
Scalar {
kind: Sk::Sint,
width: float_width,
}
} else {
Sk::Float
float_scalar
};
declaration
.overloads
.push(module.add_builtin(vec![ty(Sk::Float), ty(second_kind)], fun))
.push(module.add_builtin(vec![ty(Scalar::F32), ty(second_scalar)], fun))
}
}
"transpose" => {
@ -1389,13 +1338,9 @@ fn inject_common_builtin(
args.push(match maybe_size {
Some(size) => TypeInner::Vector {
size,
kind: Sk::Float,
width: float_width,
},
None => TypeInner::Scalar {
kind: Sk::Float,
width: float_width,
scalar: float_scalar,
},
None => TypeInner::Scalar(float_scalar),
})
}
@ -1414,13 +1359,11 @@ fn inject_common_builtin(
let args = vec![
TypeInner::Vector {
size: VectorSize::Tri,
kind: Sk::Float,
width: float_width,
scalar: float_scalar,
},
TypeInner::Vector {
size: VectorSize::Tri,
kind: Sk::Float,
width: float_width,
scalar: float_scalar,
},
];
@ -1447,13 +1390,11 @@ fn inject_common_builtin(
let args = vec![
TypeInner::Vector {
size: size1,
kind: Sk::Float,
width: float_width,
scalar: float_scalar,
},
TypeInner::Vector {
size: size2,
kind: Sk::Float,
width: float_width,
scalar: float_scalar,
},
];
@ -1476,13 +1417,9 @@ fn inject_common_builtin(
let ty = || match size {
Some(size) => TypeInner::Vector {
size,
kind: Sk::Float,
width: float_width,
},
None => TypeInner::Scalar {
kind: Sk::Float,
width: float_width,
scalar: float_scalar,
},
None => TypeInner::Scalar(float_scalar),
};
let args = vec![ty(), ty(), ty()];
@ -1509,22 +1446,11 @@ fn inject_common_builtin(
let ty = || match size {
Some(size) => TypeInner::Vector {
size,
kind: Sk::Float,
width: float_width,
},
None => TypeInner::Scalar {
kind: Sk::Float,
width: float_width,
scalar: float_scalar,
},
None => TypeInner::Scalar(float_scalar),
};
let args = vec![
ty(),
ty(),
TypeInner::Scalar {
kind: Sk::Float,
width: 4,
},
];
let args = vec![ty(), ty(), TypeInner::Scalar(Scalar::F32)];
declaration
.overloads
.push(module.add_builtin(args, MacroCall::MathFunction(MathFunction::Refract)))
@ -1549,19 +1475,12 @@ fn inject_common_builtin(
let base_ty = || match size {
Some(size) => TypeInner::Vector {
size,
kind: Sk::Float,
width: float_width,
},
None => TypeInner::Scalar {
kind: Sk::Float,
width: float_width,
scalar: float_scalar,
},
None => TypeInner::Scalar(float_scalar),
};
let ty = || match splatted {
true => TypeInner::Scalar {
kind: Sk::Float,
width: float_width,
},
true => TypeInner::Scalar(float_scalar),
false => base_ty(),
};
declaration.overloads.push(module.add_builtin(
@ -1810,8 +1729,7 @@ impl MacroCall {
name: None,
inner: TypeInner::Vector {
size,
kind: crate::ScalarKind::Uint,
width: 4,
scalar: Scalar::U32,
},
},
Span::default(),
@ -2100,7 +2018,7 @@ fn texture_call(
let mut array_index = comps.array_index;
if let Some(ref mut array_index_expr) = array_index {
ctx.conversion(array_index_expr, meta, Sk::Sint, 4)?;
ctx.conversion(array_index_expr, meta, Scalar::I32)?;
}
Ok(ctx.add_expression(

View File

@ -9,8 +9,8 @@ use super::{
};
use crate::{
front::Typifier, proc::Emitter, AddressSpace, Arena, BinaryOperator, Block, Expression,
FastHashMap, FunctionArgument, Handle, Literal, LocalVariable, RelationalFunction, ScalarKind,
Span, Statement, Type, TypeInner, VectorSize,
FastHashMap, FunctionArgument, Handle, Literal, LocalVariable, RelationalFunction, Scalar,
ScalarKind, Span, Statement, Type, TypeInner, VectorSize,
};
use std::ops::Index;
@ -602,7 +602,7 @@ impl<'a> Context<'a> {
match op {
BinaryOperator::ShiftLeft | BinaryOperator::ShiftRight => {
self.implicit_conversion(&mut right, right_meta, ScalarKind::Uint, 4)?
self.implicit_conversion(&mut right, right_meta, Scalar::U32)?
}
_ => self
.binary_implicit_conversion(&mut left, left_meta, &mut right, right_meta)?,
@ -824,9 +824,9 @@ impl<'a> Context<'a> {
_ => self.add_expression(Expression::Binary { left, op, right }, meta)?,
},
(
&TypeInner::Scalar {
&TypeInner::Scalar(Scalar {
width: left_width, ..
},
}),
&TypeInner::Matrix {
rows,
columns,
@ -911,9 +911,9 @@ impl<'a> Context<'a> {
columns,
width: left_width,
},
&TypeInner::Scalar {
&TypeInner::Scalar(Scalar {
width: right_width, ..
},
}),
) => {
// Check that the two arguments have the same width
if left_width != right_width {
@ -1100,37 +1100,24 @@ impl<'a> Context<'a> {
// We need to do some custom implicit conversions since the two target expressions
// are in different bodies
if let (
Some((accept_power, accept_width, accept_kind)),
Some((reject_power, reject_width, reject_kind)),
) = (
if let (Some((accept_power, accept_scalar)), Some((reject_power, reject_scalar))) = (
// Get the components of both branches and calculate the type power
self.expr_scalar_components(accept, accept_meta)?
.and_then(|(kind, width)| Some((type_power(kind, width)?, width, kind))),
.and_then(|scalar| Some((type_power(scalar)?, scalar))),
self.expr_scalar_components(reject, reject_meta)?
.and_then(|(kind, width)| Some((type_power(kind, width)?, width, kind))),
.and_then(|scalar| Some((type_power(scalar)?, scalar))),
) {
match accept_power.cmp(&reject_power) {
std::cmp::Ordering::Less => {
accept_body = self.with_body(accept_body, |ctx| {
ctx.conversion(
&mut accept,
accept_meta,
reject_kind,
reject_width,
)?;
ctx.conversion(&mut accept, accept_meta, reject_scalar)?;
Ok(())
})?;
}
std::cmp::Ordering::Equal => {}
std::cmp::Ordering::Greater => {
reject_body = self.with_body(reject_body, |ctx| {
ctx.conversion(
&mut reject,
reject_meta,
accept_kind,
accept_width,
)?;
ctx.conversion(&mut reject, reject_meta, accept_scalar)?;
Ok(())
})?;
}
@ -1201,8 +1188,8 @@ impl<'a> Context<'a> {
ref ty => ty,
};
if let Some((kind, width)) = scalar_components(ty) {
self.implicit_conversion(&mut value, value_meta, kind, width)?;
if let Some(scalar) = scalar_components(ty) {
self.implicit_conversion(&mut value, value_meta, scalar)?;
}
self.lower_store(pointer, value, meta)?;
@ -1218,13 +1205,13 @@ impl<'a> Context<'a> {
};
let res = match *self.resolve_type(left, meta)? {
TypeInner::Scalar { kind, width } => {
let ty = TypeInner::Scalar { kind, width };
Literal::one(kind, width).map(|i| (ty, i, None, None))
TypeInner::Scalar(scalar) => {
let ty = TypeInner::Scalar(scalar);
Literal::one(scalar).map(|i| (ty, i, None, None))
}
TypeInner::Vector { size, kind, width } => {
let ty = TypeInner::Vector { size, kind, width };
Literal::one(kind, width).map(|i| (ty, i, Some(size), None))
TypeInner::Vector { size, scalar } => {
let ty = TypeInner::Vector { size, scalar };
Literal::one(scalar).map(|i| (ty, i, Some(size), None))
}
TypeInner::Matrix {
columns,
@ -1236,8 +1223,11 @@ impl<'a> Context<'a> {
rows,
width,
};
Literal::one(ScalarKind::Float, width)
.map(|i| (ty, i, Some(rows), Some(columns)))
Literal::one(Scalar {
kind: ScalarKind::Float,
width,
})
.map(|i| (ty, i, Some(rows), Some(columns)))
}
_ => None,
};
@ -1323,19 +1313,14 @@ impl<'a> Context<'a> {
Expression::Literal(Literal::U32(size.get())),
meta,
)?;
self.forced_conversion(
&mut array_length,
meta,
ScalarKind::Sint,
4,
)?;
self.forced_conversion(&mut array_length, meta, Scalar::I32)?;
array_length
}
// let the error be handled in type checking if it's not a dynamic array
_ => {
let mut array_length = self
.add_expression(Expression::ArrayLength(lowered_array), meta)?;
self.conversion(&mut array_length, meta, ScalarKind::Sint, 4)?;
self.conversion(&mut array_length, meta, Scalar::I32)?;
array_length
}
}
@ -1376,7 +1361,7 @@ impl<'a> Context<'a> {
&mut self,
expr: Handle<Expression>,
meta: Span,
) -> Result<Option<(ScalarKind, crate::Bytes)>> {
) -> Result<Option<Scalar>> {
let ty = self.resolve_type(expr, meta)?;
Ok(scalar_components(ty))
}
@ -1384,21 +1369,20 @@ impl<'a> Context<'a> {
pub fn expr_power(&mut self, expr: Handle<Expression>, meta: Span) -> Result<Option<u32>> {
Ok(self
.expr_scalar_components(expr, meta)?
.and_then(|(kind, width)| type_power(kind, width)))
.and_then(type_power))
}
pub fn conversion(
&mut self,
expr: &mut Handle<Expression>,
meta: Span,
kind: ScalarKind,
width: crate::Bytes,
scalar: Scalar,
) -> Result<()> {
*expr = self.add_expression(
Expression::As {
expr: *expr,
kind,
convert: Some(width),
kind: scalar.kind,
convert: Some(scalar.width),
},
meta,
)?;
@ -1410,14 +1394,13 @@ impl<'a> Context<'a> {
&mut self,
expr: &mut Handle<Expression>,
meta: Span,
kind: ScalarKind,
width: crate::Bytes,
scalar: Scalar,
) -> Result<()> {
if let (Some(tgt_power), Some(expr_power)) =
(type_power(kind, width), self.expr_power(*expr, meta)?)
(type_power(scalar), self.expr_power(*expr, meta)?)
{
if tgt_power > expr_power {
self.conversion(expr, meta, kind, width)?;
self.conversion(expr, meta, scalar)?;
}
}
@ -1428,12 +1411,11 @@ impl<'a> Context<'a> {
&mut self,
expr: &mut Handle<Expression>,
meta: Span,
kind: ScalarKind,
width: crate::Bytes,
scalar: Scalar,
) -> Result<()> {
if let Some((expr_scalar_kind, expr_width)) = self.expr_scalar_components(*expr, meta)? {
if expr_scalar_kind != kind || expr_width != width {
self.conversion(expr, meta, kind, width)?;
if let Some(expr_scalar) = self.expr_scalar_components(*expr, meta)? {
if expr_scalar != scalar {
self.conversion(expr, meta, scalar)?;
}
}
@ -1450,21 +1432,17 @@ impl<'a> Context<'a> {
let left_components = self.expr_scalar_components(*left, left_meta)?;
let right_components = self.expr_scalar_components(*right, right_meta)?;
if let (
Some((left_power, left_width, left_kind)),
Some((right_power, right_width, right_kind)),
) = (
left_components.and_then(|(kind, width)| Some((type_power(kind, width)?, width, kind))),
right_components
.and_then(|(kind, width)| Some((type_power(kind, width)?, width, kind))),
if let (Some((left_power, left_scalar)), Some((right_power, right_scalar))) = (
left_components.and_then(|scalar| Some((type_power(scalar)?, scalar))),
right_components.and_then(|scalar| Some((type_power(scalar)?, scalar))),
) {
match left_power.cmp(&right_power) {
std::cmp::Ordering::Less => {
self.conversion(left, left_meta, right_kind, right_width)?;
self.conversion(left, left_meta, right_scalar)?;
}
std::cmp::Ordering::Equal => {}
std::cmp::Ordering::Greater => {
self.conversion(right, right_meta, left_kind, left_width)?;
self.conversion(right, right_meta, left_scalar)?;
}
}
}

View File

@ -8,7 +8,7 @@ use super::{
};
use crate::{
front::glsl::types::type_power, proc::ensure_block_returns, AddressSpace, Block, EntryPoint,
Expression, Function, FunctionArgument, FunctionResult, Handle, Literal, LocalVariable,
Expression, Function, FunctionArgument, FunctionResult, Handle, Literal, LocalVariable, Scalar,
ScalarKind, Span, Statement, StructMember, Type, TypeInner,
};
use std::iter;
@ -20,7 +20,7 @@ struct ProxyWrite {
/// A pointer to read the value of the store
value: Handle<Expression>,
/// An optional conversion to be applied
convert: Option<(ScalarKind, crate::Bytes)>,
convert: Option<Scalar>,
}
impl Frontend {
@ -68,10 +68,14 @@ impl Frontend {
let expr_is_bool = expr_type.scalar_kind() == Some(ScalarKind::Bool);
// Special case: if casting from a bool, we need to use Select and not As.
match ctx.module.types[ty].inner.scalar_kind() {
Some(result_scalar_kind) if expr_is_bool && result_scalar_kind != ScalarKind::Bool => {
let l0 = Literal::zero(result_scalar_kind, 4).unwrap();
let l1 = Literal::one(result_scalar_kind, 4).unwrap();
match ctx.module.types[ty].inner.scalar() {
Some(result_scalar) if expr_is_bool && result_scalar.kind != ScalarKind::Bool => {
let result_scalar = Scalar {
width: 4,
..result_scalar
};
let l0 = Literal::zero(result_scalar).unwrap();
let l1 = Literal::one(result_scalar).unwrap();
let mut reject = ctx.add_expression(Expression::Literal(l0), expr_meta)?;
let mut accept = ctx.add_expression(Expression::Literal(l1), expr_meta)?;
@ -93,24 +97,16 @@ impl Frontend {
}
Ok(match ctx.module.types[ty].inner {
TypeInner::Vector { size, kind, width } if vector_size.is_none() => {
ctx.forced_conversion(&mut value, expr_meta, kind, width)?;
TypeInner::Vector { size, scalar } if vector_size.is_none() => {
ctx.forced_conversion(&mut value, expr_meta, scalar)?;
if let TypeInner::Scalar { .. } = *ctx.resolve_type(value, expr_meta)? {
ctx.add_expression(Expression::Splat { size, value }, meta)?
} else {
self.vector_constructor(
ctx,
ty,
size,
kind,
width,
&[(value, expr_meta)],
meta,
)?
self.vector_constructor(ctx, ty, size, scalar, &[(value, expr_meta)], meta)?
}
}
TypeInner::Scalar { kind, width } => {
TypeInner::Scalar(scalar) => {
let mut expr = value;
if let TypeInner::Vector { .. } | TypeInner::Matrix { .. } =
*ctx.resolve_type(value, expr_meta)?
@ -136,23 +132,23 @@ impl Frontend {
ctx.add_expression(
Expression::As {
kind,
kind: scalar.kind,
expr,
convert: Some(width),
convert: Some(scalar.width),
},
meta,
)?
}
TypeInner::Vector { size, kind, width } => {
TypeInner::Vector { size, scalar } => {
if vector_size.map_or(true, |s| s != size) {
value = ctx.vector_resize(size, value, expr_meta)?;
}
ctx.add_expression(
Expression::As {
kind,
kind: scalar.kind,
expr: value,
convert: Some(width),
convert: Some(scalar.width),
},
meta,
)?
@ -166,8 +162,8 @@ impl Frontend {
let scalar_components = members
.get(0)
.and_then(|member| scalar_components(&ctx.module.types[member.ty].inner));
if let Some((kind, width)) = scalar_components {
ctx.implicit_conversion(&mut value, expr_meta, kind, width)?;
if let Some(scalar) = scalar_components {
ctx.implicit_conversion(&mut value, expr_meta, scalar)?;
}
ctx.add_expression(
@ -181,8 +177,8 @@ impl Frontend {
TypeInner::Array { base, .. } => {
let scalar_components = scalar_components(&ctx.module.types[base].inner);
if let Some((kind, width)) = scalar_components {
ctx.implicit_conversion(&mut value, expr_meta, kind, width)?;
if let Some(scalar) = scalar_components {
ctx.implicit_conversion(&mut value, expr_meta, scalar)?;
}
ctx.add_expression(
@ -220,9 +216,13 @@ impl Frontend {
// `Expression::As` doesn't support matrix width
// casts so we need to do some extra work for casts
ctx.forced_conversion(&mut value, expr_meta, ScalarKind::Float, width)?;
let element_scalar = Scalar {
kind: ScalarKind::Float,
width,
};
ctx.forced_conversion(&mut value, expr_meta, element_scalar)?;
match *ctx.resolve_type(value, expr_meta)? {
TypeInner::Scalar { .. } => {
TypeInner::Scalar(_) => {
// If a matrix is constructed with a single scalar value, then that
// value is used to initialize all the values along the diagonal of
// the matrix; the rest are given zeros.
@ -231,14 +231,13 @@ impl Frontend {
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
scalar: element_scalar,
},
},
meta,
);
let zero_literal = Literal::zero(ScalarKind::Float, width).unwrap();
let zero_literal = Literal::zero(element_scalar).unwrap();
let zero = ctx.add_expression(Expression::Literal(zero_literal), meta)?;
for i in 0..columns as u32 {
@ -268,8 +267,8 @@ impl Frontend {
// (column i, row j) in the argument will be initialized from there. All
// other components will be initialized to the identity matrix.
let zero_literal = Literal::zero(ScalarKind::Float, width).unwrap();
let one_literal = Literal::one(ScalarKind::Float, width).unwrap();
let zero_literal = Literal::zero(element_scalar).unwrap();
let one_literal = Literal::one(element_scalar).unwrap();
let zero = ctx.add_expression(Expression::Literal(zero_literal), meta)?;
let one = ctx.add_expression(Expression::Literal(one_literal), meta)?;
@ -279,8 +278,7 @@ impl Frontend {
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
scalar: element_scalar,
},
},
meta,
@ -360,15 +358,14 @@ impl Frontend {
ctx: &mut Context,
ty: Handle<Type>,
size: crate::VectorSize,
kind: ScalarKind,
width: crate::Bytes,
scalar: Scalar,
args: &[(Handle<Expression>, Span)],
meta: Span,
) -> Result<Handle<Expression>> {
let mut components = Vec::with_capacity(size as usize);
for (mut arg, expr_meta) in args.iter().copied() {
ctx.forced_conversion(&mut arg, expr_meta, kind, width)?;
ctx.forced_conversion(&mut arg, expr_meta, scalar)?;
if components.len() >= size as usize {
break;
@ -429,8 +426,12 @@ impl Frontend {
} => {
let mut flattened = Vec::with_capacity(columns as usize * rows as usize);
let element_scalar = Scalar {
kind: ScalarKind::Float,
width,
};
for (mut arg, meta) in args.iter().copied() {
ctx.forced_conversion(&mut arg, meta, ScalarKind::Float, width)?;
ctx.forced_conversion(&mut arg, meta, element_scalar)?;
match *ctx.resolve_type(arg, meta)? {
TypeInner::Vector { size, .. } => {
@ -453,8 +454,7 @@ impl Frontend {
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
scalar: element_scalar,
},
},
meta,
@ -471,14 +471,14 @@ impl Frontend {
}
None
}
TypeInner::Vector { size, kind, width } => {
return self.vector_constructor(ctx, ty, size, kind, width, &args, meta)
TypeInner::Vector { size, scalar } => {
return self.vector_constructor(ctx, ty, size, scalar, &args, meta)
}
TypeInner::Array { base, .. } => {
for (mut arg, meta) in args.iter().copied() {
let scalar_components = scalar_components(&ctx.module.types[base].inner);
if let Some((kind, width)) = scalar_components {
ctx.implicit_conversion(&mut arg, meta, kind, width)?;
if let Some(scalar) = scalar_components {
ctx.implicit_conversion(&mut arg, meta, scalar)?;
}
components.push(arg)
@ -503,8 +503,8 @@ impl Frontend {
for ((mut arg, meta), scalar_components) in
args.iter().copied().zip(struct_member_data.iter().copied())
{
if let Some((kind, width)) = scalar_components {
ctx.implicit_conversion(&mut arg, meta, kind, width)?;
if let Some(scalar) = scalar_components {
ctx.implicit_conversion(&mut arg, meta, scalar)?;
}
components.push(arg)
@ -813,8 +813,8 @@ impl Frontend {
let scalar_comps = scalar_components(&ctx.module.types[*parameter].inner);
// Apply implicit conversions as needed
if let Some((kind, width)) = scalar_comps {
ctx.implicit_conversion(&mut handle, meta, kind, width)?;
if let Some(scalar) = scalar_comps {
ctx.implicit_conversion(&mut handle, meta, scalar)?;
}
arguments.push(handle)
@ -850,8 +850,8 @@ impl Frontend {
meta,
)?;
if let Some((kind, width)) = proxy_write.convert {
ctx.conversion(&mut value, meta, kind, width)?;
if let Some(scalar) = proxy_write.convert {
ctx.conversion(&mut value, meta, scalar)?;
}
ctx.emit_restart();
@ -893,10 +893,10 @@ impl Frontend {
// If the argument is to be passed as a pointer but the type of the
// expression returns a vector it must mean that it was for example
// swizzled and it must be spilled into a local before calling
TypeInner::Vector { size, kind, width } => Some(ctx.module.types.insert(
TypeInner::Vector { size, scalar } => Some(ctx.module.types.insert(
Type {
name: None,
inner: TypeInner::Vector { size, kind, width },
inner: TypeInner::Vector { size, scalar },
},
Span::default(),
)),
@ -906,13 +906,12 @@ impl Frontend {
TypeInner::Pointer { base, space } if space != AddressSpace::Function => Some(base),
TypeInner::ValuePointer {
size,
kind,
width,
scalar,
space,
} if space != AddressSpace::Function => {
let inner = match size {
Some(size) => TypeInner::Vector { size, kind, width },
None => TypeInner::Scalar { kind, width },
Some(size) => TypeInner::Vector { size, scalar },
None => TypeInner::Scalar(scalar),
};
Some(
@ -1512,31 +1511,22 @@ fn conversion(target: &TypeInner, source: &TypeInner) -> Option<Conversion> {
use ScalarKind::*;
// Gather the `ScalarKind` and scalar width from both the target and the source
let (target_kind, target_width, source_kind, source_width) = match (target, source) {
let (target_scalar, source_scalar) = match (target, source) {
// Conversions between scalars are allowed
(
&TypeInner::Scalar {
kind: tgt_kind,
width: tgt_width,
},
&TypeInner::Scalar {
kind: src_kind,
width: src_width,
},
) => (tgt_kind, tgt_width, src_kind, src_width),
(&TypeInner::Scalar(tgt_scalar), &TypeInner::Scalar(src_scalar)) => {
(tgt_scalar, src_scalar)
}
// Conversions between vectors of the same size are allowed
(
&TypeInner::Vector {
kind: tgt_kind,
size: tgt_size,
width: tgt_width,
scalar: tgt_scalar,
},
&TypeInner::Vector {
kind: src_kind,
size: src_size,
width: src_width,
scalar: src_scalar,
},
) if tgt_size == src_size => (tgt_kind, tgt_width, src_kind, src_width),
) if tgt_size == src_size => (tgt_scalar, src_scalar),
// Conversions between matrices of the same size are allowed
(
&TypeInner::Matrix {
@ -1549,29 +1539,63 @@ fn conversion(target: &TypeInner, source: &TypeInner) -> Option<Conversion> {
columns: src_cols,
width: src_width,
},
) if tgt_cols == src_cols && tgt_rows == src_rows => (Float, tgt_width, Float, src_width),
) if tgt_cols == src_cols && tgt_rows == src_rows => (
Scalar {
kind: Float,
width: tgt_width,
},
Scalar {
kind: Float,
width: src_width,
},
),
_ => return None,
};
// Check if source can be converted into target, if this is the case then the type
// power of target must be higher than that of source
let target_power = type_power(target_kind, target_width);
let source_power = type_power(source_kind, source_width);
let target_power = type_power(target_scalar);
let source_power = type_power(source_scalar);
if target_power < source_power {
return None;
}
Some(
match ((target_kind, target_width), (source_kind, source_width)) {
// A conversion from a float to a double is special
((Float, 8), (Float, 4)) => Conversion::FloatToDouble,
// A conversion from an integer to a float is special
((Float, 4), (Sint | Uint, _)) => Conversion::IntToFloat,
// A conversion from an integer to a double is special
((Float, 8), (Sint | Uint, _)) => Conversion::IntToDouble,
_ => Conversion::Other,
},
)
Some(match (target_scalar, source_scalar) {
// A conversion from a float to a double is special
(
Scalar {
kind: Float,
width: 8,
},
Scalar {
kind: Float,
width: 4,
},
) => Conversion::FloatToDouble,
// A conversion from an integer to a float is special
(
Scalar {
kind: Float,
width: 4,
},
Scalar {
kind: Sint | Uint,
width: _,
},
) => Conversion::IntToFloat,
// A conversion from an integer to a double is special
(
Scalar {
kind: Float,
width: 8,
},
Scalar {
kind: Sint | Uint,
width: _,
},
) => Conversion::IntToDouble,
_ => Conversion::Other,
})
}
/// Helper method returning all the non standard builtin variations needed
@ -1581,10 +1605,10 @@ fn builtin_required_variations<'a>(args: impl Iterator<Item = &'a TypeInner>) ->
for ty in args {
match *ty {
TypeInner::ValuePointer { kind, width, .. }
| TypeInner::Scalar { kind, width }
| TypeInner::Vector { kind, width, .. } => {
if kind == ScalarKind::Float && width == 8 {
TypeInner::ValuePointer { scalar, .. }
| TypeInner::Scalar(scalar)
| TypeInner::Vector { scalar, .. } => {
if scalar.kind == ScalarKind::Float && scalar.width == 8 {
variations |= BuiltinVariations::DOUBLE
}
}

View File

@ -16,7 +16,7 @@ use super::{
error::{Error, ErrorKind},
Span,
};
use crate::{proc::Alignment, Handle, Type, TypeInner, UniqueArena};
use crate::{proc::Alignment, Handle, Scalar, Type, TypeInner, UniqueArena};
/// Struct with information needed for defining a struct member.
///
@ -53,12 +53,15 @@ pub fn calculate_offset(
let (align, span) = match types[ty].inner {
// 1. If the member is a scalar consuming N basic machine units,
// the base alignment is N.
TypeInner::Scalar { width, .. } => (Alignment::from_width(width), width as u32),
TypeInner::Scalar(Scalar { width, .. }) => (Alignment::from_width(width), width as u32),
// 2. If the member is a two- or four-component vector with components
// consuming N basic machine units, the base alignment is 2N or 4N, respectively.
// 3. If the member is a three-component vector with components consuming N
// basic machine units, the base alignment is 4N.
TypeInner::Vector { size, width, .. } => (
TypeInner::Vector {
size,
scalar: Scalar { width, .. },
} => (
Alignment::from(size) * Alignment::from_width(width),
size as u32 * width as u32,
),

View File

@ -13,8 +13,8 @@ use crate::{
Error, ErrorKind, Frontend, Span,
},
proc::Alignment,
AddressSpace, Expression, FunctionResult, Handle, ScalarKind, Statement, StructMember, Type,
TypeInner,
AddressSpace, Expression, FunctionResult, Handle, Scalar, ScalarKind, Statement, StructMember,
Type, TypeInner,
};
use super::{DeclarationContext, ParsingContext, Result};
@ -34,10 +34,10 @@ fn element_or_member_type(
) -> Handle<Type> {
match types[ty].inner {
// The child type of a vector is a scalar of the same kind and width
TypeInner::Vector { kind, width, .. } => types.insert(
TypeInner::Vector { scalar, .. } => types.insert(
Type {
name: None,
inner: TypeInner::Scalar { kind, width },
inner: TypeInner::Scalar(scalar),
},
Default::default(),
),
@ -48,8 +48,10 @@ fn element_or_member_type(
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
scalar: Scalar {
kind: ScalarKind::Float,
width,
},
},
},
Default::default(),
@ -156,8 +158,8 @@ impl<'source> ParsingContext<'source> {
let (mut init, init_meta) = ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?;
let scalar_components = scalar_components(&ctx.module.types[ty].inner);
if let Some((kind, width)) = scalar_components {
ctx.implicit_conversion(&mut init, init_meta, kind, width)?;
if let Some(scalar) = scalar_components {
ctx.implicit_conversion(&mut init, init_meta, scalar)?;
}
Ok((init, init_meta))
@ -233,9 +235,8 @@ impl<'source> ParsingContext<'source> {
let (mut expr, init_meta) = self.parse_initializer(frontend, ty, ctx.ctx)?;
let scalar_components = scalar_components(&ctx.ctx.module.types[ty].inner);
if let Some((kind, width)) = scalar_components {
ctx.ctx
.implicit_conversion(&mut expr, init_meta, kind, width)?;
if let Some(scalar) = scalar_components {
ctx.ctx.implicit_conversion(&mut expr, init_meta, scalar)?;
}
ctx.ctx.is_const = prev_const;
@ -509,10 +510,10 @@ impl<'source> ParsingContext<'source> {
let (ty, meta) = self.parse_type_non_void(frontend, ctx)?;
match ctx.module.types[ty].inner {
TypeInner::Scalar {
TypeInner::Scalar(Scalar {
kind: ScalarKind::Float | ScalarKind::Sint,
..
} => {}
}) => {}
_ => frontend.errors.push(Error {
kind: ErrorKind::SemanticError(
"Precision statement can only work on floats and ints".into(),

View File

@ -509,7 +509,7 @@ fn functions() {
#[test]
fn constants() {
use crate::{Constant, Expression, ScalarKind, Type, TypeInner};
use crate::{Constant, Expression, Type, TypeInner};
let mut frontend = Frontend::default();
@ -536,10 +536,7 @@ fn constants() {
ty,
&Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Float,
width: 4
}
inner: TypeInner::Scalar(crate::Scalar::F32)
}
);

View File

@ -1,6 +1,6 @@
use super::{context::Context, Error, ErrorKind, Result, Span};
use crate::{
proc::ResolveContext, Bytes, Expression, Handle, ImageClass, ImageDimension, ScalarKind, Type,
proc::ResolveContext, Expression, Handle, ImageClass, ImageDimension, Scalar, ScalarKind, Type,
TypeInner, VectorSize,
};
@ -8,38 +8,23 @@ pub fn parse_type(type_name: &str) -> Option<Type> {
match type_name {
"bool" => Some(Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Bool,
width: crate::BOOL_WIDTH,
},
inner: TypeInner::Scalar(Scalar::BOOL),
}),
"float" => Some(Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Float,
width: 4,
},
inner: TypeInner::Scalar(Scalar::F32),
}),
"double" => Some(Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Float,
width: 8,
},
inner: TypeInner::Scalar(Scalar::F64),
}),
"int" => Some(Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Sint,
width: 4,
},
inner: TypeInner::Scalar(Scalar::I32),
}),
"uint" => Some(Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Uint,
width: 4,
},
inner: TypeInner::Scalar(Scalar::U32),
}),
"sampler" | "samplerShadow" => Some(Type {
name: None,
@ -48,13 +33,13 @@ pub fn parse_type(type_name: &str) -> Option<Type> {
},
}),
word => {
fn kind_width_parse(ty: &str) -> Option<(ScalarKind, u8)> {
fn kind_width_parse(ty: &str) -> Option<Scalar> {
Some(match ty {
"" => (ScalarKind::Float, 4),
"b" => (ScalarKind::Bool, crate::BOOL_WIDTH),
"i" => (ScalarKind::Sint, 4),
"u" => (ScalarKind::Uint, 4),
"d" => (ScalarKind::Float, 8),
"" => Scalar::F32,
"b" => Scalar::BOOL,
"i" => Scalar::I32,
"u" => Scalar::U32,
"d" => Scalar::F64,
_ => return None,
})
}
@ -73,12 +58,12 @@ pub fn parse_type(type_name: &str) -> Option<Type> {
let kind = iter.next()?;
let size = iter.next()?;
let (kind, width) = kind_width_parse(kind)?;
let scalar = kind_width_parse(kind)?;
let size = size_parse(size)?;
Some(Type {
name: None,
inner: TypeInner::Vector { size, kind, width },
inner: TypeInner::Vector { size, scalar },
})
};
@ -87,7 +72,7 @@ pub fn parse_type(type_name: &str) -> Option<Type> {
let kind = iter.next()?;
let size = iter.next()?;
let (_, width) = kind_width_parse(kind)?;
let Scalar { width, .. } = kind_width_parse(kind)?;
let (columns, rows) = if let Some(size) = size_parse(size) {
(size, size)
@ -204,21 +189,24 @@ pub fn parse_type(type_name: &str) -> Option<Type> {
}
}
pub const fn scalar_components(ty: &TypeInner) -> Option<(ScalarKind, Bytes)> {
pub const fn scalar_components(ty: &TypeInner) -> Option<Scalar> {
match *ty {
TypeInner::Scalar { kind, width } => Some((kind, width)),
TypeInner::Vector { kind, width, .. } => Some((kind, width)),
TypeInner::Matrix { width, .. } => Some((ScalarKind::Float, width)),
TypeInner::ValuePointer { kind, width, .. } => Some((kind, width)),
TypeInner::Scalar(scalar)
| TypeInner::Vector { scalar, .. }
| TypeInner::ValuePointer { scalar, .. } => Some(scalar),
TypeInner::Matrix { width, .. } => Some(Scalar {
kind: ScalarKind::Float,
width,
}),
_ => None,
}
}
pub const fn type_power(kind: ScalarKind, width: Bytes) -> Option<u32> {
Some(match kind {
pub const fn type_power(scalar: Scalar) -> Option<u32> {
Some(match scalar.kind {
ScalarKind::Sint => 0,
ScalarKind::Uint => 1,
ScalarKind::Float if width == 4 => 2,
ScalarKind::Float if scalar.width == 4 => 2,
ScalarKind::Float => 3,
ScalarKind::Bool => return None,
})

View File

@ -6,8 +6,8 @@ use super::{
};
use crate::{
AddressSpace, Binding, BuiltIn, Constant, Expression, GlobalVariable, Handle, Interpolation,
LocalVariable, ResourceBinding, ScalarKind, ShaderStage, SwizzleComponent, Type, TypeInner,
VectorSize,
LocalVariable, ResourceBinding, Scalar, ScalarKind, ShaderStage, SwizzleComponent, Type,
TypeInner, VectorSize,
};
pub struct VarDeclaration<'a, 'key> {
@ -109,8 +109,7 @@ impl Frontend {
"gl_Position" => BuiltInData {
inner: TypeInner::Vector {
size: VectorSize::Quad,
kind: ScalarKind::Float,
width: 4,
scalar: Scalar::F32,
},
builtin: BuiltIn::Position { invariant: false },
mutable: true,
@ -119,8 +118,7 @@ impl Frontend {
"gl_FragCoord" => BuiltInData {
inner: TypeInner::Vector {
size: VectorSize::Quad,
kind: ScalarKind::Float,
width: 4,
scalar: Scalar::F32,
},
builtin: BuiltIn::Position { invariant: false },
mutable: false,
@ -129,8 +127,7 @@ impl Frontend {
"gl_PointCoord" => BuiltInData {
inner: TypeInner::Vector {
size: VectorSize::Bi,
kind: ScalarKind::Float,
width: 4,
scalar: Scalar::F32,
},
builtin: BuiltIn::PointCoord,
mutable: false,
@ -143,8 +140,7 @@ impl Frontend {
| "gl_LocalInvocationID" => BuiltInData {
inner: TypeInner::Vector {
size: VectorSize::Tri,
kind: ScalarKind::Uint,
width: 4,
scalar: Scalar::U32,
},
builtin: match name {
"gl_GlobalInvocationID" => BuiltIn::GlobalInvocationId,
@ -158,19 +154,13 @@ impl Frontend {
storage: StorageQualifier::Input,
},
"gl_FrontFacing" => BuiltInData {
inner: TypeInner::Scalar {
kind: ScalarKind::Bool,
width: crate::BOOL_WIDTH,
},
inner: TypeInner::Scalar(Scalar::BOOL),
builtin: BuiltIn::FrontFacing,
mutable: false,
storage: StorageQualifier::Input,
},
"gl_PointSize" | "gl_FragDepth" => BuiltInData {
inner: TypeInner::Scalar {
kind: ScalarKind::Float,
width: 4,
},
inner: TypeInner::Scalar(Scalar::F32),
builtin: match name {
"gl_PointSize" => BuiltIn::PointSize,
"gl_FragDepth" => BuiltIn::FragDepth,
@ -183,10 +173,7 @@ impl Frontend {
let base = ctx.module.types.insert(
Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Float,
width: 4,
},
inner: TypeInner::Scalar(Scalar::F32),
},
meta,
);
@ -219,10 +206,7 @@ impl Frontend {
};
BuiltInData {
inner: TypeInner::Scalar {
kind: ScalarKind::Uint,
width: 4,
},
inner: TypeInner::Scalar(Scalar::U32),
builtin,
mutable: false,
storage: StorageQualifier::Input,

View File

@ -1,4 +1,7 @@
use crate::arena::{Handle, UniqueArena};
use crate::{
arena::{Handle, UniqueArena},
Scalar,
};
use super::{Error, LookupExpression, LookupHelper as _};
@ -61,8 +64,11 @@ fn extract_image_coordinates(
ctx: &mut super::BlockContext,
) -> (Handle<crate::Expression>, Option<Handle<crate::Expression>>) {
let (given_size, kind) = match ctx.type_arena[coordinate_ty].inner {
crate::TypeInner::Scalar { kind, .. } => (None, kind),
crate::TypeInner::Vector { size, kind, .. } => (Some(size), kind),
crate::TypeInner::Scalar(Scalar { kind, .. }) => (None, kind),
crate::TypeInner::Vector {
size,
scalar: Scalar { kind, .. },
} => (Some(size), kind),
ref other => unreachable!("Unexpected texture coordinate {:?}", other),
};
@ -73,8 +79,7 @@ fn extract_image_coordinates(
name: None,
inner: crate::TypeInner::Vector {
size,
kind,
width: 4,
scalar: Scalar { kind, width: 4 },
},
})
.expect("Required coordinate type should have been set up by `parse_type_image`!")

View File

@ -2829,22 +2829,22 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let value_lexp = self.lookup_expression.lookup(value_id)?;
let ty_lookup = self.lookup_type.lookup(result_type_id)?;
let (kind, width) = match ctx.type_arena[ty_lookup.handle].inner {
crate::TypeInner::Scalar { kind, width }
| crate::TypeInner::Vector { kind, width, .. } => (kind, width),
crate::TypeInner::Matrix { width, .. } => (crate::ScalarKind::Float, width),
let scalar = match ctx.type_arena[ty_lookup.handle].inner {
crate::TypeInner::Scalar(scalar)
| crate::TypeInner::Vector { scalar, .. } => scalar,
crate::TypeInner::Matrix { width, .. } => crate::Scalar::float(width),
_ => return Err(Error::InvalidAsType(ty_lookup.handle)),
};
let expr = crate::Expression::As {
expr: get_expr_handle!(value_id, value_lexp),
kind,
convert: if kind == crate::ScalarKind::Bool {
kind: scalar.kind,
convert: if scalar.kind == crate::ScalarKind::Bool {
Some(crate::BOOL_WIDTH)
} else if inst.op == Op::Bitcast {
None
} else {
Some(width)
Some(scalar.width)
},
};
self.lookup_expression.insert(
@ -3356,10 +3356,10 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let selector_lty = self.lookup_type.lookup(selector_lexp.type_id)?;
let selector_handle = get_expr_handle!(selector, selector_lexp);
let selector = match ctx.type_arena[selector_lty.handle].inner {
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Uint,
width: _,
} => {
}) => {
// IR expects a signed integer, so do a bitcast
ctx.expressions.append(
crate::Expression::As {
@ -3370,10 +3370,10 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
span,
)
}
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Sint,
width: _,
} => selector_handle,
}) => selector_handle,
ref other => unimplemented!("Unexpected selector {:?}", other),
};
@ -4244,10 +4244,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
self.switch(ModuleState::Type, inst.op)?;
inst.expect(2)?;
let id = self.next()?;
let inner = crate::TypeInner::Scalar {
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
};
let inner = crate::TypeInner::Scalar(crate::Scalar::BOOL);
self.lookup_type.insert(
id,
LookupType {
@ -4275,14 +4272,14 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let id = self.next()?;
let width = self.next()?;
let sign = self.next()?;
let inner = crate::TypeInner::Scalar {
let inner = crate::TypeInner::Scalar(crate::Scalar {
kind: match sign {
0 => crate::ScalarKind::Uint,
1 => crate::ScalarKind::Sint,
_ => return Err(Error::InvalidSign(sign)),
},
width: map_width(width)?,
};
});
self.lookup_type.insert(
id,
LookupType {
@ -4309,10 +4306,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
inst.expect(3)?;
let id = self.next()?;
let width = self.next()?;
let inner = crate::TypeInner::Scalar {
kind: crate::ScalarKind::Float,
width: map_width(width)?,
};
let inner = crate::TypeInner::Scalar(crate::Scalar::float(map_width(width)?));
self.lookup_type.insert(
id,
LookupType {
@ -4340,15 +4334,14 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let id = self.next()?;
let type_id = self.next()?;
let type_lookup = self.lookup_type.lookup(type_id)?;
let (kind, width) = match module.types[type_lookup.handle].inner {
crate::TypeInner::Scalar { kind, width } => (kind, width),
let scalar = match module.types[type_lookup.handle].inner {
crate::TypeInner::Scalar(scalar) => scalar,
_ => return Err(Error::InvalidInnerType(type_id)),
};
let component_count = self.next()?;
let inner = crate::TypeInner::Vector {
size: map_vector_size(component_count)?,
kind,
width,
scalar,
};
self.lookup_type.insert(
id,
@ -4381,10 +4374,10 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let vector_type_lookup = self.lookup_type.lookup(vector_type_id)?;
let inner = match module.types[vector_type_lookup.handle].inner {
crate::TypeInner::Vector { size, width, .. } => crate::TypeInner::Matrix {
crate::TypeInner::Vector { size, scalar } => crate::TypeInner::Matrix {
columns: map_vector_size(num_columns)?,
rows: size,
width,
width: scalar.width,
},
_ => return Err(Error::InvalidInnerType(vector_type_id)),
};
@ -4761,11 +4754,10 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
crate::Type {
name: None,
inner: {
let kind = crate::ScalarKind::Float;
let width = 4;
let scalar = crate::Scalar::F32;
match dim.required_coordinate_size() {
None => crate::TypeInner::Scalar { kind, width },
Some(size) => crate::TypeInner::Vector { size, kind, width },
None => crate::TypeInner::Scalar(scalar),
Some(size) => crate::TypeInner::Vector { size, scalar },
}
},
},
@ -4870,30 +4862,30 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let ty = type_lookup.handle;
let literal = match module.types[ty].inner {
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Uint,
width,
} => {
}) => {
let low = self.next()?;
match width {
4 => crate::Literal::U32(low),
_ => return Err(Error::InvalidTypeWidth(width as u32)),
}
}
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Sint,
width,
} => {
}) => {
let low = self.next()?;
match width {
4 => crate::Literal::I32(low as i32),
_ => return Err(Error::InvalidTypeWidth(width as u32)),
}
}
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Float,
width,
} => {
}) => {
let low = self.next()?;
match width {
4 => crate::Literal::F32(f32::from_bits(low)),
@ -5167,17 +5159,15 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
| crate::BuiltIn::SampleIndex
| crate::BuiltIn::VertexIndex
| crate::BuiltIn::PrimitiveIndex
| crate::BuiltIn::LocalInvocationIndex => Some(crate::TypeInner::Scalar {
kind: crate::ScalarKind::Uint,
width: 4,
}),
| crate::BuiltIn::LocalInvocationIndex => {
Some(crate::TypeInner::Scalar(crate::Scalar::U32))
}
crate::BuiltIn::GlobalInvocationId
| crate::BuiltIn::LocalInvocationId
| crate::BuiltIn::WorkGroupId
| crate::BuiltIn::WorkGroupSize => Some(crate::TypeInner::Vector {
size: crate::VectorSize::Tri,
kind: crate::ScalarKind::Uint,
width: 4,
scalar: crate::Scalar::U32,
}),
_ => None,
};

View File

@ -25,24 +25,17 @@ impl crate::Module {
return handle;
}
let width = 4;
let ty_flag = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar {
width,
kind: crate::ScalarKind::Uint,
},
inner: crate::TypeInner::Scalar(crate::Scalar::U32),
},
Span::UNDEFINED,
);
let ty_scalar = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar {
width,
kind: crate::ScalarKind::Float,
},
inner: crate::TypeInner::Scalar(crate::Scalar::F32),
},
Span::UNDEFINED,
);
@ -51,8 +44,7 @@ impl crate::Module {
name: None,
inner: crate::TypeInner::Vector {
size: crate::VectorSize::Tri,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::F32,
},
},
Span::UNDEFINED,
@ -127,24 +119,17 @@ impl crate::Module {
return handle;
}
let width = 4;
let ty_flag = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar {
width,
kind: crate::ScalarKind::Uint,
},
inner: crate::TypeInner::Scalar(crate::Scalar::U32),
},
Span::UNDEFINED,
);
let ty_scalar = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar {
width,
kind: crate::ScalarKind::Float,
},
inner: crate::TypeInner::Scalar(crate::Scalar::F32),
},
Span::UNDEFINED,
);
@ -152,9 +137,8 @@ impl crate::Module {
crate::Type {
name: None,
inner: crate::TypeInner::Vector {
width,
size: crate::VectorSize::Bi,
kind: crate::ScalarKind::Float,
scalar: crate::Scalar::F32,
},
},
Span::UNDEFINED,
@ -162,10 +146,7 @@ impl crate::Module {
let ty_bool = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar {
width: crate::BOOL_WIDTH,
kind: crate::ScalarKind::Bool,
},
inner: crate::TypeInner::Scalar(crate::Scalar::BOOL),
},
Span::UNDEFINED,
);
@ -175,7 +156,7 @@ impl crate::Module {
inner: crate::TypeInner::Matrix {
columns: crate::VectorSize::Quad,
rows: crate::VectorSize::Tri,
width,
width: 4,
},
},
Span::UNDEFINED,
@ -277,28 +258,26 @@ impl crate::Module {
}
let ty = match special_type {
crate::PredeclaredType::AtomicCompareExchangeWeakResult { kind, width } => {
crate::PredeclaredType::AtomicCompareExchangeWeakResult(scalar) => {
let bool_ty = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar {
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
},
inner: crate::TypeInner::Scalar(crate::Scalar::BOOL),
},
Span::UNDEFINED,
);
let scalar_ty = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar { kind, width },
inner: crate::TypeInner::Scalar(scalar),
},
Span::UNDEFINED,
);
crate::Type {
name: Some(format!(
"__atomic_compare_exchange_result<{kind:?},{width}>"
"__atomic_compare_exchange_result<{:?},{}>",
scalar.kind, scalar.width,
)),
inner: crate::TypeInner::Struct {
members: vec![
@ -323,10 +302,7 @@ impl crate::Module {
let float_ty = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar {
kind: crate::ScalarKind::Float,
width,
},
inner: crate::TypeInner::Scalar(crate::Scalar::float(width)),
},
Span::UNDEFINED,
);
@ -337,8 +313,7 @@ impl crate::Module {
name: None,
inner: crate::TypeInner::Vector {
size,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
},
},
Span::UNDEFINED,
@ -379,10 +354,7 @@ impl crate::Module {
let float_ty = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar {
kind: crate::ScalarKind::Float,
width,
},
inner: crate::TypeInner::Scalar(crate::Scalar::float(width)),
},
Span::UNDEFINED,
);
@ -390,10 +362,10 @@ impl crate::Module {
let int_ty = self.types.insert(
crate::Type {
name: None,
inner: crate::TypeInner::Scalar {
inner: crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Sint,
width,
},
}),
},
Span::UNDEFINED,
);
@ -404,8 +376,7 @@ impl crate::Module {
name: None,
inner: crate::TypeInner::Vector {
size,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
},
},
Span::UNDEFINED,
@ -415,8 +386,10 @@ impl crate::Module {
name: None,
inner: crate::TypeInner::Vector {
size,
kind: crate::ScalarKind::Sint,
width,
scalar: crate::Scalar {
kind: crate::ScalarKind::Sint,
width,
},
},
},
Span::UNDEFINED,

View File

@ -185,11 +185,11 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
ty_inner: &crate::TypeInner::Scalar { .. },
..
},
Constructor::Type((_, &crate::TypeInner::Scalar { kind, width })),
Constructor::Type((_, &crate::TypeInner::Scalar(scalar))),
) => crate::Expression::As {
expr: component,
kind,
convert: Some(width),
kind: scalar.kind,
convert: Some(scalar.width),
},
// Vector conversion (vector -> vector)
@ -203,14 +203,13 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
_,
&crate::TypeInner::Vector {
size: dst_size,
kind: dst_kind,
width: dst_width,
scalar: dst_scalar,
},
)),
) if dst_size == src_size => crate::Expression::As {
expr: component,
kind: dst_kind,
convert: Some(dst_width),
kind: dst_scalar.kind,
convert: Some(dst_scalar.width),
},
// Vector conversion (vector -> vector) - partial
@ -294,23 +293,17 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
(
Components::One {
component,
ty_inner:
&crate::TypeInner::Scalar {
kind: src_kind,
width: src_width,
..
},
ty_inner: &crate::TypeInner::Scalar(src_scalar),
..
},
Constructor::Type((
_,
&crate::TypeInner::Vector {
size,
kind: dst_kind,
width: dst_width,
scalar: dst_scalar,
},
)),
) if dst_kind == src_kind || dst_width == src_width => crate::Expression::Splat {
) if dst_scalar == src_scalar => crate::Expression::Splat {
size,
value: component,
},
@ -320,8 +313,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
Components::Many {
components,
first_component_ty_inner:
&crate::TypeInner::Scalar { kind, width }
| &crate::TypeInner::Vector { kind, width, .. },
&crate::TypeInner::Scalar(scalar) | &crate::TypeInner::Vector { scalar, .. },
..
},
Constructor::PartialVector { size },
@ -333,9 +325,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
&crate::TypeInner::Scalar { .. } | &crate::TypeInner::Vector { .. },
..
},
Constructor::Type((_, &crate::TypeInner::Vector { size, width, kind })),
Constructor::Type((_, &crate::TypeInner::Vector { size, scalar })),
) => {
let inner = crate::TypeInner::Vector { size, kind, width };
let inner = crate::TypeInner::Vector { size, scalar };
let ty = ctx.ensure_type_exists(inner);
crate::Expression::Compose { ty, components }
}
@ -344,7 +336,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
(
Components::Many {
components,
first_component_ty_inner: &crate::TypeInner::Scalar { width, .. },
first_component_ty_inner: &crate::TypeInner::Scalar(crate::Scalar { width, .. }),
..
},
Constructor::PartialMatrix { columns, rows },
@ -365,8 +357,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
)),
) => {
let vec_ty = ctx.ensure_type_exists(crate::TypeInner::Vector {
width,
kind: crate::ScalarKind::Float,
scalar: crate::Scalar::float(width),
size: rows,
});
@ -395,7 +386,11 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
(
Components::Many {
components,
first_component_ty_inner: &crate::TypeInner::Vector { width, .. },
first_component_ty_inner:
&crate::TypeInner::Vector {
scalar: crate::Scalar { width, .. },
..
},
..
},
Constructor::PartialMatrix { columns, rows },

View File

@ -1413,22 +1413,19 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
};
let mut ectx = ctx.as_expression(block, &mut emitter);
let (kind, width) = match *resolve_inner!(ectx, target_handle) {
let scalar = match *resolve_inner!(ectx, target_handle) {
crate::TypeInner::ValuePointer {
size: None,
kind,
width,
..
} => (kind, width),
size: None, scalar, ..
} => scalar,
crate::TypeInner::Pointer { base, .. } => match ectx.module.types[base].inner {
crate::TypeInner::Scalar { kind, width } => (kind, width),
crate::TypeInner::Scalar(scalar) => scalar,
_ => return Err(Error::BadIncrDecrReferenceType(value_span)),
},
_ => return Err(Error::BadIncrDecrReferenceType(value_span)),
};
let literal = match kind {
let literal = match scalar.kind {
crate::ScalarKind::Sint | crate::ScalarKind::Uint => {
crate::Literal::one(kind, width)
crate::Literal::one(scalar)
.ok_or(Error::BadIncrDecrReferenceType(value_span))?
}
_ => return Err(Error::BadIncrDecrReferenceType(value_span)),
@ -1608,21 +1605,17 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
match *inner {
crate::TypeInner::Pointer { base, .. } => &ctx.module.types[base].inner,
crate::TypeInner::ValuePointer {
size: None,
kind,
width,
..
size: None, scalar, ..
} => {
temp_inner = crate::TypeInner::Scalar { kind, width };
temp_inner = crate::TypeInner::Scalar(scalar);
&temp_inner
}
crate::TypeInner::ValuePointer {
size: Some(size),
kind,
width,
scalar,
..
} => {
temp_inner = crate::TypeInner::Vector { size, kind, width };
temp_inner = crate::TypeInner::Vector { size, scalar };
&temp_inner
}
_ => unreachable!(
@ -1679,9 +1672,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let expr = self.expression(expr, ctx)?;
let to_resolved = self.resolve_ast_type(to, &mut ctx.as_global())?;
let kind = match ctx.module.types[to_resolved].inner {
crate::TypeInner::Scalar { kind, .. } => kind,
crate::TypeInner::Vector { kind, .. } => kind,
let element_scalar = match ctx.module.types[to_resolved].inner {
crate::TypeInner::Scalar(scalar) => scalar,
crate::TypeInner::Vector { scalar, .. } => scalar,
_ => {
let ty = resolve!(ctx, expr);
return Err(Error::BadTypeCast {
@ -1694,7 +1687,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
Typed::Plain(crate::Expression::As {
expr,
kind,
kind: element_scalar.kind,
convert: None,
})
}
@ -1785,10 +1778,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
) && {
matches!(
resolve_inner!(ctx, argument),
&crate::TypeInner::Scalar {
&crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Bool,
..
}
})
)
};
@ -1828,10 +1821,14 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
if fun == crate::MathFunction::Modf || fun == crate::MathFunction::Frexp {
if let Some((size, width)) = match *resolve_inner!(ctx, arg) {
crate::TypeInner::Scalar { width, .. } => Some((None, width)),
crate::TypeInner::Vector { size, width, .. } => {
Some((Some(size), width))
crate::TypeInner::Scalar(crate::Scalar { width, .. }) => {
Some((None, width))
}
crate::TypeInner::Vector {
size,
scalar: crate::Scalar { width, .. },
..
} => Some((Some(size), width)),
_ => None,
} {
ctx.module.generate_predeclared_type(
@ -1976,13 +1973,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
args.finish()?;
let expression = match *resolve_inner!(ctx, value) {
crate::TypeInner::Scalar { kind, width } => {
crate::TypeInner::Scalar(scalar) => {
crate::Expression::AtomicResult {
ty: ctx.module.generate_predeclared_type(
crate::PredeclaredType::AtomicCompareExchangeWeakResult {
kind,
width,
},
crate::PredeclaredType::AtomicCompareExchangeWeakResult(
scalar,
),
),
comparison: true,
}

View File

@ -17,6 +17,7 @@ use thiserror::Error;
pub use crate::front::wgsl::error::ParseError;
use crate::front::wgsl::lower::Lowerer;
use crate::Scalar;
pub struct Frontend {
parser: Parser,
@ -104,9 +105,8 @@ impl crate::TypeInner {
use crate::TypeInner as Ti;
match *self {
Ti::Scalar { kind, width } => Scalar { kind, width }.to_wgsl(),
Ti::Vector { size, kind, width } => {
let scalar = Scalar { kind, width };
Ti::Scalar(scalar) => scalar.to_wgsl(),
Ti::Vector { size, scalar } => {
format!("vec{}<{}>", size as u32, scalar.to_wgsl())
}
Ti::Matrix {
@ -118,23 +118,19 @@ impl crate::TypeInner {
"mat{}x{}<{}>",
columns as u32,
rows as u32,
Scalar {
kind: crate::ScalarKind::Float,
width
}
.to_wgsl(),
Scalar::float(width).to_wgsl(),
)
}
Ti::Atomic { kind, width } => {
format!("atomic<{}>", Scalar { kind, width }.to_wgsl())
Ti::Atomic(scalar) => {
format!("atomic<{}>", scalar.to_wgsl())
}
Ti::Pointer { base, .. } => {
let base = &gctx.types[base];
let name = base.name.as_deref().unwrap_or("unknown");
format!("ptr<{name}>")
}
Ti::ValuePointer { kind, width, .. } => {
format!("ptr<{}>", Scalar { kind, width }.to_wgsl())
Ti::ValuePointer { scalar, .. } => {
format!("ptr<{}>", scalar.to_wgsl())
}
Ti::Array { base, size, .. } => {
let member_type = &gctx.types[base];
@ -292,16 +288,6 @@ mod type_inner_tests {
}
}
/// Characteristics of a scalar type.
#[derive(Clone, Copy, Debug)]
pub struct Scalar {
/// How the value's bits are to be interpreted.
pub kind: crate::ScalarKind,
/// The size of the value in bytes.
pub width: crate::Bytes,
}
impl Scalar {
/// Format a scalar kind+width as a type is written in wgsl.
///
@ -315,26 +301,4 @@ impl Scalar {
};
format!("{}{}", prefix, self.width * 8)
}
const fn to_inner_scalar(self) -> crate::TypeInner {
crate::TypeInner::Scalar {
kind: self.kind,
width: self.width,
}
}
const fn to_inner_vector(self, size: crate::VectorSize) -> crate::TypeInner {
crate::TypeInner::Vector {
size,
kind: self.kind,
width: self.width,
}
}
const fn to_inner_atomic(self) -> crate::TypeInner {
crate::TypeInner::Atomic {
kind: self.kind,
width: self.width,
}
}
}

View File

@ -307,10 +307,7 @@ impl Parser {
"vec2f" => {
return Ok(Some(ast::ConstructorType::Vector {
size: crate::VectorSize::Bi,
scalar: Scalar {
kind: crate::ScalarKind::Float,
width: 4,
},
scalar: Scalar::F32,
}))
}
"vec3" => ast::ConstructorType::PartialVector {
@ -319,28 +316,19 @@ impl Parser {
"vec3i" => {
return Ok(Some(ast::ConstructorType::Vector {
size: crate::VectorSize::Tri,
scalar: Scalar {
kind: crate::ScalarKind::Sint,
width: 4,
},
scalar: Scalar::I32,
}))
}
"vec3u" => {
return Ok(Some(ast::ConstructorType::Vector {
size: crate::VectorSize::Tri,
scalar: Scalar {
kind: crate::ScalarKind::Uint,
width: 4,
},
scalar: Scalar::U32,
}))
}
"vec3f" => {
return Ok(Some(ast::ConstructorType::Vector {
size: crate::VectorSize::Tri,
scalar: Scalar {
kind: crate::ScalarKind::Float,
width: 4,
},
scalar: Scalar::F32,
}))
}
"vec4" => ast::ConstructorType::PartialVector {
@ -349,28 +337,19 @@ impl Parser {
"vec4i" => {
return Ok(Some(ast::ConstructorType::Vector {
size: crate::VectorSize::Quad,
scalar: Scalar {
kind: crate::ScalarKind::Sint,
width: 4,
},
scalar: Scalar::I32,
}))
}
"vec4u" => {
return Ok(Some(ast::ConstructorType::Vector {
size: crate::VectorSize::Quad,
scalar: Scalar {
kind: crate::ScalarKind::Uint,
width: 4,
},
scalar: Scalar::U32,
}))
}
"vec4f" => {
return Ok(Some(ast::ConstructorType::Vector {
size: crate::VectorSize::Quad,
scalar: Scalar {
kind: crate::ScalarKind::Float,
width: 4,
},
scalar: Scalar::F32,
}))
}
"mat2x2" => ast::ConstructorType::PartialMatrix {
@ -1109,10 +1088,7 @@ impl Parser {
},
"vec2f" => ast::Type::Vector {
size: crate::VectorSize::Bi,
scalar: Scalar {
kind: crate::ScalarKind::Float,
width: 4,
},
scalar: Scalar::F32,
},
"vec3" => {
let scalar = lexer.next_scalar_generic()?;
@ -1137,10 +1113,7 @@ impl Parser {
},
"vec3f" => ast::Type::Vector {
size: crate::VectorSize::Tri,
scalar: Scalar {
kind: crate::ScalarKind::Float,
width: 4,
},
scalar: Scalar::F32,
},
"vec4" => {
let scalar = lexer.next_scalar_generic()?;
@ -1165,10 +1138,7 @@ impl Parser {
},
"vec4f" => ast::Type::Vector {
size: crate::VectorSize::Quad,
scalar: Scalar {
kind: crate::ScalarKind::Float,
width: 4,
},
scalar: Scalar::F32,
},
"mat2x2" => {
self.matrix_scalar_type(lexer, crate::VectorSize::Bi, crate::VectorSize::Bi)?

View File

@ -472,6 +472,19 @@ pub enum ScalarKind {
Bool,
}
/// Characteristics of a scalar type.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub struct Scalar {
/// How the value's bits are to be interpreted.
pub kind: ScalarKind,
/// This size of the value in bytes.
pub width: Bytes,
}
/// Size of an array.
#[repr(u8)]
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
@ -677,13 +690,9 @@ pub struct Type {
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub enum TypeInner {
/// Number of integral or floating-point kind.
Scalar { kind: ScalarKind, width: Bytes },
Scalar(Scalar),
/// Vector of numbers.
Vector {
size: VectorSize,
kind: ScalarKind,
width: Bytes,
},
Vector { size: VectorSize, scalar: Scalar },
/// Matrix of floats.
Matrix {
columns: VectorSize,
@ -691,7 +700,7 @@ pub enum TypeInner {
width: Bytes,
},
/// Atomic scalar.
Atomic { kind: ScalarKind, width: Bytes },
Atomic(Scalar),
/// Pointer to another type.
///
/// Pointers to scalars and vectors should be treated as equivalent to
@ -737,8 +746,7 @@ pub enum TypeInner {
/// [`TypeResolution::Value`]: proc::TypeResolution::Value
ValuePointer {
size: Option<VectorSize>,
kind: ScalarKind,
width: Bytes,
scalar: Scalar,
space: AddressSpace,
},
@ -1966,10 +1974,7 @@ pub struct EntryPoint {
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub enum PredeclaredType {
AtomicCompareExchangeWeakResult {
kind: ScalarKind,
width: Bytes,
},
AtomicCompareExchangeWeakResult(Scalar),
ModfResult {
size: Option<VectorSize>,
width: Bytes,

View File

@ -404,7 +404,7 @@ impl<'a> ConstantEvaluator<'a> {
let expr = self.check_and_get(expr)?;
match convert {
Some(width) => self.cast(expr, kind, width, span),
Some(width) => self.cast(expr, crate::Scalar { kind, width }, span),
None => Err(ConstantEvaluatorError::NotImplemented(
"bitcast built-in function".into(),
)),
@ -462,12 +462,11 @@ impl<'a> ConstantEvaluator<'a> {
) -> Result<Handle<Expression>, ConstantEvaluatorError> {
match self.expressions[value] {
Expression::Literal(literal) => {
let kind = literal.scalar_kind();
let width = literal.width();
let scalar = literal.scalar();
let ty = self.types.insert(
Type {
name: None,
inner: TypeInner::Vector { size, kind, width },
inner: TypeInner::Vector { size, scalar },
},
span,
);
@ -479,7 +478,7 @@ impl<'a> ConstantEvaluator<'a> {
}
Expression::ZeroValue(ty) => {
let inner = match self.types[ty].inner {
TypeInner::Scalar { kind, width } => TypeInner::Vector { size, kind, width },
TypeInner::Scalar(scalar) => TypeInner::Vector { size, scalar },
_ => return Err(ConstantEvaluatorError::SplatScalarOnly),
};
let res_ty = self.types.insert(Type { name: None, inner }, span);
@ -498,14 +497,10 @@ impl<'a> ConstantEvaluator<'a> {
pattern: [crate::SwizzleComponent; 4],
) -> Result<Handle<Expression>, ConstantEvaluatorError> {
let mut get_dst_ty = |ty| match self.types[ty].inner {
crate::TypeInner::Vector {
size: _,
kind,
width,
} => Ok(self.types.insert(
crate::TypeInner::Vector { size: _, scalar } => Ok(self.types.insert(
Type {
name: None,
inner: crate::TypeInner::Vector { size, kind, width },
inner: crate::TypeInner::Vector { size, scalar },
},
span,
)),
@ -611,7 +606,10 @@ impl<'a> ConstantEvaluator<'a> {
&& matches!(
self.types[ty0].inner,
crate::TypeInner::Vector {
kind: crate::ScalarKind::Float,
scalar: crate::Scalar {
kind: crate::ScalarKind::Float,
..
},
..
}
) =>
@ -709,7 +707,10 @@ impl<'a> ConstantEvaluator<'a> {
&& matches!(
self.types[ty0].inner,
crate::TypeInner::Vector {
kind: crate::ScalarKind::Float,
scalar: crate::Scalar {
kind: crate::ScalarKind::Float,
..
},
..
}
) =>
@ -831,10 +832,10 @@ impl<'a> ConstantEvaluator<'a> {
Expression::ZeroValue(ty)
if matches!(
self.types[ty].inner,
crate::TypeInner::Scalar {
crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Uint,
..
}
})
) =>
{
Ok(0)
@ -873,18 +874,17 @@ impl<'a> ConstantEvaluator<'a> {
span: Span,
) -> Result<Handle<Expression>, ConstantEvaluatorError> {
match self.types[ty].inner {
TypeInner::Scalar { kind, width } => {
TypeInner::Scalar(scalar) => {
let expr = Expression::Literal(
Literal::zero(kind, width)
.ok_or(ConstantEvaluatorError::TypeNotConstructible)?,
Literal::zero(scalar).ok_or(ConstantEvaluatorError::TypeNotConstructible)?,
);
self.register_evaluated_expr(expr, span)
}
TypeInner::Vector { size, kind, width } => {
TypeInner::Vector { size, scalar } => {
let scalar_ty = self.types.insert(
Type {
name: None,
inner: TypeInner::Scalar { kind, width },
inner: TypeInner::Scalar(scalar),
},
span,
);
@ -905,8 +905,10 @@ impl<'a> ConstantEvaluator<'a> {
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
scalar: crate::Scalar {
kind: ScalarKind::Float,
width,
},
},
},
span,
@ -943,43 +945,57 @@ impl<'a> ConstantEvaluator<'a> {
}
}
/// Convert the scalar components of `expr` to `kind` and `target_width`.
/// Convert the scalar components of `expr` to `target`.
///
/// Treat `span` as the location of the resulting expression.
pub fn cast(
&mut self,
expr: Handle<Expression>,
kind: ScalarKind,
target_width: crate::Bytes,
target: crate::Scalar,
span: Span,
) -> Result<Handle<Expression>, ConstantEvaluatorError> {
use crate::Scalar as Sc;
use crate::ScalarKind as Sk;
let expr = self.eval_zero_value_and_splat(expr, span)?;
let expr = match self.expressions[expr] {
Expression::Literal(literal) => {
let literal = match (kind, target_width) {
(ScalarKind::Sint, 4) => Literal::I32(match literal {
let literal = match target {
Sc {
kind: Sk::Sint,
width: 4,
} => Literal::I32(match literal {
Literal::I32(v) => v,
Literal::U32(v) => v as i32,
Literal::F32(v) => v as i32,
Literal::Bool(v) => v as i32,
Literal::F64(_) => return Err(ConstantEvaluatorError::InvalidCastArg),
}),
(ScalarKind::Uint, 4) => Literal::U32(match literal {
Sc {
kind: Sk::Uint,
width: 4,
} => Literal::U32(match literal {
Literal::I32(v) => v as u32,
Literal::U32(v) => v,
Literal::F32(v) => v as u32,
Literal::Bool(v) => v as u32,
Literal::F64(_) => return Err(ConstantEvaluatorError::InvalidCastArg),
}),
(ScalarKind::Float, 4) => Literal::F32(match literal {
Sc {
kind: Sk::Float,
width: 4,
} => Literal::F32(match literal {
Literal::I32(v) => v as f32,
Literal::U32(v) => v as f32,
Literal::F32(v) => v,
Literal::Bool(v) => v as u32 as f32,
Literal::F64(_) => return Err(ConstantEvaluatorError::InvalidCastArg),
}),
(ScalarKind::Bool, crate::BOOL_WIDTH) => Literal::Bool(match literal {
Sc {
kind: Sk::Bool,
width: crate::BOOL_WIDTH,
} => Literal::Bool(match literal {
Literal::I32(v) => v != 0,
Literal::U32(v) => v != 0,
Literal::F32(v) => v != 0.0,
@ -997,20 +1013,19 @@ impl<'a> ConstantEvaluator<'a> {
let ty_inner = match self.types[ty].inner {
TypeInner::Vector { size, .. } => TypeInner::Vector {
size,
kind,
width: target_width,
scalar: target,
},
TypeInner::Matrix { columns, rows, .. } => TypeInner::Matrix {
columns,
rows,
width: target_width,
width: target.width,
},
_ => return Err(ConstantEvaluatorError::InvalidCastArg),
};
let mut components = src_components.clone();
for component in &mut components {
*component = self.cast(*component, kind, target_width, span)?;
*component = self.cast(*component, target, span)?;
}
let ty = self.types.insert(
@ -1305,10 +1320,7 @@ mod tests {
let scalar_ty = types.insert(
Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Sint,
width: 4,
},
inner: TypeInner::Scalar(crate::Scalar::I32),
},
Default::default(),
);
@ -1318,8 +1330,10 @@ mod tests {
name: None,
inner: TypeInner::Vector {
size: VectorSize::Bi,
kind: ScalarKind::Sint,
width: 4,
scalar: crate::Scalar {
kind: ScalarKind::Sint,
width: 4,
},
},
},
Default::default(),
@ -1441,10 +1455,7 @@ mod tests {
let scalar_ty = types.insert(
Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Sint,
width: 4,
},
inner: TypeInner::Scalar(crate::Scalar::I32),
},
Default::default(),
);
@ -1509,8 +1520,10 @@ mod tests {
name: None,
inner: TypeInner::Vector {
size: VectorSize::Tri,
kind: ScalarKind::Float,
width: 4,
scalar: crate::Scalar {
kind: ScalarKind::Float,
width: 4,
},
},
},
Default::default(),
@ -1649,10 +1662,7 @@ mod tests {
let i32_ty = types.insert(
Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Sint,
width: 4,
},
inner: TypeInner::Scalar(crate::Scalar::I32),
},
Default::default(),
);
@ -1662,8 +1672,10 @@ mod tests {
name: None,
inner: TypeInner::Vector {
size: VectorSize::Bi,
kind: ScalarKind::Sint,
width: 4,
scalar: crate::Scalar {
kind: ScalarKind::Sint,
width: 4,
},
},
},
Default::default(),
@ -1733,10 +1745,7 @@ mod tests {
let i32_ty = types.insert(
Type {
name: None,
inner: TypeInner::Scalar {
kind: ScalarKind::Sint,
width: 4,
},
inner: TypeInner::Scalar(crate::Scalar::I32),
},
Default::default(),
);
@ -1746,8 +1755,10 @@ mod tests {
name: None,
inner: TypeInner::Vector {
size: VectorSize::Bi,
kind: ScalarKind::Sint,
width: 4,
scalar: crate::Scalar {
kind: ScalarKind::Sint,
width: 4,
},
},
},
Default::default(),

View File

@ -171,17 +171,16 @@ impl Layouter {
for (ty_handle, ty) in gctx.types.iter().skip(self.layouts.len()) {
let size = ty.inner.size(gctx);
let layout = match ty.inner {
Ti::Scalar { width, .. } | Ti::Atomic { width, .. } => {
let alignment = Alignment::new(width as u32)
Ti::Scalar(scalar) | Ti::Atomic(scalar) => {
let alignment = Alignment::new(scalar.width as u32)
.ok_or(LayoutErrorInner::NonPowerOfTwoWidth.with(ty_handle))?;
TypeLayout { size, alignment }
}
Ti::Vector {
size: vec_size,
width,
..
scalar,
} => {
let alignment = Alignment::new(width as u32)
let alignment = Alignment::new(scalar.width as u32)
.ok_or(LayoutErrorInner::NonPowerOfTwoWidth.with(ty_handle))?;
TypeLayout {
size,

View File

@ -77,6 +77,52 @@ impl super::ScalarKind {
}
}
impl super::Scalar {
pub const I32: Self = Self {
kind: crate::ScalarKind::Sint,
width: 4,
};
pub const U32: Self = Self {
kind: crate::ScalarKind::Uint,
width: 4,
};
pub const F32: Self = Self {
kind: crate::ScalarKind::Float,
width: 4,
};
pub const F64: Self = Self {
kind: crate::ScalarKind::Float,
width: 8,
};
pub const BOOL: Self = Self {
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
};
/// Construct a float `Scalar` with the given width.
///
/// This is especially common when dealing with
/// `TypeInner::Matrix`, where the scalar kind is implicit.
pub const fn float(width: crate::Bytes) -> Self {
Self {
kind: crate::ScalarKind::Float,
width,
}
}
pub const fn to_inner_scalar(self) -> crate::TypeInner {
crate::TypeInner::Scalar(self)
}
pub const fn to_inner_vector(self, size: crate::VectorSize) -> crate::TypeInner {
crate::TypeInner::Vector { size, scalar: self }
}
pub const fn to_inner_atomic(self) -> crate::TypeInner {
crate::TypeInner::Atomic(self)
}
}
impl PartialEq for crate::Literal {
fn eq(&self, other: &Self) -> bool {
match (*self, *other) {
@ -118,8 +164,8 @@ impl std::hash::Hash for crate::Literal {
}
impl crate::Literal {
pub const fn new(value: u8, kind: crate::ScalarKind, width: crate::Bytes) -> Option<Self> {
match (value, kind, width) {
pub const fn new(value: u8, scalar: crate::Scalar) -> Option<Self> {
match (value, scalar.kind, scalar.width) {
(value, crate::ScalarKind::Float, 8) => Some(Self::F64(value as _)),
(value, crate::ScalarKind::Float, 4) => Some(Self::F32(value as _)),
(value, crate::ScalarKind::Uint, 4) => Some(Self::U32(value as _)),
@ -130,12 +176,12 @@ impl crate::Literal {
}
}
pub const fn zero(kind: crate::ScalarKind, width: crate::Bytes) -> Option<Self> {
Self::new(0, kind, width)
pub const fn zero(scalar: crate::Scalar) -> Option<Self> {
Self::new(0, scalar)
}
pub const fn one(kind: crate::ScalarKind, width: crate::Bytes) -> Option<Self> {
Self::new(1, kind, width)
pub const fn one(scalar: crate::Scalar) -> Option<Self> {
Self::new(1, scalar)
}
pub const fn width(&self) -> crate::Bytes {
@ -145,44 +191,41 @@ impl crate::Literal {
Self::Bool(_) => 1,
}
}
pub const fn scalar_kind(&self) -> crate::ScalarKind {
pub const fn scalar(&self) -> crate::Scalar {
match *self {
Self::F64(_) | Self::F32(_) => crate::ScalarKind::Float,
Self::U32(_) => crate::ScalarKind::Uint,
Self::I32(_) => crate::ScalarKind::Sint,
Self::Bool(_) => crate::ScalarKind::Bool,
crate::Literal::F64(_) => crate::Scalar::F64,
crate::Literal::F32(_) => crate::Scalar::F32,
crate::Literal::U32(_) => crate::Scalar::U32,
crate::Literal::I32(_) => crate::Scalar::I32,
crate::Literal::Bool(_) => crate::Scalar::BOOL,
}
}
pub const fn scalar_kind(&self) -> crate::ScalarKind {
self.scalar().kind
}
pub const fn ty_inner(&self) -> crate::TypeInner {
crate::TypeInner::Scalar {
kind: self.scalar_kind(),
width: self.width(),
}
crate::TypeInner::Scalar(self.scalar())
}
}
pub const POINTER_SPAN: u32 = 4;
impl super::TypeInner {
pub const fn scalar_kind(&self) -> Option<super::ScalarKind> {
pub const fn scalar(&self) -> Option<super::Scalar> {
use crate::TypeInner as Ti;
match *self {
super::TypeInner::Scalar { kind, .. } | super::TypeInner::Vector { kind, .. } => {
Some(kind)
}
super::TypeInner::Matrix { .. } => Some(super::ScalarKind::Float),
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => Some(scalar),
Ti::Matrix { width, .. } => Some(super::Scalar::float(width)),
_ => None,
}
}
pub const fn scalar_width(&self) -> Option<u8> {
// Multiply by 8 to get the bit width
match *self {
super::TypeInner::Scalar { width, .. } | super::TypeInner::Vector { width, .. } => {
Some(width * 8)
}
super::TypeInner::Matrix { width, .. } => Some(width * 8),
_ => None,
}
pub fn scalar_kind(&self) -> Option<super::ScalarKind> {
self.scalar().map(|scalar| scalar.kind)
}
pub fn scalar_width(&self) -> Option<u8> {
self.scalar().map(|scalar| scalar.width * 8)
}
pub const fn pointer_space(&self) -> Option<crate::AddressSpace> {
@ -206,12 +249,8 @@ impl super::TypeInner {
/// Get the size of this type.
pub fn size(&self, _gctx: GlobalCtx) -> u32 {
match *self {
Self::Scalar { kind: _, width } | Self::Atomic { kind: _, width } => width as u32,
Self::Vector {
size,
kind: _,
width,
} => size as u32 * width as u32,
Self::Scalar(scalar) | Self::Atomic(scalar) => scalar.width as u32,
Self::Vector { size, scalar } => size as u32 * scalar.width as u32,
// matrices are treated as arrays of aligned columns
Self::Matrix {
columns,
@ -255,16 +294,14 @@ impl super::TypeInner {
use crate::TypeInner as Ti;
match *self {
Ti::Pointer { base, space } => match types[base].inner {
Ti::Scalar { kind, width } => Some(Ti::ValuePointer {
Ti::Scalar(scalar) => Some(Ti::ValuePointer {
size: None,
kind,
width,
scalar,
space,
}),
Ti::Vector { size, kind, width } => Some(Ti::ValuePointer {
Ti::Vector { size, scalar } => Some(Ti::ValuePointer {
size: Some(size),
kind,
width,
scalar,
space,
}),
_ => None,
@ -318,13 +355,10 @@ impl super::TypeInner {
pub fn component_type(&self, index: usize) -> Option<TypeResolution> {
Some(match *self {
Self::Vector { kind, width, .. } => {
TypeResolution::Value(crate::TypeInner::Scalar { kind, width })
}
Self::Vector { scalar, .. } => TypeResolution::Value(crate::TypeInner::Scalar(scalar)),
Self::Matrix { rows, width, .. } => TypeResolution::Value(crate::TypeInner::Vector {
size: rows,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
}),
Self::Array {
base,
@ -628,7 +662,7 @@ impl GlobalCtx<'_> {
match arena[handle] {
crate::Expression::Literal(literal) => Some(literal),
crate::Expression::ZeroValue(ty) => match gctx.types[ty].inner {
crate::TypeInner::Scalar { kind, width } => crate::Literal::zero(kind, width),
crate::TypeInner::Scalar(scalar) => crate::Literal::zero(scalar),
_ => None,
},
_ => None,

View File

@ -119,8 +119,8 @@ impl Clone for TypeResolution {
match *self {
Self::Handle(handle) => Self::Handle(handle),
Self::Value(ref v) => Self::Value(match *v {
Ti::Scalar { kind, width } => Ti::Scalar { kind, width },
Ti::Vector { size, kind, width } => Ti::Vector { size, kind, width },
Ti::Scalar(scalar) => Ti::Scalar(scalar),
Ti::Vector { size, scalar } => Ti::Vector { size, scalar },
Ti::Matrix {
rows,
columns,
@ -133,13 +133,11 @@ impl Clone for TypeResolution {
Ti::Pointer { base, space } => Ti::Pointer { base, space },
Ti::ValuePointer {
size,
kind,
width,
scalar,
space,
} => Ti::ValuePointer {
size,
kind,
width,
scalar,
space,
},
_ => unreachable!("Unexpected clone type: {:?}", v),
@ -243,36 +241,24 @@ impl<'a> ResolveContext<'a> {
Ti::Array { base, .. } => TypeResolution::Handle(base),
Ti::Matrix { rows, width, .. } => TypeResolution::Value(Ti::Vector {
size: rows,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
}),
Ti::Vector {
size: _,
kind,
width,
} => TypeResolution::Value(Ti::Scalar { kind, width }),
Ti::Vector { size: _, scalar } => TypeResolution::Value(Ti::Scalar(scalar)),
Ti::ValuePointer {
size: Some(_),
kind,
width,
scalar,
space,
} => TypeResolution::Value(Ti::ValuePointer {
size: None,
kind,
width,
scalar,
space,
}),
Ti::Pointer { base, space } => {
TypeResolution::Value(match types[base].inner {
Ti::Array { base, .. } => Ti::Pointer { base, space },
Ti::Vector {
size: _,
kind,
width,
} => Ti::ValuePointer {
Ti::Vector { size: _, scalar } => Ti::ValuePointer {
size: None,
kind,
width,
scalar,
space,
},
// Matrices are only dynamically indexed behind a pointer
@ -281,9 +267,8 @@ impl<'a> ResolveContext<'a> {
rows,
width,
} => Ti::ValuePointer {
kind: crate::ScalarKind::Float,
size: Some(rows),
width,
scalar: crate::Scalar::float(width),
space,
},
Ti::BindingArray { base, .. } => Ti::Pointer { base, space },
@ -307,11 +292,11 @@ impl<'a> ResolveContext<'a> {
},
crate::Expression::AccessIndex { base, index } => {
match *past(base)?.inner_with(types) {
Ti::Vector { size, kind, width } => {
Ti::Vector { size, scalar } => {
if index >= size as u32 {
return Err(ResolveError::OutOfBoundsIndex { expr: base, index });
}
TypeResolution::Value(Ti::Scalar { kind, width })
TypeResolution::Value(Ti::Scalar(scalar))
}
Ti::Matrix {
columns,
@ -323,8 +308,7 @@ impl<'a> ResolveContext<'a> {
}
TypeResolution::Value(crate::TypeInner::Vector {
size: rows,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
})
}
Ti::Array { base, .. } => TypeResolution::Handle(base),
@ -336,8 +320,7 @@ impl<'a> ResolveContext<'a> {
}
Ti::ValuePointer {
size: Some(size),
kind,
width,
scalar,
space,
} => {
if index >= size as u32 {
@ -345,8 +328,7 @@ impl<'a> ResolveContext<'a> {
}
TypeResolution::Value(Ti::ValuePointer {
size: None,
kind,
width,
scalar,
space,
})
}
@ -355,14 +337,13 @@ impl<'a> ResolveContext<'a> {
space,
} => TypeResolution::Value(match types[ty_base].inner {
Ti::Array { base, .. } => Ti::Pointer { base, space },
Ti::Vector { size, kind, width } => {
Ti::Vector { size, scalar } => {
if index >= size as u32 {
return Err(ResolveError::OutOfBoundsIndex { expr: base, index });
}
Ti::ValuePointer {
size: None,
kind,
width,
scalar,
space,
}
}
@ -376,8 +357,7 @@ impl<'a> ResolveContext<'a> {
}
Ti::ValuePointer {
size: Some(rows),
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
space,
}
}
@ -410,9 +390,7 @@ impl<'a> ResolveContext<'a> {
}
}
crate::Expression::Splat { size, value } => match *past(value)?.inner_with(types) {
Ti::Scalar { kind, width } => {
TypeResolution::Value(Ti::Vector { size, kind, width })
}
Ti::Scalar(scalar) => TypeResolution::Value(Ti::Vector { size, scalar }),
ref other => {
log::error!("Scalar type {:?}", other);
return Err(ResolveError::InvalidScalar(value));
@ -423,11 +401,9 @@ impl<'a> ResolveContext<'a> {
vector,
pattern: _,
} => match *past(vector)?.inner_with(types) {
Ti::Vector {
size: _,
kind,
width,
} => TypeResolution::Value(Ti::Vector { size, kind, width }),
Ti::Vector { size: _, scalar } => {
TypeResolution::Value(Ti::Vector { size, scalar })
}
ref other => {
log::error!("Vector type {:?}", other);
return Err(ResolveError::InvalidVector(vector));
@ -464,20 +440,19 @@ impl<'a> ResolveContext<'a> {
}
crate::Expression::Load { pointer } => match *past(pointer)?.inner_with(types) {
Ti::Pointer { base, space: _ } => {
if let Ti::Atomic { kind, width } = types[base].inner {
TypeResolution::Value(Ti::Scalar { kind, width })
if let Ti::Atomic(scalar) = types[base].inner {
TypeResolution::Value(Ti::Scalar(scalar))
} else {
TypeResolution::Handle(base)
}
}
Ti::ValuePointer {
size,
kind,
width,
scalar,
space: _,
} => TypeResolution::Value(match size {
Some(size) => Ti::Vector { size, kind, width },
None => Ti::Scalar { kind, width },
Some(size) => Ti::Vector { size, scalar },
None => Ti::Scalar(scalar),
}),
ref other => {
log::error!("Pointer type {:?}", other);
@ -490,11 +465,13 @@ impl<'a> ResolveContext<'a> {
..
} => match *past(image)?.inner_with(types) {
Ti::Image { class, .. } => TypeResolution::Value(Ti::Vector {
kind: match class {
crate::ImageClass::Sampled { kind, multi: _ } => kind,
_ => crate::ScalarKind::Float,
scalar: crate::Scalar {
kind: match class {
crate::ImageClass::Sampled { kind, multi: _ } => kind,
_ => crate::ScalarKind::Float,
},
width: 4,
},
width: 4,
size: crate::VectorSize::Quad,
}),
ref other => {
@ -505,18 +482,16 @@ impl<'a> ResolveContext<'a> {
crate::Expression::ImageSample { image, .. }
| crate::Expression::ImageLoad { image, .. } => match *past(image)?.inner_with(types) {
Ti::Image { class, .. } => TypeResolution::Value(match class {
crate::ImageClass::Depth { multi: _ } => Ti::Scalar {
kind: crate::ScalarKind::Float,
width: 4,
},
crate::ImageClass::Depth { multi: _ } => Ti::Scalar(crate::Scalar::F32),
crate::ImageClass::Sampled { kind, multi: _ } => Ti::Vector {
kind,
width: 4,
scalar: crate::Scalar { kind, width: 4 },
size: crate::VectorSize::Quad,
},
crate::ImageClass::Storage { format, .. } => Ti::Vector {
kind: format.into(),
width: 4,
scalar: crate::Scalar {
kind: format.into(),
width: 4,
},
size: crate::VectorSize::Quad,
},
}),
@ -528,19 +503,14 @@ impl<'a> ResolveContext<'a> {
crate::Expression::ImageQuery { image, query } => TypeResolution::Value(match query {
crate::ImageQuery::Size { level: _ } => match *past(image)?.inner_with(types) {
Ti::Image { dim, .. } => match dim {
crate::ImageDimension::D1 => Ti::Scalar {
kind: crate::ScalarKind::Uint,
width: 4,
},
crate::ImageDimension::D1 => Ti::Scalar(crate::Scalar::U32),
crate::ImageDimension::D2 | crate::ImageDimension::Cube => Ti::Vector {
size: crate::VectorSize::Bi,
kind: crate::ScalarKind::Uint,
width: 4,
scalar: crate::Scalar::U32,
},
crate::ImageDimension::D3 => Ti::Vector {
size: crate::VectorSize::Tri,
kind: crate::ScalarKind::Uint,
width: 4,
scalar: crate::Scalar::U32,
},
},
ref other => {
@ -550,10 +520,7 @@ impl<'a> ResolveContext<'a> {
},
crate::ImageQuery::NumLevels
| crate::ImageQuery::NumLayers
| crate::ImageQuery::NumSamples => Ti::Scalar {
kind: crate::ScalarKind::Uint,
width: 4,
},
| crate::ImageQuery::NumSamples => Ti::Scalar(crate::Scalar::U32),
}),
crate::Expression::Unary { expr, .. } => past(expr)?.clone(),
crate::Expression::Binary { op, left, right } => match op {
@ -585,8 +552,7 @@ impl<'a> ResolveContext<'a> {
&Ti::Vector { .. },
) => TypeResolution::Value(Ti::Vector {
size: rows,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
}),
(
&Ti::Vector { .. },
@ -597,8 +563,7 @@ impl<'a> ResolveContext<'a> {
},
) => TypeResolution::Value(Ti::Vector {
size: columns,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
}),
(&Ti::Scalar { .. }, _) => res_right.clone(),
(_, &Ti::Scalar { .. }) => res_left.clone(),
@ -618,11 +583,10 @@ impl<'a> ResolveContext<'a> {
| crate::BinaryOperator::GreaterEqual
| crate::BinaryOperator::LogicalAnd
| crate::BinaryOperator::LogicalOr => {
let kind = crate::ScalarKind::Bool;
let width = crate::BOOL_WIDTH;
let scalar = crate::Scalar::BOOL;
let inner = match *past(left)?.inner_with(types) {
Ti::Scalar { .. } => Ti::Scalar { kind, width },
Ti::Vector { size, .. } => Ti::Vector { size, kind, width },
Ti::Scalar { .. } => Ti::Scalar(scalar),
Ti::Vector { size, .. } => Ti::Vector { size, scalar },
ref other => {
return Err(ResolveError::IncompatibleOperands(format!(
"{op:?}({other:?}, _)"
@ -643,20 +607,13 @@ impl<'a> ResolveContext<'a> {
crate::Expression::Derivative { expr, .. } => past(expr)?.clone(),
crate::Expression::Relational { fun, argument } => match fun {
crate::RelationalFunction::All | crate::RelationalFunction::Any => {
TypeResolution::Value(Ti::Scalar {
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
})
TypeResolution::Value(Ti::Scalar(crate::Scalar::BOOL))
}
crate::RelationalFunction::IsNan | crate::RelationalFunction::IsInf => {
match *past(argument)?.inner_with(types) {
Ti::Scalar { .. } => TypeResolution::Value(Ti::Scalar {
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
}),
Ti::Scalar { .. } => TypeResolution::Value(Ti::Scalar(crate::Scalar::BOOL)),
Ti::Vector { size, .. } => TypeResolution::Value(Ti::Vector {
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
scalar: crate::Scalar::BOOL,
size,
}),
ref other => {
@ -714,14 +671,16 @@ impl<'a> ResolveContext<'a> {
Mf::Pow => res_arg.clone(),
Mf::Modf | Mf::Frexp => {
let (size, width) = match res_arg.inner_with(types) {
&Ti::Scalar {
&Ti::Scalar(crate::Scalar {
kind: crate::ScalarKind::Float,
width,
} => (None, width),
&Ti::Vector {
kind: crate::ScalarKind::Float,
size,
width,
}) => (None, width),
&Ti::Vector {
scalar: crate::Scalar {
kind: crate::ScalarKind::Float,
width,
},
size,
} => (Some(size), width),
ref other =>
return Err(ResolveError::IncompatibleOperands(format!("{fun:?}({other:?}, _)")))
@ -740,10 +699,9 @@ impl<'a> ResolveContext<'a> {
// geometry
Mf::Dot => match *res_arg.inner_with(types) {
Ti::Vector {
kind,
size: _,
width,
} => TypeResolution::Value(Ti::Scalar { kind, width }),
scalar,
} => TypeResolution::Value(Ti::Scalar(scalar)),
ref other =>
return Err(ResolveError::IncompatibleOperands(
format!("{fun:?}({other:?}, _)")
@ -754,7 +712,14 @@ impl<'a> ResolveContext<'a> {
format!("{fun:?}(_, None)")
))?;
match (res_arg.inner_with(types), past(arg1)?.inner_with(types)) {
(&Ti::Vector {kind: _, size: columns,width}, &Ti::Vector{ size: rows, .. }) => TypeResolution::Value(Ti::Matrix { columns, rows, width }),
(
&Ti::Vector { size: columns, scalar },
&Ti::Vector{ size: rows, .. }
) => TypeResolution::Value(Ti::Matrix {
columns,
rows,
width: scalar.width
}),
(left, right) =>
return Err(ResolveError::IncompatibleOperands(
format!("{fun:?}({left:?}, {right:?})")
@ -764,8 +729,8 @@ impl<'a> ResolveContext<'a> {
Mf::Cross => res_arg.clone(),
Mf::Distance |
Mf::Length => match *res_arg.inner_with(types) {
Ti::Scalar {width,kind} |
Ti::Vector {width,kind,size:_} => TypeResolution::Value(Ti::Scalar { kind, width }),
Ti::Scalar(scalar) |
Ti::Vector {scalar,size:_} => TypeResolution::Value(Ti::Scalar(scalar)),
ref other => return Err(ResolveError::IncompatibleOperands(
format!("{fun:?}({other:?})")
)),
@ -814,7 +779,7 @@ impl<'a> ResolveContext<'a> {
Ti::Matrix {
width,
..
} => TypeResolution::Value(Ti::Scalar { kind: crate::ScalarKind::Float, width }),
} => TypeResolution::Value(Ti::Scalar(crate::Scalar::float(width))),
ref other => return Err(ResolveError::IncompatibleOperands(
format!("{fun:?}({other:?})")
)),
@ -828,10 +793,17 @@ impl<'a> ResolveContext<'a> {
Mf::InsertBits |
Mf::FindLsb |
Mf::FindMsb => match *res_arg.inner_with(types) {
Ti::Scalar { kind: kind @ (crate::ScalarKind::Sint | crate::ScalarKind::Uint), width } =>
TypeResolution::Value(Ti::Scalar { kind, width }),
Ti::Vector { size, kind: kind @ (crate::ScalarKind::Sint | crate::ScalarKind::Uint), width } =>
TypeResolution::Value(Ti::Vector { size, kind, width }),
Ti::Scalar(scalar @ crate::Scalar {
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
..
}) => TypeResolution::Value(Ti::Scalar(scalar)),
Ti::Vector {
size,
scalar: scalar @ crate::Scalar {
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
..
}
} => TypeResolution::Value(Ti::Vector { size, scalar }),
ref other => return Err(ResolveError::IncompatibleOperands(
format!("{fun:?}({other:?})")
)),
@ -841,13 +813,19 @@ impl<'a> ResolveContext<'a> {
Mf::Pack4x8unorm |
Mf::Pack2x16snorm |
Mf::Pack2x16unorm |
Mf::Pack2x16float => TypeResolution::Value(Ti::Scalar { kind: crate::ScalarKind::Uint, width: 4 }),
Mf::Pack2x16float => TypeResolution::Value(Ti::Scalar(crate::Scalar::U32)),
// data unpacking
Mf::Unpack4x8snorm |
Mf::Unpack4x8unorm => TypeResolution::Value(Ti::Vector { size: crate::VectorSize::Quad, kind: crate::ScalarKind::Float, width: 4 }),
Mf::Unpack4x8unorm => TypeResolution::Value(Ti::Vector {
size: crate::VectorSize::Quad,
scalar: crate::Scalar::F32
}),
Mf::Unpack2x16snorm |
Mf::Unpack2x16unorm |
Mf::Unpack2x16float => TypeResolution::Value(Ti::Vector { size: crate::VectorSize::Bi, kind: crate::ScalarKind::Float, width: 4 }),
Mf::Unpack2x16float => TypeResolution::Value(Ti::Vector {
size: crate::VectorSize::Bi,
scalar: crate::Scalar::F32
}),
}
}
crate::Expression::As {
@ -855,18 +833,21 @@ impl<'a> ResolveContext<'a> {
kind,
convert,
} => match *past(expr)?.inner_with(types) {
Ti::Scalar { kind: _, width } => TypeResolution::Value(Ti::Scalar {
kind,
width: convert.unwrap_or(width),
}),
Ti::Scalar(crate::Scalar { width, .. }) => {
TypeResolution::Value(Ti::Scalar(crate::Scalar {
kind,
width: convert.unwrap_or(width),
}))
}
Ti::Vector {
kind: _,
size,
width,
scalar: crate::Scalar { kind: _, width },
} => TypeResolution::Value(Ti::Vector {
kind,
size,
width: convert.unwrap_or(width),
scalar: crate::Scalar {
kind,
width: convert.unwrap_or(width),
},
}),
Ti::Matrix {
columns,
@ -890,14 +871,12 @@ impl<'a> ResolveContext<'a> {
.ok_or(ResolveError::FunctionReturnsVoid)?;
TypeResolution::Handle(result.ty)
}
crate::Expression::ArrayLength(_) => TypeResolution::Value(Ti::Scalar {
kind: crate::ScalarKind::Uint,
width: 4,
}),
crate::Expression::RayQueryProceedResult => TypeResolution::Value(Ti::Scalar {
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
}),
crate::Expression::ArrayLength(_) => {
TypeResolution::Value(Ti::Scalar(crate::Scalar::U32))
}
crate::Expression::RayQueryProceedResult => {
TypeResolution::Value(Ti::Scalar(crate::Scalar::BOOL))
}
crate::Expression::RayQueryGetIntersection { .. } => {
let result = self
.special_types

View File

@ -159,10 +159,10 @@ impl ExpressionInfo {
ref_count: 0,
assignable_global: None,
// this doesn't matter at this point, will be overwritten
ty: TypeResolution::Value(crate::TypeInner::Scalar {
ty: TypeResolution::Value(crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Bool,
width: 0,
}),
})),
}
}
}
@ -1070,8 +1070,7 @@ fn uniform_control_flow() {
name: None,
inner: crate::TypeInner::Vector {
size: crate::VectorSize::Bi,
kind: crate::ScalarKind::Float,
width: 4,
scalar: crate::Scalar::F32,
},
},
Default::default(),

View File

@ -24,19 +24,15 @@ pub fn validate_compose(
match gctx.types[self_ty_handle].inner {
// vectors are composed from scalars or other vectors
Ti::Vector { size, kind, width } => {
Ti::Vector { size, scalar } => {
let mut total = 0;
for (index, comp_res) in component_resolutions.enumerate() {
total += match *comp_res.inner_with(gctx.types) {
Ti::Scalar {
kind: comp_kind,
width: comp_width,
} if comp_kind == kind && comp_width == width => 1,
Ti::Scalar(comp_scalar) if comp_scalar == scalar => 1,
Ti::Vector {
size: comp_size,
kind: comp_kind,
width: comp_width,
} if comp_kind == kind && comp_width == width => comp_size as u32,
scalar: comp_scalar,
} if comp_scalar == scalar => comp_size as u32,
ref other => {
log::error!("Vector component[{}] type {:?}", index, other);
return Err(ComposeError::ComponentType {
@ -60,8 +56,7 @@ pub fn validate_compose(
} => {
let inner = Ti::Vector {
size: rows,
kind: crate::ScalarKind::Float,
width,
scalar: crate::Scalar::float(width),
};
if columns as usize != component_resolutions.len() {
return Err(ComposeError::ComponentCount {

View File

@ -221,7 +221,7 @@ impl super::Validator {
info: &FunctionInfo,
mod_info: &ModuleInfo,
) -> Result<ShaderStages, ExpressionError> {
use crate::{Expression as E, ScalarKind as Sk, TypeInner as Ti};
use crate::{Expression as E, Scalar as Sc, ScalarKind as Sk, TypeInner as Ti};
let resolver = ExpressionTypeResolver {
root,
@ -246,10 +246,10 @@ impl super::Validator {
};
match resolver[index] {
//TODO: only allow one of these
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Sint | Sk::Uint,
width: _,
} => {}
..
}) => {}
ref other => {
log::error!("Indexing by {:?}", other);
return Err(ExpressionError::InvalidIndexType(index));
@ -412,10 +412,10 @@ impl super::Validator {
}
if let Some(expr) = array_index {
match resolver[expr] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Sint | Sk::Uint,
width: _,
} => {}
..
}) => {}
_ => return Err(ExpressionError::InvalidImageArrayIndexType(expr)),
}
}
@ -452,13 +452,15 @@ impl super::Validator {
crate::ImageDimension::D3 | crate::ImageDimension::Cube => 3,
};
match resolver[coordinate] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float, ..
} if num_components == 1 => {}
}) if num_components == 1 => {}
Ti::Vector {
size,
kind: Sk::Float,
..
scalar:
Sc {
kind: Sk::Float, ..
},
} if size as u32 == num_components => {}
_ => return Err(ExpressionError::InvalidImageCoordinateType(dim, coordinate)),
}
@ -466,11 +468,10 @@ impl super::Validator {
// check constant offset
if let Some(const_expr) = offset {
match *mod_info[const_expr].inner_with(&module.types) {
Ti::Scalar { kind: Sk::Sint, .. } if num_components == 1 => {}
Ti::Scalar(Sc { kind: Sk::Sint, .. }) if num_components == 1 => {}
Ti::Vector {
size,
kind: Sk::Sint,
..
scalar: Sc { kind: Sk::Sint, .. },
} if size as u32 == num_components => {}
_ => {
return Err(ExpressionError::InvalidSampleOffset(dim, const_expr));
@ -481,9 +482,9 @@ impl super::Validator {
// check depth reference type
if let Some(expr) = depth_ref {
match resolver[expr] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float, ..
} => {}
}) => {}
_ => return Err(ExpressionError::InvalidDepthReference(expr)),
}
match level {
@ -518,44 +519,48 @@ impl super::Validator {
crate::SampleLevel::Zero => ShaderStages::all(),
crate::SampleLevel::Exact(expr) => {
match resolver[expr] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float, ..
} => {}
}) => {}
_ => return Err(ExpressionError::InvalidSampleLevelExactType(expr)),
}
ShaderStages::all()
}
crate::SampleLevel::Bias(expr) => {
match resolver[expr] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float, ..
} => {}
}) => {}
_ => return Err(ExpressionError::InvalidSampleLevelBiasType(expr)),
}
ShaderStages::FRAGMENT
}
crate::SampleLevel::Gradient { x, y } => {
match resolver[x] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float, ..
} if num_components == 1 => {}
}) if num_components == 1 => {}
Ti::Vector {
size,
kind: Sk::Float,
..
scalar:
Sc {
kind: Sk::Float, ..
},
} if size as u32 == num_components => {}
_ => {
return Err(ExpressionError::InvalidSampleLevelGradientType(dim, x))
}
}
match resolver[y] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float, ..
} if num_components == 1 => {}
}) if num_components == 1 => {}
Ti::Vector {
size,
kind: Sk::Float,
..
scalar:
Sc {
kind: Sk::Float, ..
},
} if size as u32 == num_components => {}
_ => {
return Err(ExpressionError::InvalidSampleLevelGradientType(dim, y))
@ -592,10 +597,10 @@ impl super::Validator {
}
if let Some(expr) = array_index {
match resolver[expr] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Sint | Sk::Uint,
width: _,
} => {}
}) => {}
_ => return Err(ExpressionError::InvalidImageArrayIndexType(expr)),
}
}
@ -669,7 +674,7 @@ impl super::Validator {
let right_inner = &resolver[right];
let good = match op {
Bo::Add | Bo::Subtract => match *left_inner {
Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner,
Sk::Bool => false,
},
@ -677,7 +682,7 @@ impl super::Validator {
_ => false,
},
Bo::Divide | Bo::Modulo => match *left_inner {
Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner,
Sk::Bool => false,
},
@ -690,52 +695,62 @@ impl super::Validator {
};
let types_match = match (left_inner, right_inner) {
// Straight scalar and mixed scalar/vector.
(&Ti::Scalar { kind: kind1, .. }, &Ti::Scalar { kind: kind2, .. })
| (&Ti::Vector { kind: kind1, .. }, &Ti::Scalar { kind: kind2, .. })
| (&Ti::Scalar { kind: kind1, .. }, &Ti::Vector { kind: kind2, .. }) => {
kind1 == kind2
}
(&Ti::Scalar(scalar1), &Ti::Scalar(scalar2))
| (
&Ti::Vector {
scalar: scalar1, ..
},
&Ti::Scalar(scalar2),
)
| (
&Ti::Scalar(scalar1),
&Ti::Vector {
scalar: scalar2, ..
},
) => scalar1 == scalar2,
// Scalar/matrix.
(
&Ti::Scalar {
&Ti::Scalar(Sc {
kind: Sk::Float, ..
},
}),
&Ti::Matrix { .. },
)
| (
&Ti::Matrix { .. },
&Ti::Scalar {
&Ti::Scalar(Sc {
kind: Sk::Float, ..
},
}),
) => true,
// Vector/vector.
(
&Ti::Vector {
kind: kind1,
size: size1,
..
scalar: scalar1,
},
&Ti::Vector {
kind: kind2,
size: size2,
..
scalar: scalar2,
},
) => kind1 == kind2 && size1 == size2,
) => scalar1 == scalar2 && size1 == size2,
// Matrix * vector.
(
&Ti::Matrix { columns, .. },
&Ti::Vector {
kind: Sk::Float,
size,
..
scalar:
Sc {
kind: Sk::Float, ..
},
},
) => columns == size,
// Vector * matrix.
(
&Ti::Vector {
kind: Sk::Float,
size,
..
scalar:
Sc {
kind: Sk::Float, ..
},
},
&Ti::Matrix { rows, .. },
) => size == rows,
@ -744,24 +759,14 @@ impl super::Validator {
}
_ => false,
};
let left_width = match *left_inner {
Ti::Scalar { width, .. }
| Ti::Vector { width, .. }
| Ti::Matrix { width, .. } => width,
_ => 0,
};
let right_width = match *right_inner {
Ti::Scalar { width, .. }
| Ti::Vector { width, .. }
| Ti::Matrix { width, .. } => width,
_ => 0,
};
let left_width = left_inner.scalar_width().unwrap_or(0);
let right_width = right_inner.scalar_width().unwrap_or(0);
kind_allowed && types_match && left_width == right_width
}
Bo::Equal | Bo::NotEqual => left_inner.is_sized() && left_inner == right_inner,
Bo::Less | Bo::LessEqual | Bo::Greater | Bo::GreaterEqual => {
match *left_inner {
Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner,
Sk::Bool => false,
},
@ -772,16 +777,18 @@ impl super::Validator {
}
}
Bo::LogicalAnd | Bo::LogicalOr => match *left_inner {
Ti::Scalar { kind: Sk::Bool, .. } | Ti::Vector { kind: Sk::Bool, .. } => {
left_inner == right_inner
}
Ti::Scalar(Sc { kind: Sk::Bool, .. })
| Ti::Vector {
scalar: Sc { kind: Sk::Bool, .. },
..
} => left_inner == right_inner,
ref other => {
log::error!("Op {:?} left type {:?}", op, other);
false
}
},
Bo::And | Bo::InclusiveOr => match *left_inner {
Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Bool | Sk::Sint | Sk::Uint => left_inner == right_inner,
Sk::Float => false,
},
@ -791,7 +798,7 @@ impl super::Validator {
}
},
Bo::ExclusiveOr => match *left_inner {
Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind {
Sk::Sint | Sk::Uint => left_inner == right_inner,
Sk::Bool | Sk::Float => false,
},
@ -801,27 +808,26 @@ impl super::Validator {
}
},
Bo::ShiftLeft | Bo::ShiftRight => {
let (base_size, base_kind) = match *left_inner {
Ti::Scalar { kind, .. } => (Ok(None), kind),
Ti::Vector { size, kind, .. } => (Ok(Some(size)), kind),
let (base_size, base_scalar) = match *left_inner {
Ti::Scalar(scalar) => (Ok(None), scalar),
Ti::Vector { size, scalar } => (Ok(Some(size)), scalar),
ref other => {
log::error!("Op {:?} base type {:?}", op, other);
(Err(()), Sk::Bool)
(Err(()), Sc::BOOL)
}
};
let shift_size = match *right_inner {
Ti::Scalar { kind: Sk::Uint, .. } => Ok(None),
Ti::Scalar(Sc { kind: Sk::Uint, .. }) => Ok(None),
Ti::Vector {
size,
kind: Sk::Uint,
..
scalar: Sc { kind: Sk::Uint, .. },
} => Ok(Some(size)),
ref other => {
log::error!("Op {:?} shift type {:?}", op, other);
Err(())
}
};
match base_kind {
match base_scalar.kind {
Sk::Sint | Sk::Uint => base_size.is_ok() && base_size == shift_size,
Sk::Float | Sk::Bool => false,
}
@ -850,10 +856,10 @@ impl super::Validator {
let accept_inner = &resolver[accept];
let reject_inner = &resolver[reject];
let condition_good = match resolver[condition] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Bool,
width: _,
} => {
}) => {
// When `condition` is a single boolean, `accept` and
// `reject` can be vectors or scalars.
match *accept_inner {
@ -863,8 +869,11 @@ impl super::Validator {
}
Ti::Vector {
size,
kind: Sk::Bool,
width: _,
scalar:
Sc {
kind: Sk::Bool,
width: _,
},
} => match *accept_inner {
Ti::Vector {
size: other_size, ..
@ -880,11 +889,15 @@ impl super::Validator {
}
E::Derivative { expr, .. } => {
match resolver[expr] {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float, ..
}
})
| Ti::Vector {
kind: Sk::Float, ..
scalar:
Sc {
kind: Sk::Float, ..
},
..
} => {}
_ => return Err(ExpressionError::InvalidDerivative),
}
@ -895,19 +908,18 @@ impl super::Validator {
let argument_inner = &resolver[argument];
match fun {
Rf::All | Rf::Any => match *argument_inner {
Ti::Vector { kind: Sk::Bool, .. } => {}
Ti::Vector {
scalar: Sc { kind: Sk::Bool, .. },
..
} => {}
ref other => {
log::error!("All/Any of type {:?}", other);
return Err(ExpressionError::InvalidBooleanVector(argument));
}
},
Rf::IsNan | Rf::IsInf => match *argument_inner {
Ti::Scalar {
kind: Sk::Float, ..
}
| Ti::Vector {
kind: Sk::Float, ..
} => {}
Ti::Scalar(scalar) | Ti::Vector { scalar, .. }
if scalar.kind == Sk::Float => {}
ref other => {
log::error!("Float test of type {:?}", other);
return Err(ExpressionError::InvalidFloatArgument(argument));
@ -936,7 +948,9 @@ impl super::Validator {
return Err(ExpressionError::WrongArgumentCount(fun));
}
let good = match *arg_ty {
Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => kind != Sk::Bool,
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => {
scalar.kind != Sk::Bool
}
_ => false,
};
if !good {
@ -949,7 +963,9 @@ impl super::Validator {
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
};
let good = match *arg_ty {
Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => kind != Sk::Bool,
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => {
scalar.kind != Sk::Bool
}
_ => false,
};
if !good {
@ -969,7 +985,9 @@ impl super::Validator {
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
};
let good = match *arg_ty {
Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => kind != Sk::Bool,
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => {
scalar.kind != Sk::Bool
}
_ => false,
};
if !good {
@ -1021,12 +1039,8 @@ impl super::Validator {
return Err(ExpressionError::WrongArgumentCount(fun));
}
match *arg_ty {
Ti::Scalar {
kind: Sk::Float, ..
}
| Ti::Vector {
kind: Sk::Float, ..
} => {}
Ti::Scalar(scalar) | Ti::Vector { scalar, .. }
if scalar.kind == Sk::Float => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
}
@ -1035,12 +1049,16 @@ impl super::Validator {
return Err(ExpressionError::WrongArgumentCount(fun));
}
match *arg_ty {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float | Sk::Sint,
..
}
})
| Ti::Vector {
kind: Sk::Float | Sk::Sint,
scalar:
Sc {
kind: Sk::Float | Sk::Sint,
..
},
..
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
@ -1052,12 +1070,8 @@ impl super::Validator {
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
};
match *arg_ty {
Ti::Scalar {
kind: Sk::Float, ..
}
| Ti::Vector {
kind: Sk::Float, ..
} => {}
Ti::Scalar(scalar) | Ti::Vector { scalar, .. }
if scalar.kind == Sk::Float => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
if arg1_ty != arg_ty {
@ -1072,16 +1086,10 @@ impl super::Validator {
if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() {
return Err(ExpressionError::WrongArgumentCount(fun));
}
if !matches!(
*arg_ty,
Ti::Scalar {
kind: Sk::Float,
..
} | Ti::Vector {
kind: Sk::Float,
..
},
) {
if !matches!(*arg_ty,
Ti::Scalar(scalar) | Ti::Vector { scalar, .. }
if scalar.kind == Sk::Float)
{
return Err(ExpressionError::InvalidArgumentType(fun, 1, arg));
}
}
@ -1091,24 +1099,25 @@ impl super::Validator {
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
};
let size0 = match *arg_ty {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float, ..
} => None,
}) => None,
Ti::Vector {
kind: Sk::Float,
scalar:
Sc {
kind: Sk::Float, ..
},
size,
..
} => Some(size),
_ => {
return Err(ExpressionError::InvalidArgumentType(fun, 0, arg));
}
};
let good = match *arg1_ty {
Ti::Scalar { kind: Sk::Sint, .. } if size0.is_none() => true,
Ti::Scalar(Sc { kind: Sk::Sint, .. }) if size0.is_none() => true,
Ti::Vector {
size,
kind: Sk::Sint,
..
scalar: Sc { kind: Sk::Sint, .. },
} if Some(size) == size0 => true,
_ => false,
};
@ -1127,7 +1136,11 @@ impl super::Validator {
};
match *arg_ty {
Ti::Vector {
kind: Sk::Float | Sk::Sint | Sk::Uint,
scalar:
Sc {
kind: Sk::Float | Sk::Sint | Sk::Uint,
..
},
..
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
@ -1147,7 +1160,11 @@ impl super::Validator {
};
match *arg_ty {
Ti::Vector {
kind: Sk::Float, ..
scalar:
Sc {
kind: Sk::Float, ..
},
..
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
@ -1167,7 +1184,11 @@ impl super::Validator {
match *arg_ty {
Ti::Vector {
kind: Sk::Float, ..
scalar:
Sc {
kind: Sk::Float, ..
},
..
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
@ -1183,13 +1204,17 @@ impl super::Validator {
match (arg_ty, arg2_ty) {
(
&Ti::Vector {
width: vector_width,
scalar:
Sc {
width: vector_width,
..
},
..
},
&Ti::Scalar {
&Ti::Scalar(Sc {
width: scalar_width,
kind: Sk::Float,
},
}),
) if vector_width == scalar_width => {}
_ => {
return Err(ExpressionError::InvalidArgumentType(
@ -1206,7 +1231,11 @@ impl super::Validator {
}
match *arg_ty {
Ti::Vector {
kind: Sk::Float, ..
scalar:
Sc {
kind: Sk::Float, ..
},
..
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
@ -1217,11 +1246,15 @@ impl super::Validator {
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
};
match *arg_ty {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float, ..
}
})
| Ti::Vector {
kind: Sk::Float, ..
scalar:
Sc {
kind: Sk::Float, ..
},
..
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
@ -1246,13 +1279,16 @@ impl super::Validator {
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
};
let arg_width = match *arg_ty {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float,
width,
}
})
| Ti::Vector {
kind: Sk::Float,
width,
scalar:
Sc {
kind: Sk::Float,
width,
},
..
} => width,
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
@ -1266,10 +1302,10 @@ impl super::Validator {
}
// the last argument can always be a scalar
match *arg2_ty {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Float,
width,
} if width == arg_width => {}
}) if width == arg_width => {}
_ if arg2_ty == arg_ty => {}
_ => {
return Err(ExpressionError::InvalidArgumentType(
@ -1311,12 +1347,16 @@ impl super::Validator {
return Err(ExpressionError::WrongArgumentCount(fun));
}
match *arg_ty {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Sint | Sk::Uint,
..
}
})
| Ti::Vector {
kind: Sk::Sint | Sk::Uint,
scalar:
Sc {
kind: Sk::Sint | Sk::Uint,
..
},
..
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
@ -1328,12 +1368,16 @@ impl super::Validator {
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
};
match *arg_ty {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Sint | Sk::Uint,
..
}
})
| Ti::Vector {
kind: Sk::Sint | Sk::Uint,
scalar:
Sc {
kind: Sk::Sint | Sk::Uint,
..
},
..
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
@ -1346,7 +1390,7 @@ impl super::Validator {
));
}
match *arg2_ty {
Ti::Scalar { kind: Sk::Uint, .. } => {}
Ti::Scalar(Sc { kind: Sk::Uint, .. }) => {}
_ => {
return Err(ExpressionError::InvalidArgumentType(
fun,
@ -1356,7 +1400,7 @@ impl super::Validator {
}
}
match *arg3_ty {
Ti::Scalar { kind: Sk::Uint, .. } => {}
Ti::Scalar(Sc { kind: Sk::Uint, .. }) => {}
_ => {
return Err(ExpressionError::InvalidArgumentType(
fun,
@ -1372,18 +1416,22 @@ impl super::Validator {
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
};
match *arg_ty {
Ti::Scalar {
Ti::Scalar(Sc {
kind: Sk::Sint | Sk::Uint,
..
}
})
| Ti::Vector {
kind: Sk::Sint | Sk::Uint,
scalar:
Sc {
kind: Sk::Sint | Sk::Uint,
..
},
..
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
match *arg1_ty {
Ti::Scalar { kind: Sk::Uint, .. } => {}
Ti::Scalar(Sc { kind: Sk::Uint, .. }) => {}
_ => {
return Err(ExpressionError::InvalidArgumentType(
fun,
@ -1393,7 +1441,7 @@ impl super::Validator {
}
}
match *arg2_ty {
Ti::Scalar { kind: Sk::Uint, .. } => {}
Ti::Scalar(Sc { kind: Sk::Uint, .. }) => {}
_ => {
return Err(ExpressionError::InvalidArgumentType(
fun,
@ -1410,8 +1458,10 @@ impl super::Validator {
match *arg_ty {
Ti::Vector {
size: crate::VectorSize::Bi,
kind: Sk::Float,
..
scalar:
Sc {
kind: Sk::Float, ..
},
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
@ -1423,8 +1473,10 @@ impl super::Validator {
match *arg_ty {
Ti::Vector {
size: crate::VectorSize::Quad,
kind: Sk::Float,
..
scalar:
Sc {
kind: Sk::Float, ..
},
} => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
@ -1438,7 +1490,7 @@ impl super::Validator {
return Err(ExpressionError::WrongArgumentCount(fun));
}
match *arg_ty {
Ti::Scalar { kind: Sk::Uint, .. } => {}
Ti::Scalar(Sc { kind: Sk::Uint, .. }) => {}
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
}
}
@ -1450,14 +1502,18 @@ impl super::Validator {
kind,
convert,
} => {
let base_width = match resolver[expr] {
crate::TypeInner::Scalar { width, .. }
| crate::TypeInner::Vector { width, .. }
| crate::TypeInner::Matrix { width, .. } => width,
let mut base_scalar = match resolver[expr] {
crate::TypeInner::Scalar(scalar) | crate::TypeInner::Vector { scalar, .. } => {
scalar
}
crate::TypeInner::Matrix { width, .. } => crate::Scalar::float(width),
_ => return Err(ExpressionError::InvalidCastArgument),
};
let width = convert.unwrap_or(base_width);
if self.check_width(kind, width).is_err() {
base_scalar.kind = kind;
if let Some(width) = convert {
base_scalar.width = width;
}
if self.check_width(base_scalar).is_err() {
return Err(ExpressionError::InvalidCastArgument);
}
ShaderStages::all()
@ -1465,10 +1521,12 @@ impl super::Validator {
E::CallResult(function) => mod_info.functions[function.index()].available_stages,
E::AtomicResult { ty, comparison } => {
let scalar_predicate = |ty: &crate::TypeInner| match ty {
&crate::TypeInner::Scalar {
kind: kind @ (crate::ScalarKind::Uint | crate::ScalarKind::Sint),
width,
} => self.check_width(kind, width).is_ok(),
&crate::TypeInner::Scalar(
scalar @ Sc {
kind: crate::ScalarKind::Uint | crate::ScalarKind::Sint,
..
},
) => self.check_width(scalar).is_ok(),
_ => false,
};
let good = match &module.types[ty].inner {
@ -1569,9 +1627,7 @@ impl super::Validator {
}
pub fn validate_literal(&self, literal: crate::Literal) -> Result<(), LiteralError> {
let kind = literal.scalar_kind();
let width = literal.width();
self.check_width(kind, width)?;
self.check_width(literal.scalar())?;
check_literal_value(literal)?;
Ok(())

View File

@ -345,9 +345,9 @@ impl super::Validator {
context: &BlockContext,
) -> Result<(), WithSpan<FunctionError>> {
let pointer_inner = context.resolve_type(pointer, &self.valid_expression_set)?;
let (ptr_kind, ptr_width) = match *pointer_inner {
let ptr_scalar = match *pointer_inner {
crate::TypeInner::Pointer { base, .. } => match context.types[base].inner {
crate::TypeInner::Atomic { kind, width } => (kind, width),
crate::TypeInner::Atomic(scalar) => scalar,
ref other => {
log::error!("Atomic pointer to type {:?}", other);
return Err(AtomicError::InvalidPointer(pointer)
@ -365,7 +365,7 @@ impl super::Validator {
let value_inner = context.resolve_type(value, &self.valid_expression_set)?;
match *value_inner {
crate::TypeInner::Scalar { width, kind } if kind == ptr_kind && width == ptr_width => {}
crate::TypeInner::Scalar(scalar) if scalar == ptr_scalar => {}
ref other => {
log::error!("Atomic operand type {:?}", other);
return Err(AtomicError::InvalidOperand(value)
@ -387,12 +387,8 @@ impl super::Validator {
match context.expressions[result] {
crate::Expression::AtomicResult { ty, comparison }
if {
let scalar_predicate = |ty: &crate::TypeInner| {
*ty == crate::TypeInner::Scalar {
kind: ptr_kind,
width: ptr_width,
}
};
let scalar_predicate =
|ty: &crate::TypeInner| *ty == crate::TypeInner::Scalar(ptr_scalar);
match &context.types[ty].inner {
ty if !comparison => scalar_predicate(ty),
&crate::TypeInner::Struct { ref members, .. } if comparison => {
@ -445,10 +441,10 @@ impl super::Validator {
ref reject,
} => {
match *context.resolve_type(condition, &self.valid_expression_set)? {
Ti::Scalar {
Ti::Scalar(crate::Scalar {
kind: crate::ScalarKind::Bool,
width: _,
} => {}
}) => {}
_ => {
return Err(FunctionError::InvalidIfType(condition)
.with_span_handle(condition, context.expressions))
@ -560,10 +556,10 @@ impl super::Validator {
if let Some(condition) = break_if {
match *context.resolve_type(condition, &self.valid_expression_set)? {
Ti::Scalar {
Ti::Scalar(crate::Scalar {
kind: crate::ScalarKind::Bool,
width: _,
} => {}
}) => {}
_ => {
return Err(FunctionError::InvalidIfType(condition)
.with_span_handle(condition, context.expressions))
@ -665,21 +661,19 @@ impl super::Validator {
let good = match *pointer_ty {
Ti::Pointer { base, space: _ } => match context.types[base].inner {
Ti::Atomic { kind, width } => *value_ty == Ti::Scalar { kind, width },
Ti::Atomic(scalar) => *value_ty == Ti::Scalar(scalar),
ref other => value_ty == other,
},
Ti::ValuePointer {
size: Some(size),
kind,
width,
scalar,
space: _,
} => *value_ty == Ti::Vector { size, kind, width },
} => *value_ty == Ti::Vector { size, scalar },
Ti::ValuePointer {
size: None,
kind,
width,
scalar,
space: _,
} => *value_ty == Ti::Scalar { kind, width },
} => *value_ty == Ti::Scalar(scalar),
_ => false,
};
if !good {
@ -768,10 +762,10 @@ impl super::Validator {
}
if let Some(expr) = array_index {
match *context.resolve_type(expr, &self.valid_expression_set)? {
Ti::Scalar {
Ti::Scalar(crate::Scalar {
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
width: _,
} => {}
}) => {}
_ => {
return Err(FunctionError::InvalidImageStore(
ExpressionError::InvalidImageArrayIndexType(expr),
@ -783,9 +777,11 @@ impl super::Validator {
match class {
crate::ImageClass::Storage { format, .. } => {
crate::TypeInner::Vector {
kind: format.into(),
size: crate::VectorSize::Quad,
width: 4,
scalar: crate::Scalar {
kind: format.into(),
width: 4,
},
}
}
_ => {

View File

@ -678,10 +678,7 @@ fn constant_deps() {
let i32_handle = types.insert(
Type {
name: None,
inner: TypeInner::Scalar {
kind: crate::ScalarKind::Sint,
width: 4,
},
inner: TypeInner::Scalar(crate::Scalar::I32),
},
nowhere,
);

View File

@ -142,9 +142,7 @@ impl VaryingContext<'_> {
ty: Handle<crate::Type>,
binding: &crate::Binding,
) -> Result<(), VaryingError> {
use crate::{
BuiltIn as Bi, ScalarKind as Sk, ShaderStage as St, TypeInner as Ti, VectorSize as Vs,
};
use crate::{BuiltIn as Bi, ShaderStage as St, TypeInner as Ti, VectorSize as Vs};
let ty_inner = &self.types[ty].inner;
match *binding {
@ -174,44 +172,30 @@ impl VaryingContext<'_> {
return Err(VaryingError::UnsupportedCapability(required));
}
let width = 4;
let (visible, type_good) = match built_in {
Bi::BaseInstance | Bi::BaseVertex | Bi::InstanceIndex | Bi::VertexIndex => (
self.stage == St::Vertex && !self.output,
*ty_inner
== Ti::Scalar {
kind: Sk::Uint,
width,
},
*ty_inner == Ti::Scalar(crate::Scalar::U32),
),
Bi::ClipDistance | Bi::CullDistance => (
self.stage == St::Vertex && self.output,
match *ty_inner {
Ti::Array { base, .. } => {
self.types[base].inner
== Ti::Scalar {
kind: Sk::Float,
width,
}
self.types[base].inner == Ti::Scalar(crate::Scalar::F32)
}
_ => false,
},
),
Bi::PointSize => (
self.stage == St::Vertex && self.output,
*ty_inner
== Ti::Scalar {
kind: Sk::Float,
width,
},
*ty_inner == Ti::Scalar(crate::Scalar::F32),
),
Bi::PointCoord => (
self.stage == St::Fragment && !self.output,
*ty_inner
== Ti::Vector {
size: Vs::Bi,
kind: Sk::Float,
width,
scalar: crate::Scalar::F32,
},
),
Bi::Position { .. } => (
@ -223,8 +207,7 @@ impl VaryingContext<'_> {
*ty_inner
== Ti::Vector {
size: Vs::Quad,
kind: Sk::Float,
width,
scalar: crate::Scalar::F32,
},
),
Bi::ViewIndex => (
@ -232,59 +215,31 @@ impl VaryingContext<'_> {
St::Vertex | St::Fragment => !self.output,
St::Compute => false,
},
*ty_inner
== Ti::Scalar {
kind: Sk::Sint,
width,
},
*ty_inner == Ti::Scalar(crate::Scalar::I32),
),
Bi::FragDepth => (
self.stage == St::Fragment && self.output,
*ty_inner
== Ti::Scalar {
kind: Sk::Float,
width,
},
*ty_inner == Ti::Scalar(crate::Scalar::F32),
),
Bi::FrontFacing => (
self.stage == St::Fragment && !self.output,
*ty_inner
== Ti::Scalar {
kind: Sk::Bool,
width: crate::BOOL_WIDTH,
},
*ty_inner == Ti::Scalar(crate::Scalar::BOOL),
),
Bi::PrimitiveIndex => (
self.stage == St::Fragment && !self.output,
*ty_inner
== Ti::Scalar {
kind: Sk::Uint,
width,
},
*ty_inner == Ti::Scalar(crate::Scalar::U32),
),
Bi::SampleIndex => (
self.stage == St::Fragment && !self.output,
*ty_inner
== Ti::Scalar {
kind: Sk::Uint,
width,
},
*ty_inner == Ti::Scalar(crate::Scalar::U32),
),
Bi::SampleMask => (
self.stage == St::Fragment,
*ty_inner
== Ti::Scalar {
kind: Sk::Uint,
width,
},
*ty_inner == Ti::Scalar(crate::Scalar::U32),
),
Bi::LocalInvocationIndex => (
self.stage == St::Compute && !self.output,
*ty_inner
== Ti::Scalar {
kind: Sk::Uint,
width,
},
*ty_inner == Ti::Scalar(crate::Scalar::U32),
),
Bi::GlobalInvocationId
| Bi::LocalInvocationId
@ -295,8 +250,7 @@ impl VaryingContext<'_> {
*ty_inner
== Ti::Vector {
size: Vs::Tri,
kind: Sk::Uint,
width,
scalar: crate::Scalar::U32,
},
),
};

View File

@ -264,19 +264,25 @@ impl crate::TypeInner {
#[cfg(feature = "validate")]
const fn image_storage_coordinates(&self) -> Option<crate::ImageDimension> {
match *self {
Self::Scalar {
Self::Scalar(crate::Scalar {
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
..
} => Some(crate::ImageDimension::D1),
}) => Some(crate::ImageDimension::D1),
Self::Vector {
size: crate::VectorSize::Bi,
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
..
scalar:
crate::Scalar {
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
..
},
} => Some(crate::ImageDimension::D2),
Self::Vector {
size: crate::VectorSize::Tri,
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
..
scalar:
crate::Scalar {
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
..
},
} => Some(crate::ImageDimension::D3),
_ => None,
}
@ -349,10 +355,11 @@ impl Validator {
ValidationError::from(e).with_span_handle(handle, &module.types)
})?;
let placeholder = TypeResolution::Value(crate::TypeInner::Scalar {
// These should all get overwritten.
let placeholder = TypeResolution::Value(crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Bool,
width: 0,
});
}));
let mut mod_info = ModuleInfo {
type_flags: Vec::with_capacity(module.types.len()),
@ -482,9 +489,5 @@ fn validate_atomic_compare_exchange_struct(
&& members[0].name.as_deref() == Some("old_value")
&& scalar_predicate(&types[members[0].ty].inner)
&& members[1].name.as_deref() == Some("exchanged")
&& types[members[1].ty].inner
== crate::TypeInner::Scalar {
kind: crate::ScalarKind::Bool,
width: crate::BOOL_WIDTH,
}
&& types[members[1].ty].inner == crate::TypeInner::Scalar(crate::Scalar::BOOL)
}

View File

@ -224,15 +224,11 @@ impl super::Validator {
}
}
pub(super) const fn check_width(
&self,
kind: crate::ScalarKind,
width: crate::Bytes,
) -> Result<(), WidthError> {
let good = match kind {
crate::ScalarKind::Bool => width == crate::BOOL_WIDTH,
pub(super) const fn check_width(&self, scalar: crate::Scalar) -> Result<(), WidthError> {
let good = match scalar.kind {
crate::ScalarKind::Bool => scalar.width == crate::BOOL_WIDTH,
crate::ScalarKind::Float => {
if width == 8 {
if scalar.width == 8 {
if !self.capabilities.contains(Capabilities::FLOAT64) {
return Err(WidthError::MissingCapability {
name: "f64",
@ -241,15 +237,15 @@ impl super::Validator {
}
true
} else {
width == 4
scalar.width == 4
}
}
crate::ScalarKind::Sint | crate::ScalarKind::Uint => width == 4,
crate::ScalarKind::Sint | crate::ScalarKind::Uint => scalar.width == 4,
};
if good {
Ok(())
} else {
Err(WidthError::Invalid(kind, width))
Err(WidthError::Invalid(scalar.kind, scalar.width))
}
}
@ -266,9 +262,9 @@ impl super::Validator {
) -> Result<TypeInfo, TypeError> {
use crate::TypeInner as Ti;
Ok(match gctx.types[handle].inner {
Ti::Scalar { kind, width } => {
self.check_width(kind, width)?;
let shareable = if kind.is_numeric() {
Ti::Scalar(scalar) => {
self.check_width(scalar)?;
let shareable = if scalar.kind.is_numeric() {
TypeFlags::IO_SHAREABLE | TypeFlags::HOST_SHAREABLE
} else {
TypeFlags::empty()
@ -280,12 +276,12 @@ impl super::Validator {
| TypeFlags::ARGUMENT
| TypeFlags::CONSTRUCTIBLE
| shareable,
Alignment::from_width(width),
Alignment::from_width(scalar.width),
)
}
Ti::Vector { size, kind, width } => {
self.check_width(kind, width)?;
let shareable = if kind.is_numeric() {
Ti::Vector { size, scalar } => {
self.check_width(scalar)?;
let shareable = if scalar.kind.is_numeric() {
TypeFlags::IO_SHAREABLE | TypeFlags::HOST_SHAREABLE
} else {
TypeFlags::empty()
@ -298,7 +294,7 @@ impl super::Validator {
| TypeFlags::ARGUMENT
| TypeFlags::CONSTRUCTIBLE
| shareable,
Alignment::from(size) * Alignment::from_width(width),
Alignment::from(size) * Alignment::from_width(scalar.width),
)
}
Ti::Matrix {
@ -306,7 +302,7 @@ impl super::Validator {
rows,
width,
} => {
self.check_width(crate::ScalarKind::Float, width)?;
self.check_width(crate::Scalar::float(width))?;
TypeInfo::new(
TypeFlags::DATA
| TypeFlags::SIZED
@ -317,7 +313,7 @@ impl super::Validator {
Alignment::from(rows) * Alignment::from_width(width),
)
}
Ti::Atomic { kind, width } => {
Ti::Atomic(crate::Scalar { kind, width }) => {
let good = match kind {
crate::ScalarKind::Bool | crate::ScalarKind::Float => false,
crate::ScalarKind::Sint | crate::ScalarKind::Uint => width == 4,
@ -373,8 +369,7 @@ impl super::Validator {
}
Ti::ValuePointer {
size: _,
kind,
width,
scalar,
space,
} => {
// ValuePointer should be treated the same way as the equivalent
@ -384,7 +379,7 @@ impl super::Validator {
// However, some cases are trivial: All our implicit base types
// are DATA and SIZED, so we can never return
// `InvalidPointerBase` or `InvalidPointerToUnsized`.
self.check_width(kind, width)?;
self.check_width(scalar)?;
// `Validator::validate_function` actually checks the address
// space of pointer arguments explicitly before checking the

File diff suppressed because it is too large Load Diff

View File

@ -47,10 +47,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -80,10 +80,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -92,10 +92,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Bool,
width: 1,
)),
))),
),
(
uniformity: (
@ -113,10 +113,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -134,10 +134,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -146,10 +146,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Bool,
width: 1,
)),
))),
),
(
uniformity: (
@ -167,10 +167,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -188,10 +188,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -218,10 +218,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -248,10 +248,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -334,10 +334,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -388,10 +388,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (

View File

@ -119,10 +119,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -131,10 +131,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Bool,
width: 1,
)),
))),
),
(
uniformity: (
@ -143,10 +143,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -155,10 +155,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -194,10 +194,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -226,8 +226,10 @@
assignable_global: None,
ty: Value(Vector(
size: Bi,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
)),
),
(
@ -246,10 +248,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -258,10 +260,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -270,10 +272,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Sint,
width: 4,
)),
))),
),
(
uniformity: (
@ -282,10 +284,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -303,10 +305,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -315,10 +317,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -345,10 +347,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -357,10 +359,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -378,10 +380,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -390,10 +392,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Sint,
width: 4,
)),
))),
),
(
uniformity: (
@ -402,10 +404,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
],
sampling: [],
@ -695,8 +697,10 @@
assignable_global: Some(3),
ty: Value(ValuePointer(
size: None,
kind: Uint,
width: 4,
scalar: (
kind: Uint,
width: 4,
),
space: Uniform,
)),
),
@ -707,10 +711,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -719,10 +723,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Uint,
width: 4,
)),
))),
),
(
uniformity: (
@ -731,10 +735,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Bool,
width: 1,
)),
))),
),
(
uniformity: (
@ -832,8 +836,10 @@
assignable_global: None,
ty: Value(Vector(
size: Quad,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
)),
),
(
@ -923,8 +929,10 @@
assignable_global: Some(4),
ty: Value(ValuePointer(
size: None,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
space: Storage(
access: ("LOAD"),
),
@ -937,10 +945,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1002,8 +1010,10 @@
assignable_global: Some(4),
ty: Value(ValuePointer(
size: None,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
space: Storage(
access: ("LOAD"),
),
@ -1016,10 +1026,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1081,8 +1091,10 @@
assignable_global: Some(4),
ty: Value(ValuePointer(
size: None,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
space: Storage(
access: ("LOAD"),
),
@ -1095,10 +1107,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1118,8 +1130,10 @@
assignable_global: Some(5),
ty: Value(ValuePointer(
size: None,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
space: Private,
)),
),
@ -1130,10 +1144,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1144,8 +1158,10 @@
assignable_global: Some(5),
ty: Value(ValuePointer(
size: None,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
space: Private,
)),
),
@ -1156,10 +1172,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1170,8 +1186,10 @@
assignable_global: Some(5),
ty: Value(ValuePointer(
size: None,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
space: Private,
)),
),
@ -1182,10 +1200,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1221,10 +1239,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1304,8 +1322,10 @@
assignable_global: Some(4),
ty: Value(ValuePointer(
size: None,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
space: Storage(
access: ("LOAD"),
),
@ -1318,10 +1338,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1383,8 +1403,10 @@
assignable_global: Some(4),
ty: Value(ValuePointer(
size: None,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
space: Storage(
access: ("LOAD"),
),
@ -1397,10 +1419,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1462,8 +1484,10 @@
assignable_global: Some(4),
ty: Value(ValuePointer(
size: None,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
space: Storage(
access: ("LOAD"),
),
@ -1476,10 +1500,10 @@
),
ref_count: 1,
assignable_global: None,
ty: Value(Scalar(
ty: Value(Scalar((
kind: Float,
width: 4,
)),
))),
),
(
uniformity: (
@ -1643,81 +1667,81 @@
),
],
const_expression_types: [
Value(Scalar(
Value(Scalar((
kind: Float,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Float,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Float,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Float,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Float,
width: 4,
)),
))),
Handle(1),
Handle(1),
Handle(1),
Handle(2),
Value(Scalar(
Value(Scalar((
kind: Uint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Uint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Uint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
Value(Scalar(
))),
Value(Scalar((
kind: Sint,
width: 4,
)),
))),
],
)

View File

@ -2,25 +2,27 @@
types: [
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Uint,
width: 4,
),
)),
),
(
name: None,
inner: Vector(
size: Tri,
kind: Uint,
width: 4,
scalar: (
kind: Uint,
width: 4,
),
),
),
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Sint,
width: 4,
),
)),
),
(
name: Some("GlobalConst"),
@ -88,10 +90,10 @@
),
(
name: None,
inner: Atomic(
inner: Atomic((
kind: Sint,
width: 4,
),
)),
),
(
name: None,
@ -105,8 +107,10 @@
name: None,
inner: Vector(
size: Bi,
kind: Uint,
width: 4,
scalar: (
kind: Uint,
width: 4,
),
),
),
(
@ -195,8 +199,10 @@
name: None,
inner: Vector(
size: Bi,
kind: Sint,
width: 4,
scalar: (
kind: Sint,
width: 4,
),
),
),
(
@ -231,10 +237,10 @@
),
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Float,
width: 4,
),
)),
),
(
name: None,
@ -263,8 +269,10 @@
name: None,
inner: Vector(
size: Quad,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(

View File

@ -2,25 +2,27 @@
types: [
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Uint,
width: 4,
),
)),
),
(
name: None,
inner: Vector(
size: Tri,
kind: Uint,
width: 4,
scalar: (
kind: Uint,
width: 4,
),
),
),
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Sint,
width: 4,
),
)),
),
(
name: Some("GlobalConst"),
@ -88,10 +90,10 @@
),
(
name: None,
inner: Atomic(
inner: Atomic((
kind: Sint,
width: 4,
),
)),
),
(
name: None,
@ -105,8 +107,10 @@
name: None,
inner: Vector(
size: Bi,
kind: Uint,
width: 4,
scalar: (
kind: Uint,
width: 4,
),
),
),
(
@ -195,16 +199,20 @@
name: None,
inner: Vector(
size: Bi,
kind: Sint,
width: 4,
scalar: (
kind: Sint,
width: 4,
),
),
),
(
name: None,
inner: Vector(
size: Bi,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(
@ -239,10 +247,10 @@
),
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Float,
width: 4,
),
)),
),
(
name: None,
@ -271,8 +279,10 @@
name: None,
inner: Vector(
size: Quad,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(
@ -296,16 +306,20 @@
name: None,
inner: Vector(
size: Quad,
kind: Sint,
width: 4,
scalar: (
kind: Sint,
width: 4,
),
),
),
(
name: None,
inner: Vector(
size: Tri,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(

View File

@ -2,10 +2,10 @@
types: [
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Uint,
width: 4,
),
)),
),
(
name: None,
@ -33,8 +33,10 @@
name: None,
inner: Vector(
size: Tri,
kind: Uint,
width: 4,
scalar: (
kind: Uint,
width: 4,
),
),
),
],

View File

@ -2,10 +2,10 @@
types: [
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Uint,
width: 4,
),
)),
),
(
name: None,
@ -33,8 +33,10 @@
name: None,
inner: Vector(
size: Tri,
kind: Uint,
width: 4,
scalar: (
kind: Uint,
width: 4,
),
),
),
],

View File

@ -2,40 +2,46 @@
types: [
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Float,
width: 4,
),
)),
),
(
name: None,
inner: Vector(
size: Tri,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Uint,
width: 4,
),
)),
),
(
name: None,
inner: Vector(
size: Quad,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(
name: None,
inner: Vector(
size: Bi,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(
@ -50,17 +56,19 @@
),
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Sint,
width: 4,
),
)),
),
(
name: None,
inner: Vector(
size: Quad,
kind: Uint,
width: 4,
scalar: (
kind: Uint,
width: 4,
),
),
),
(

View File

@ -2,47 +2,53 @@
types: [
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Float,
width: 4,
),
)),
),
(
name: None,
inner: Vector(
size: Tri,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Uint,
width: 4,
),
)),
),
(
name: None,
inner: Vector(
size: Quad,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Bool,
width: 1,
),
)),
),
(
name: None,
inner: Vector(
size: Bi,
kind: Float,
width: 4,
scalar: (
kind: Float,
width: 4,
),
),
),
(
@ -63,10 +69,10 @@
),
(
name: None,
inner: Scalar(
inner: Scalar((
kind: Sint,
width: 4,
),
)),
),
(
name: None,
@ -86,8 +92,10 @@
name: None,
inner: Vector(
size: Quad,
kind: Uint,
width: 4,
scalar: (
kind: Uint,
width: 4,
),
),
),
(

View File

@ -57,13 +57,18 @@ impl NumericDimension {
#[derive(Clone, Copy, Debug)]
pub struct NumericType {
dim: NumericDimension,
kind: naga::ScalarKind,
width: naga::Bytes,
scalar: naga::Scalar,
}
impl fmt::Display for NumericType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}{}{}", self.kind, self.width * 8, self.dim)
write!(
f,
"{:?}{}{}",
self.scalar.kind,
self.scalar.width * 8,
self.dim
)
}
}
@ -592,77 +597,76 @@ impl Resource {
impl NumericType {
fn from_vertex_format(format: wgt::VertexFormat) -> Self {
use naga::{ScalarKind as Sk, VectorSize as Vs};
use naga::{Scalar, VectorSize as Vs};
use wgt::VertexFormat as Vf;
let (dim, kind, width) = match format {
Vf::Uint32 => (NumericDimension::Scalar, Sk::Uint, 4),
let (dim, scalar) = match format {
Vf::Uint32 => (NumericDimension::Scalar, Scalar::U32),
Vf::Uint8x2 | Vf::Uint16x2 | Vf::Uint32x2 => {
(NumericDimension::Vector(Vs::Bi), Sk::Uint, 4)
(NumericDimension::Vector(Vs::Bi), Scalar::U32)
}
Vf::Uint32x3 => (NumericDimension::Vector(Vs::Tri), Sk::Uint, 4),
Vf::Uint32x3 => (NumericDimension::Vector(Vs::Tri), Scalar::U32),
Vf::Uint8x4 | Vf::Uint16x4 | Vf::Uint32x4 => {
(NumericDimension::Vector(Vs::Quad), Sk::Uint, 4)
(NumericDimension::Vector(Vs::Quad), Scalar::U32)
}
Vf::Sint32 => (NumericDimension::Scalar, Sk::Sint, 4),
Vf::Sint32 => (NumericDimension::Scalar, Scalar::I32),
Vf::Sint8x2 | Vf::Sint16x2 | Vf::Sint32x2 => {
(NumericDimension::Vector(Vs::Bi), Sk::Sint, 4)
(NumericDimension::Vector(Vs::Bi), Scalar::I32)
}
Vf::Sint32x3 => (NumericDimension::Vector(Vs::Tri), Sk::Sint, 4),
Vf::Sint32x3 => (NumericDimension::Vector(Vs::Tri), Scalar::I32),
Vf::Sint8x4 | Vf::Sint16x4 | Vf::Sint32x4 => {
(NumericDimension::Vector(Vs::Quad), Sk::Sint, 4)
(NumericDimension::Vector(Vs::Quad), Scalar::I32)
}
Vf::Float32 => (NumericDimension::Scalar, Sk::Float, 4),
Vf::Float32 => (NumericDimension::Scalar, Scalar::F32),
Vf::Unorm8x2
| Vf::Snorm8x2
| Vf::Unorm16x2
| Vf::Snorm16x2
| Vf::Float16x2
| Vf::Float32x2 => (NumericDimension::Vector(Vs::Bi), Sk::Float, 4),
Vf::Float32x3 => (NumericDimension::Vector(Vs::Tri), Sk::Float, 4),
| Vf::Float32x2 => (NumericDimension::Vector(Vs::Bi), Scalar::F32),
Vf::Float32x3 => (NumericDimension::Vector(Vs::Tri), Scalar::F32),
Vf::Unorm8x4
| Vf::Snorm8x4
| Vf::Unorm16x4
| Vf::Snorm16x4
| Vf::Float16x4
| Vf::Float32x4 => (NumericDimension::Vector(Vs::Quad), Sk::Float, 4),
Vf::Float64 => (NumericDimension::Scalar, Sk::Float, 8),
Vf::Float64x2 => (NumericDimension::Vector(Vs::Bi), Sk::Float, 8),
Vf::Float64x3 => (NumericDimension::Vector(Vs::Tri), Sk::Float, 8),
Vf::Float64x4 => (NumericDimension::Vector(Vs::Quad), Sk::Float, 8),
| Vf::Float32x4 => (NumericDimension::Vector(Vs::Quad), Scalar::F32),
Vf::Float64 => (NumericDimension::Scalar, Scalar::F64),
Vf::Float64x2 => (NumericDimension::Vector(Vs::Bi), Scalar::F64),
Vf::Float64x3 => (NumericDimension::Vector(Vs::Tri), Scalar::F64),
Vf::Float64x4 => (NumericDimension::Vector(Vs::Quad), Scalar::F64),
};
NumericType {
dim,
kind,
//Note: Shader always sees data as int, uint, or float.
// It doesn't know if the original is normalized in a tighter form.
width,
scalar,
}
}
fn from_texture_format(format: wgt::TextureFormat) -> Self {
use naga::{ScalarKind as Sk, VectorSize as Vs};
use naga::{Scalar, VectorSize as Vs};
use wgt::TextureFormat as Tf;
let (dim, kind) = match format {
let (dim, scalar) = match format {
Tf::R8Unorm | Tf::R8Snorm | Tf::R16Float | Tf::R32Float => {
(NumericDimension::Scalar, Sk::Float)
(NumericDimension::Scalar, Scalar::F32)
}
Tf::R8Uint | Tf::R16Uint | Tf::R32Uint => (NumericDimension::Scalar, Sk::Uint),
Tf::R8Sint | Tf::R16Sint | Tf::R32Sint => (NumericDimension::Scalar, Sk::Sint),
Tf::R8Uint | Tf::R16Uint | Tf::R32Uint => (NumericDimension::Scalar, Scalar::U32),
Tf::R8Sint | Tf::R16Sint | Tf::R32Sint => (NumericDimension::Scalar, Scalar::I32),
Tf::Rg8Unorm | Tf::Rg8Snorm | Tf::Rg16Float | Tf::Rg32Float => {
(NumericDimension::Vector(Vs::Bi), Sk::Float)
(NumericDimension::Vector(Vs::Bi), Scalar::F32)
}
Tf::Rg8Uint | Tf::Rg16Uint | Tf::Rg32Uint => {
(NumericDimension::Vector(Vs::Bi), Sk::Uint)
(NumericDimension::Vector(Vs::Bi), Scalar::U32)
}
Tf::Rg8Sint | Tf::Rg16Sint | Tf::Rg32Sint => {
(NumericDimension::Vector(Vs::Bi), Sk::Sint)
(NumericDimension::Vector(Vs::Bi), Scalar::I32)
}
Tf::R16Snorm | Tf::R16Unorm => (NumericDimension::Scalar, Sk::Float),
Tf::Rg16Snorm | Tf::Rg16Unorm => (NumericDimension::Vector(Vs::Bi), Sk::Float),
Tf::Rgba16Snorm | Tf::Rgba16Unorm => (NumericDimension::Vector(Vs::Quad), Sk::Float),
Tf::R16Snorm | Tf::R16Unorm => (NumericDimension::Scalar, Scalar::F32),
Tf::Rg16Snorm | Tf::Rg16Unorm => (NumericDimension::Vector(Vs::Bi), Scalar::F32),
Tf::Rgba16Snorm | Tf::Rgba16Unorm => (NumericDimension::Vector(Vs::Quad), Scalar::F32),
Tf::Rgba8Unorm
| Tf::Rgba8UnormSrgb
| Tf::Rgba8Snorm
@ -670,14 +674,14 @@ impl NumericType {
| Tf::Bgra8UnormSrgb
| Tf::Rgb10a2Unorm
| Tf::Rgba16Float
| Tf::Rgba32Float => (NumericDimension::Vector(Vs::Quad), Sk::Float),
| Tf::Rgba32Float => (NumericDimension::Vector(Vs::Quad), Scalar::F32),
Tf::Rgba8Uint | Tf::Rgba16Uint | Tf::Rgba32Uint | Tf::Rgb10a2Uint => {
(NumericDimension::Vector(Vs::Quad), Sk::Uint)
(NumericDimension::Vector(Vs::Quad), Scalar::U32)
}
Tf::Rgba8Sint | Tf::Rgba16Sint | Tf::Rgba32Sint => {
(NumericDimension::Vector(Vs::Quad), Sk::Sint)
(NumericDimension::Vector(Vs::Quad), Scalar::I32)
}
Tf::Rg11b10Float => (NumericDimension::Vector(Vs::Tri), Sk::Float),
Tf::Rg11b10Float => (NumericDimension::Vector(Vs::Tri), Scalar::F32),
Tf::Stencil8
| Tf::Depth16Unorm
| Tf::Depth32Float
@ -686,7 +690,7 @@ impl NumericType {
| Tf::Depth24PlusStencil8 => {
panic!("Unexpected depth format")
}
Tf::Rgb9e5Ufloat => (NumericDimension::Vector(Vs::Tri), Sk::Float),
Tf::Rgb9e5Ufloat => (NumericDimension::Vector(Vs::Tri), Scalar::F32),
Tf::Bc1RgbaUnorm
| Tf::Bc1RgbaUnormSrgb
| Tf::Bc2RgbaUnorm
@ -698,36 +702,35 @@ impl NumericType {
| Tf::Etc2Rgb8A1Unorm
| Tf::Etc2Rgb8A1UnormSrgb
| Tf::Etc2Rgba8Unorm
| Tf::Etc2Rgba8UnormSrgb => (NumericDimension::Vector(Vs::Quad), Sk::Float),
| Tf::Etc2Rgba8UnormSrgb => (NumericDimension::Vector(Vs::Quad), Scalar::F32),
Tf::Bc4RUnorm | Tf::Bc4RSnorm | Tf::EacR11Unorm | Tf::EacR11Snorm => {
(NumericDimension::Scalar, Sk::Float)
(NumericDimension::Scalar, Scalar::F32)
}
Tf::Bc5RgUnorm | Tf::Bc5RgSnorm | Tf::EacRg11Unorm | Tf::EacRg11Snorm => {
(NumericDimension::Vector(Vs::Bi), Sk::Float)
(NumericDimension::Vector(Vs::Bi), Scalar::F32)
}
Tf::Bc6hRgbUfloat | Tf::Bc6hRgbFloat | Tf::Etc2Rgb8Unorm | Tf::Etc2Rgb8UnormSrgb => {
(NumericDimension::Vector(Vs::Tri), Sk::Float)
(NumericDimension::Vector(Vs::Tri), Scalar::F32)
}
Tf::Astc {
block: _,
channel: _,
} => (NumericDimension::Vector(Vs::Quad), Sk::Float),
} => (NumericDimension::Vector(Vs::Quad), Scalar::F32),
};
NumericType {
dim,
kind,
//Note: Shader always sees data as int, uint, or float.
// It doesn't know if the original is normalized in a tighter form.
width: 4,
scalar,
}
}
fn is_subtype_of(&self, other: &NumericType) -> bool {
if self.width > other.width {
if self.scalar.width > other.scalar.width {
return false;
}
if self.kind != other.kind {
if self.scalar.kind != other.scalar.kind {
return false;
}
match (self.dim, other.dim) {
@ -742,7 +745,7 @@ impl NumericType {
}
fn is_compatible_with(&self, other: &NumericType) -> bool {
if self.kind != other.kind {
if self.scalar.kind != other.scalar.kind {
return false;
}
match (self.dim, other.dim) {
@ -778,15 +781,13 @@ impl Interface {
arena: &naga::UniqueArena<naga::Type>,
) {
let numeric_ty = match arena[ty].inner {
naga::TypeInner::Scalar { kind, width } => NumericType {
naga::TypeInner::Scalar(scalar) => NumericType {
dim: NumericDimension::Scalar,
kind,
width,
scalar,
},
naga::TypeInner::Vector { size, kind, width } => NumericType {
naga::TypeInner::Vector { size, scalar } => NumericType {
dim: NumericDimension::Vector(size),
kind,
width,
scalar,
},
naga::TypeInner::Matrix {
columns,
@ -794,8 +795,7 @@ impl Interface {
width,
} => NumericType {
dim: NumericDimension::Matrix(columns, rows),
kind: naga::ScalarKind::Float,
width,
scalar: naga::Scalar::float(width),
},
naga::TypeInner::Struct { ref members, .. } => {
for member in members {

View File

@ -1463,33 +1463,27 @@ impl super::Queue {
//
// --- Float 1-4 Component ---
//
naga::TypeInner::Scalar {
kind: naga::ScalarKind::Float,
width: 4,
} => {
naga::TypeInner::Scalar(naga::Scalar::F32) => {
let data = unsafe { get_data::<f32, 1>(data_bytes, offset)[0] };
unsafe { gl.uniform_1_f32(location, data) };
}
naga::TypeInner::Vector {
kind: naga::ScalarKind::Float,
size: naga::VectorSize::Bi,
width: 4,
scalar: naga::Scalar::F32,
} => {
let data = unsafe { get_data::<f32, 2>(data_bytes, offset) };
unsafe { gl.uniform_2_f32_slice(location, data) };
}
naga::TypeInner::Vector {
kind: naga::ScalarKind::Float,
size: naga::VectorSize::Tri,
width: 4,
scalar: naga::Scalar::F32,
} => {
let data = unsafe { get_data::<f32, 3>(data_bytes, offset) };
unsafe { gl.uniform_3_f32_slice(location, data) };
}
naga::TypeInner::Vector {
kind: naga::ScalarKind::Float,
size: naga::VectorSize::Quad,
width: 4,
scalar: naga::Scalar::F32,
} => {
let data = unsafe { get_data::<f32, 4>(data_bytes, offset) };
unsafe { gl.uniform_4_f32_slice(location, data) };
@ -1498,33 +1492,27 @@ impl super::Queue {
//
// --- Int 1-4 Component ---
//
naga::TypeInner::Scalar {
kind: naga::ScalarKind::Sint,
width: 4,
} => {
naga::TypeInner::Scalar(naga::Scalar::I32) => {
let data = unsafe { get_data::<i32, 1>(data_bytes, offset)[0] };
unsafe { gl.uniform_1_i32(location, data) };
}
naga::TypeInner::Vector {
kind: naga::ScalarKind::Sint,
size: naga::VectorSize::Bi,
width: 4,
scalar: naga::Scalar::I32,
} => {
let data = unsafe { get_data::<i32, 2>(data_bytes, offset) };
unsafe { gl.uniform_2_i32_slice(location, data) };
}
naga::TypeInner::Vector {
kind: naga::ScalarKind::Sint,
size: naga::VectorSize::Tri,
width: 4,
scalar: naga::Scalar::I32,
} => {
let data = unsafe { get_data::<i32, 3>(data_bytes, offset) };
unsafe { gl.uniform_3_i32_slice(location, data) };
}
naga::TypeInner::Vector {
kind: naga::ScalarKind::Sint,
size: naga::VectorSize::Quad,
width: 4,
scalar: naga::Scalar::I32,
} => {
let data = unsafe { get_data::<i32, 4>(data_bytes, offset) };
unsafe { gl.uniform_4_i32_slice(location, data) };
@ -1533,33 +1521,27 @@ impl super::Queue {
//
// --- Uint 1-4 Component ---
//
naga::TypeInner::Scalar {
kind: naga::ScalarKind::Uint,
width: 4,
} => {
naga::TypeInner::Scalar(naga::Scalar::U32) => {
let data = unsafe { get_data::<u32, 1>(data_bytes, offset)[0] };
unsafe { gl.uniform_1_u32(location, data) };
}
naga::TypeInner::Vector {
kind: naga::ScalarKind::Uint,
size: naga::VectorSize::Bi,
width: 4,
scalar: naga::Scalar::U32,
} => {
let data = unsafe { get_data::<u32, 2>(data_bytes, offset) };
unsafe { gl.uniform_2_u32_slice(location, data) };
}
naga::TypeInner::Vector {
kind: naga::ScalarKind::Uint,
size: naga::VectorSize::Tri,
width: 4,
scalar: naga::Scalar::U32,
} => {
let data = unsafe { get_data::<u32, 3>(data_bytes, offset) };
unsafe { gl.uniform_3_u32_slice(location, data) };
}
naga::TypeInner::Vector {
kind: naga::ScalarKind::Uint,
size: naga::VectorSize::Quad,
width: 4,
scalar: naga::Scalar::U32,
} => {
let data = unsafe { get_data::<u32, 4>(data_bytes, offset) };
unsafe { gl.uniform_4_u32_slice(location, data) };