From e64f28375e8e813e81ef70bb2699ddd1871eee7e Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 10 Sep 2020 01:43:27 -0400 Subject: [PATCH] ir: bitcast expression --- src/back/glsl.rs | 187 ++++++++++++++++++------------------------ src/front/spv/mod.rs | 12 ++- src/lib.rs | 11 ++- src/proc/interface.rs | 2 +- src/proc/typifier.rs | 6 +- 5 files changed, 103 insertions(+), 115 deletions(-) diff --git a/src/back/glsl.rs b/src/back/glsl.rs index 708374e5bb..589a054120 100644 --- a/src/back/glsl.rs +++ b/src/back/glsl.rs @@ -684,20 +684,7 @@ fn write_expression<'a, 'b>( let constructor = match module.types[ty].inner { TypeInner::Vector { size, kind, width } => format!( "{}vec{}", - match kind { - ScalarKind::Sint => "i", - ScalarKind::Uint => "u", - ScalarKind::Float => match width { - 4 => "", - 8 => "d", - _ => - return Err(Error::Custom(format!( - "Cannot build float of width {}", - width - ))), - }, - ScalarKind::Bool => "b", - }, + map_scalar(kind, width, builder.features)?.prefix, size as u8, ), TypeInner::Matrix { @@ -707,20 +694,7 @@ fn write_expression<'a, 'b>( width, } => format!( "{}mat{}x{}", - match kind { - ScalarKind::Sint => "i", - ScalarKind::Uint => "u", - ScalarKind::Float => match width { - 4 => "", - 8 => "d", - _ => - return Err(Error::Custom(format!( - "Cannot build float of width {}", - width - ))), - }, - ScalarKind::Bool => "b", - }, + map_scalar(kind, width, builder.features)?.prefix, columns as u8, rows as u8, ), @@ -820,12 +794,7 @@ fn write_expression<'a, 'b>( let sampler_constructor = format!( "{}sampler{}{}{}{}({},{})", - match kind { - ScalarKind::Sint => "i", - ScalarKind::Uint => "u", - ScalarKind::Float => "", - _ => return Err(Error::Custom(String::from("Cannot build image of bools",))), - }, + map_scalar(kind, 4, builder.features)?.prefix, ImageDimension(dim), if ms { "MS" } else { "" }, if arrayed { "Array" } else { "" }, @@ -917,15 +886,7 @@ fn write_expression<'a, 'b>( //TODO: fix this let sampler_constructor = format!( "{}sampler{}{}{}({})", - match kind { - ScalarKind::Sint => "i", - ScalarKind::Uint => "u", - ScalarKind::Float => "", - _ => - return Err(Error::Custom(String::from( - "Cannot build image of bools" - ))), - }, + map_scalar(kind, 4, builder.features)?.prefix, ImageDimension(dim), if ms { "MS" } else { "" }, if arrayed { "Array" } else { "" }, @@ -1137,26 +1098,47 @@ fn write_expression<'a, 'b>( left_ty, ) } - Expression::As(value, kind) => { + Expression::As { + expr, + kind, + convert, + } => { let (value_expr, value_ty) = - write_expression(&builder.expressions[value], module, builder)?; - let (width, out_ty) = match *value_ty.borrow() { - TypeInner::Scalar { width, kind: _ } => { - (width, MaybeOwned::Owned(TypeInner::Scalar { kind, width })) - } - TypeInner::Vector { - width, - kind: _, - size, - } => ( - width, + write_expression(&builder.expressions[expr], module, builder)?; + let (source_kind, ty_expr, out_ty) = match *value_ty.borrow() { + TypeInner::Scalar { width, kind } => ( + kind, + Cow::Borrowed(map_scalar(kind, width, builder.features)?.full), + MaybeOwned::Owned(TypeInner::Scalar { kind, width }), + ), + TypeInner::Vector { width, kind, size } => ( + kind, + Cow::Owned(format!( + "{}vec", + map_scalar(kind, width, builder.features)?.prefix + )), MaybeOwned::Owned(TypeInner::Vector { kind, width, size }), ), - _ => return Err(Error::Custom(format!("Cannot cast {}", value_expr))), + _ => return Err(Error::Custom(format!("Cannot convert {}", value_expr))), + }; + let op = if convert { + ty_expr + } else { + Cow::Borrowed(match (source_kind, kind) { + (ScalarKind::Float, ScalarKind::Sint) => "floatBitsToInt", + (ScalarKind::Float, ScalarKind::Uint) => "floatBitsToUInt", + (ScalarKind::Sint, ScalarKind::Float) => "intBitsToFloat", + (ScalarKind::Uint, ScalarKind::Float) => "uintBitsToFloat", + _ => { + return Err(Error::Custom(format!( + "Cannot bitcast {:?} to {:?}", + source_kind, kind + ))) + } + }) }; - let ty_expr = map_scalar(kind, width, builder.features)?; - (Cow::Owned(format!("{}({})", ty_expr, value_expr)), out_ty) + (Cow::Owned(format!("{}({})", op, value_expr)), out_ty) } Expression::Derivative { axis, expr } => { let (expr, ty) = write_expression(&builder.expressions[expr], module, builder)?; @@ -1255,17 +1237,34 @@ fn write_constant( }) } +struct ScalarString<'a> { + prefix: &'a str, + full: &'a str, +} + fn map_scalar( kind: ScalarKind, width: crate::Bytes, features: SupportedFeatures, -) -> Result<&'static str, Error> { +) -> Result, Error> { Ok(match kind { - ScalarKind::Sint => "int", - ScalarKind::Uint => "uint", + ScalarKind::Sint => ScalarString { + prefix: "i", + full: "int", + }, + ScalarKind::Uint => ScalarString { + prefix: "u", + full: "uint", + }, ScalarKind::Float => match width { - 4 => "float", - 8 if features.contains(SupportedFeatures::DOUBLE_TYPE) => "double", + 4 => ScalarString { + prefix: "", + full: "float", + }, + 8 if features.contains(SupportedFeatures::DOUBLE_TYPE) => ScalarString { + prefix: "d", + full: "double", + }, _ => { return Err(Error::Custom(format!( "Cannot build float of width {}", @@ -1273,7 +1272,10 @@ fn map_scalar( ))) } }, - ScalarKind::Bool => "bool", + ScalarKind::Bool => ScalarString { + prefix: "b", + full: "bool", + }, }) } @@ -1285,23 +1287,10 @@ fn write_type<'a>( features: SupportedFeatures, ) -> Result, Error> { Ok(match types[ty].inner { - TypeInner::Scalar { kind, width } => Cow::Borrowed(map_scalar(kind, width, features)?), + TypeInner::Scalar { kind, width } => Cow::Borrowed(map_scalar(kind, width, features)?.full), TypeInner::Vector { size, kind, width } => Cow::Owned(format!( "{}vec{}", - match kind { - ScalarKind::Sint => "i", - ScalarKind::Uint => "u", - ScalarKind::Float => match width { - 4 => "", - 8 if features.contains(SupportedFeatures::DOUBLE_TYPE) => "d", - _ => - return Err(Error::Custom(format!( - "Cannot build float of width {}", - width - ))), - }, - ScalarKind::Bool => "b", - }, + map_scalar(kind, width, features)?.prefix, size as u8 )), TypeInner::Matrix { @@ -1311,27 +1300,15 @@ fn write_type<'a>( width, } => Cow::Owned(format!( "{}mat{}x{}", - match kind { - ScalarKind::Sint if features.contains(SupportedFeatures::NON_FLOAT_MATRICES) => "i", - ScalarKind::Uint if features.contains(SupportedFeatures::NON_FLOAT_MATRICES) => "u", - ScalarKind::Float => match width { - 4 => "", - 8 if features.contains( - SupportedFeatures::DOUBLE_TYPE & SupportedFeatures::NON_FLOAT_MATRICES - ) => - "d", - _ => - return Err(Error::Custom(format!( - "Cannot build float of width {}", - width - ))), - }, - ScalarKind::Bool if features.contains(SupportedFeatures::NON_FLOAT_MATRICES) => "b", - _ => - return Err(Error::Custom(format!( - "Cannot build matrix of base type {:?}", - kind - ))), + if (width == 4 && kind == ScalarKind::Float) + || features.contains(SupportedFeatures::NON_FLOAT_MATRICES) + { + map_scalar(kind, width, features)?.prefix + } else { + return Err(Error::Custom(format!( + "Cannot build matrix of base type {:?}", + kind + ))); }, columns as u8, rows as u8 @@ -1384,15 +1361,7 @@ fn write_type<'a>( Cow::Owned(format!( "{}{}{}{}", - match kind { - ScalarKind::Sint => "i", - ScalarKind::Uint => "u", - ScalarKind::Float => "", - ScalarKind::Bool => - return Err(Error::Custom(String::from( - "Cannot build image of booleans", - ))), - }, + map_scalar(kind, 4, features)?.prefix, match class { ImageClass::Storage(_) => "image", _ => "texture", diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index e467dec02f..559d1a30ae 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -1087,7 +1087,11 @@ impl> Parser { }, ); } - Op::ConvertSToF | Op::ConvertUToF | Op::ConvertFToU | Op::ConvertFToS => { + Op::Bitcast + | Op::ConvertSToF + | Op::ConvertUToF + | Op::ConvertFToU + | Op::ConvertFToS => { inst.expect_at_least(4)?; let result_type_id = self.next()?; let result_id = self.next()?; @@ -1101,7 +1105,11 @@ impl> Parser { _ => return Err(Error::InvalidAsType(ty_lookup.handle)), }; - let expr = crate::Expression::As(value_lexp.handle, kind); + let expr = crate::Expression::As { + expr: value_lexp.handle, + kind, + convert: inst.op != Op::Bitcast, + }; self.lookup_expression.insert( result_id, LookupExpression { diff --git a/src/lib.rs b/src/lib.rs index c4c9f15960..2b65d8ac81 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -615,8 +615,15 @@ pub enum Expression { DotProduct(Handle, Handle), /// Cross product between two vectors. CrossProduct(Handle, Handle), - /// Cast a scalar or a vector to another kind. - As(Handle, ScalarKind), + /// Cast a simply type to another kind. + As { + /// Source expression, which can only be a scalar or a vector. + expr: Handle, + /// Target scalar kind. + kind: ScalarKind, + /// True = conversion needs to take place; False = bitcast. + convert: bool, + }, /// Compute the derivative on an axis. Derivative { axis: DerivativeAxis, diff --git a/src/proc/interface.rs b/src/proc/interface.rs index 4e2ec5f8b7..394033874c 100644 --- a/src/proc/interface.rs +++ b/src/proc/interface.rs @@ -89,7 +89,7 @@ where self.traverse_expr(left); self.traverse_expr(right); } - E::As(expr, _) => { + E::As { expr, .. } => { self.traverse_expr(expr); } E::Derivative { expr, .. } => { diff --git a/src/proc/typifier.rs b/src/proc/typifier.rs index 7ae2de663c..58e0edc3e5 100644 --- a/src/proc/typifier.rs +++ b/src/proc/typifier.rs @@ -186,7 +186,11 @@ impl Typifier { } } crate::Expression::CrossProduct(_, _) => unimplemented!(), - crate::Expression::As(expr, kind) => { + crate::Expression::As { + expr, + kind, + convert: _, + } => { let ty_handle = self.types[expr.index()]; match arena[ty_handle].inner { crate::TypeInner::Scalar { kind: _, width } => {