As expressions

This commit is contained in:
Dzmitry Malyshau
2020-08-27 00:19:39 -04:00
committed by Dzmitry Malyshau
parent 35e14378b3
commit 462c82fb71
6 changed files with 97 additions and 16 deletions

View File

@@ -1041,6 +1041,24 @@ fn write_expression<'a, 'b>(
left_ty,
)
}
Expression::As(value, kind) => {
let (value_expr, value_ty) =
write_expression(&builder.expressions[value], module, builder)?;
let (width, out_ty) = match *value_ty.as_ref() {
TypeInner::Scalar { width, kind: _ } => {
(width, Cow::Owned(TypeInner::Scalar { kind, width }))
}
TypeInner::Vector {
width,
kind: _,
size,
} => (width, Cow::Owned(TypeInner::Vector { kind, width, size })),
_ => return Err(Error::Custom(format!("Cannot cast {}", value_expr))),
};
let ty_expr = map_scalar(kind, width, builder.features)?;
(Cow::Owned(format!("{}({})", ty_expr, value_expr)), out_ty)
}
Expression::Derivative { axis, expr } => {
let (expr, ty) = write_expression(&builder.expressions[expr], module, builder)?;
@@ -1138,6 +1156,28 @@ fn write_constant(
})
}
fn map_scalar(
kind: ScalarKind,
width: crate::Bytes,
features: SupportedFeatures,
) -> Result<&'static str, Error> {
Ok(match kind {
ScalarKind::Sint => "int",
ScalarKind::Uint => "uint",
ScalarKind::Float => match width {
4 => "float",
8 if features.contains(SupportedFeatures::DOUBLE_TYPE) => "double",
_ => {
return Err(Error::Custom(format!(
"Cannot build float of width {}",
width
)))
}
},
ScalarKind::Bool => "bool",
})
}
fn write_type<'a>(
ty: Handle<Type>,
types: &Arena<Type>,
@@ -1146,21 +1186,7 @@ fn write_type<'a>(
features: SupportedFeatures,
) -> Result<Cow<'a, str>, Error> {
Ok(match types[ty].inner {
TypeInner::Scalar { kind, width } => match kind {
ScalarKind::Sint => Cow::Borrowed("int"),
ScalarKind::Uint => Cow::Borrowed("uint"),
ScalarKind::Float => match width {
4 => Cow::Borrowed("float"),
8 if features.contains(SupportedFeatures::DOUBLE_TYPE) => Cow::Borrowed("double"),
_ => {
return Err(Error::Custom(format!(
"Cannot build float of width {}",
width
)))
}
},
ScalarKind::Bool => Cow::Borrowed("bool"),
},
TypeInner::Scalar { kind, width } => Cow::Borrowed(map_scalar(kind, width, features)?),
TypeInner::Vector { size, kind, width } => Cow::Owned(format!(
"{}vec{}",
match kind {

View File

@@ -44,6 +44,7 @@ pub enum Error {
InvalidSampleSampler(Handle<crate::Type>),
InvalidSampleCoordinates(Handle<crate::Type>),
InvalidDepthReference(Handle<crate::Type>),
InvalidAsType(Handle<crate::Type>),
InconsistentComparisonSampling(Handle<crate::Type>),
WrongFunctionResultType(spirv::Word),
WrongFunctionParameterType(spirv::Word),

View File

@@ -1009,6 +1009,29 @@ impl<I: Iterator<Item = u32>> Parser<I> {
},
);
}
Op::ConvertSToF | Op::ConvertUToF | Op::ConvertFToU | Op::ConvertFToS => {
inst.expect_at_least(4)?;
let result_type_id = self.next()?;
let result_id = self.next()?;
let value_id = self.next()?;
let value_expr = self.lookup_expression.lookup(value_id)?;
let ty_lookup = self.lookup_type.lookup(result_type_id)?;
let kind = match type_arena[ty_lookup.handle].inner {
crate::TypeInner::Scalar { kind, .. }
| crate::TypeInner::Vector { kind, .. } => kind,
_ => return Err(Error::InvalidAsType(ty_lookup.handle)),
};
let expr = crate::Expression::As(value_expr.handle, kind);
self.lookup_expression.insert(
result_id,
LookupExpression {
handle: expressions.append(expr),
type_id: result_type_id,
},
);
}
Op::FunctionCall => {
inst.expect_at_least(4)?;
let result_type_id = self.next()?;

View File

@@ -526,6 +526,8 @@ pub enum Expression {
DotProduct(Handle<Expression>, Handle<Expression>),
/// Cross product between two vectors.
CrossProduct(Handle<Expression>, Handle<Expression>),
/// Cast a scalar or a vector to another kind.
As(Handle<Expression>, ScalarKind),
/// Compute the derivative on an axis.
Derivative {
axis: DerivativeAxis,

View File

@@ -80,6 +80,9 @@ impl<'a> Interface<'a> {
self.add_inputs(left);
self.add_inputs(right);
}
E::As(expr, _) => {
self.add_inputs(expr);
}
E::Derivative { expr, .. } => {
self.add_inputs(expr);
}

View File

@@ -182,8 +182,34 @@ impl Typifier {
};
types.fetch_or_append(Type { name: None, inner })
}
crate::Expression::DotProduct(_, _) => unimplemented!(),
crate::Expression::DotProduct(left_expr, _) => {
let left_ty = self.types[left_expr.index()];
let inner = match types[left_ty].inner {
crate::TypeInner::Vector {
kind,
size: _,
width,
} => crate::TypeInner::Scalar { kind, width },
ref other => panic!("incompatible dot of {:?}", other),
};
types.fetch_or_append(Type { name: None, inner })
}
crate::Expression::CrossProduct(_, _) => unimplemented!(),
crate::Expression::As(expr, kind) => {
let ty_handle = self.types[expr.index()];
let inner = match types[ty_handle].inner {
crate::TypeInner::Scalar { kind: _, width } => {
crate::TypeInner::Scalar { kind, width }
}
crate::TypeInner::Vector {
kind: _,
size,
width,
} => crate::TypeInner::Vector { kind, size, width },
ref other => panic!("incompatible as of {:?}", other),
};
types.fetch_or_append(Type { name: None, inner })
}
crate::Expression::Derivative { .. } => unimplemented!(),
crate::Expression::Call {
origin: crate::FunctionOrigin::External(ref name),