diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index 0e04093bb6..f45c93a49b 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -44,14 +44,9 @@ pub use features::Features; use crate::{ - back::{FunctionCtx, FunctionType, COMPONENTS, INDENT}, - proc::{EntryPointIndex, NameKey, Namer, TypeResolution}, - valid::{FunctionInfo, ModuleInfo}, - ArraySize, BinaryOperator, Binding, BuiltIn, Bytes, ConservativeDepth, Constant, ConstantInner, - DerivativeAxis, Expression, FastHashMap, Function, GlobalVariable, Handle, ImageClass, - Interpolation, Module, RelationalFunction, Sampling, ScalarKind, ScalarValue, ShaderStage, - Statement, StorageAccess, StorageClass, StorageFormat, StructMember, Type, TypeInner, - UnaryOperator, + back, + proc::{self, NameKey}, + valid, Handle, ShaderStage, TypeInner, }; use features::FeaturesManager; use std::{ @@ -153,8 +148,8 @@ impl Default for Options { /// Structure that contains a reflection info pub struct ReflectionInfo { - pub texture_mapping: FastHashMap, - pub uniforms: FastHashMap, String>, + pub texture_mapping: crate::FastHashMap, + pub uniforms: crate::FastHashMap, String>, } /// Structure that connects a texture to a sampler or not @@ -169,9 +164,9 @@ pub struct ReflectionInfo { #[derive(Debug, Clone)] pub struct TextureMapping { /// Handle to the image global variable - pub texture: Handle, + pub texture: Handle, /// Handle to the associated sampler global variable if it exists - pub sampler: Option>, + pub sampler: Option>, } /// Helper structure that generates a number @@ -196,14 +191,14 @@ impl IdGenerator { /// prefix identifying which pipeline stage the varying connects, and `X` is /// the location. struct VaryingName<'a> { - binding: &'a Binding, + binding: &'a crate::Binding, stage: ShaderStage, output: bool, } impl fmt::Display for VaryingName<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self.binding { - Binding::Location { location, .. } => { + crate::Binding::Location { location, .. } => { let prefix = match (self.stage, self.output) { (ShaderStage::Compute, _) => unreachable!(), // pipeline to vertex @@ -215,7 +210,7 @@ impl fmt::Display for VaryingName<'_> { }; write!(f, "_{}_location{}", prefix, location,) } - Binding::BuiltIn(built_in) => { + crate::Binding::BuiltIn(built_in) => { write!(f, "{}", glsl_built_in(built_in, self.output)) } } @@ -251,7 +246,7 @@ pub enum Error { UnsupportedExternal(String), /// A scalar with an unsupported width was requested #[error("A scalar with an unsupported width was requested: {0:?} {1:?}")] - UnsupportedScalar(ScalarKind, Bytes), + UnsupportedScalar(crate::ScalarKind, crate::Bytes), /// A image was used with multiple samplers, this isn't supported #[error("A image was used with multiple samplers")] ImageMultipleSamplers, @@ -263,9 +258,9 @@ pub enum Error { pub struct Writer<'a, W> { // Inputs /// The module being written - module: &'a Module, + module: &'a crate::Module, /// The module analysis. - info: &'a ModuleInfo, + info: &'a valid::ModuleInfo, /// The output writer out: W, /// User defined configuration to be used @@ -274,16 +269,16 @@ pub struct Writer<'a, W> { // Internal State /// Features manager used to store all the needed features and write them features: FeaturesManager, - namer: Namer, + namer: proc::Namer, /// A map with all the names needed for writing the module /// (generated by a [`Namer`](crate::proc::Namer)) - names: FastHashMap, + names: crate::FastHashMap, /// A map with all the names needed for reflections - reflection_names: FastHashMap, String>, + reflection_names: crate::FastHashMap, String>, /// The selected entry point entry_point: &'a crate::EntryPoint, /// The index of the selected entry point - entry_point_idx: EntryPointIndex, + entry_point_idx: proc::EntryPointIndex, /// Used to generate a unique number for blocks block_id: IdGenerator, /// Set of expressions that have associated temporary variables @@ -299,8 +294,8 @@ impl<'a, W: Write> Writer<'a, W> { /// - If the version specified doesn't support some used features pub fn new( out: W, - module: &'a Module, - info: &'a ModuleInfo, + module: &'a crate::Module, + info: &'a valid::ModuleInfo, options: &'a Options, ) -> Result { // Check if the requested version is supported @@ -317,8 +312,8 @@ impl<'a, W: Write> Writer<'a, W> { .ok_or(Error::EntryPointNotFound)?; // Generate a map with names required to write the module - let mut names = FastHashMap::default(); - let mut namer = Namer::default(); + let mut names = crate::FastHashMap::default(); + let mut namer = proc::Namer::default(); namer.reset(module, keywords::RESERVED_KEYWORDS, &["gl_"], &mut names); // Build the instance @@ -330,7 +325,7 @@ impl<'a, W: Write> Writer<'a, W> { namer, features: FeaturesManager::new(), names, - reflection_names: FastHashMap::default(), + reflection_names: crate::FastHashMap::default(), entry_point: &module.entry_points[ep_idx], entry_point_idx: ep_idx as u16, @@ -390,13 +385,15 @@ impl<'a, W: Write> Writer<'a, W> { writeln!(self.out, "layout(early_fragment_tests) in;")?; if let Some(conservative) = depth_test.conservative { + use crate::ConservativeDepth as Cd; + writeln!( self.out, "layout (depth_{}) out float gl_FragDepth;", match conservative { - ConservativeDepth::GreaterEqual => "greater", - ConservativeDepth::LessEqual => "less", - ConservativeDepth::Unchanged => "unchanged", + Cd::GreaterEqual => "greater", + Cd::LessEqual => "less", + Cd::Unchanged => "unchanged", } )?; } @@ -444,7 +441,7 @@ impl<'a, W: Write> Writer<'a, W> { } => { // Write the storage format if needed if let TypeInner::Image { - class: ImageClass::Storage(format), + class: crate::ImageClass::Storage(format), .. } = self.module.types[global.ty].inner { @@ -505,13 +502,18 @@ impl<'a, W: Write> Writer<'a, W> { let fun_info = &self.info[handle]; // Write the function - self.write_function(FunctionType::Function(handle), function, fun_info, &name)?; + self.write_function( + back::FunctionType::Function(handle), + function, + fun_info, + &name, + )?; writeln!(self.out)?; } self.write_function( - FunctionType::EntryPoint(self.entry_point_idx), + back::FunctionType::EntryPoint(self.entry_point_idx), &self.entry_point.function, ep_info, "main", @@ -524,21 +526,23 @@ impl<'a, W: Write> Writer<'a, W> { self.collect_reflection_info() } - fn write_array_size(&mut self, size: ArraySize) -> BackendResult { + fn write_array_size(&mut self, size: crate::ArraySize) -> BackendResult { write!(self.out, "[")?; // Write the array size // Writes nothing if `ArraySize::Dynamic` // Panics if `ArraySize::Constant` has a constant that isn't an uint match size { - ArraySize::Constant(const_handle) => match self.module.constants[const_handle].inner { - ConstantInner::Scalar { - width: _, - value: ScalarValue::Uint(size), - } => write!(self.out, "{}", size)?, - _ => unreachable!(), - }, - ArraySize::Dynamic => (), + crate::ArraySize::Constant(const_handle) => { + match self.module.constants[const_handle].inner { + crate::ConstantInner::Scalar { + width: _, + value: crate::ScalarValue::Uint(size), + } => write!(self.out, "{}", size)?, + _ => unreachable!(), + } + } + crate::ArraySize::Dynamic => (), } write!(self.out, "]")?; @@ -589,7 +593,7 @@ impl<'a, W: Write> Writer<'a, W> { } => write!( self.out, "{}mat{}x{}", - glsl_scalar(ScalarKind::Float, width)?.prefix, + glsl_scalar(crate::ScalarKind::Float, width)?.prefix, columns as u8, rows as u8 )?, @@ -619,7 +623,7 @@ impl<'a, W: Write> Writer<'a, W> { /// - If type is either a image or sampler /// - If it's an Array with a [`ArraySize::Constant`](crate::ArraySize::Constant) with a /// constant that isn't [`Uint`](crate::ConstantInner::Uint) - fn write_type(&mut self, ty: Handle) -> BackendResult { + fn write_type(&mut self, ty: Handle) -> BackendResult { match self.module.types[ty].inner { // glsl has no pointer types so just write types as normal and loads are skipped TypeInner::Pointer { base, .. } => self.write_type(base), @@ -649,7 +653,7 @@ impl<'a, W: Write> Writer<'a, W> { &mut self, dim: crate::ImageDimension, arrayed: bool, - class: ImageClass, + class: crate::ImageClass, ) -> BackendResult { // glsl images consist of four parts the scalar prefix, the image "type", the dimensions // and modifiers @@ -663,12 +667,13 @@ impl<'a, W: Write> Writer<'a, W> { // - MS - used if it's a multisampled image // - Array - used if it's an image array // - Shadow - used if it's a depth image + use crate::ImageClass as Ic; let (base, kind, ms, comparison) = match class { - ImageClass::Sampled { kind, multi: true } => ("sampler", kind, "MS", ""), - ImageClass::Sampled { kind, multi: false } => ("sampler", kind, "", ""), - ImageClass::Depth => ("sampler", crate::ScalarKind::Float, "", "Shadow"), - ImageClass::Storage(format) => ("image", format.into(), "", ""), + Ic::Sampled { kind, multi: true } => ("sampler", kind, "MS", ""), + Ic::Sampled { kind, multi: false } => ("sampler", kind, "", ""), + Ic::Depth => ("sampler", crate::ScalarKind::Float, "", "Shadow"), + Ic::Storage(format) => ("image", format.into(), "", ""), }; write!( @@ -694,8 +699,8 @@ impl<'a, W: Write> Writer<'a, W> { /// If the global has type sampler fn write_global( &mut self, - handle: Handle, - global: &GlobalVariable, + handle: Handle, + global: &crate::GlobalVariable, ) -> BackendResult { if let Some(storage_access) = glsl_storage_access(global.storage_access) { write!(self.out, "{} ", storage_access)?; @@ -737,7 +742,11 @@ impl<'a, W: Write> Writer<'a, W> { /// - Globals without bindings use the name from the [`Namer`](crate::proc::Namer) /// - Globals with resource binding are named `_group_X_binding_Y` where `X` /// is the group and `Y` is the binding - fn get_global_name(&self, handle: Handle, global: &GlobalVariable) -> String { + fn get_global_name( + &self, + handle: Handle, + global: &crate::GlobalVariable, + ) -> String { match global.binding { Some(ref br) => { format!("_group_{}_binding_{}", br.group, br.binding) @@ -749,8 +758,8 @@ impl<'a, W: Write> Writer<'a, W> { /// Writes the varying declaration. fn write_varying( &mut self, - binding: Option<&Binding>, - ty: Handle, + binding: Option<&crate::Binding>, + ty: Handle, output: bool, ) -> Result<(), Error> { match self.module.types[ty].inner { @@ -761,7 +770,7 @@ impl<'a, W: Write> Writer<'a, W> { } _ => { let (location, interpolation, sampling) = match binding { - Some(&Binding::Location { + Some(&crate::Binding::Location { location, interpolation, sampling, @@ -814,7 +823,7 @@ impl<'a, W: Write> Writer<'a, W> { // Finally write the global name and end the global with a `;` and a newline // Leading space is important let vname = VaryingName { - binding: &Binding::Location { + binding: &crate::Binding::Location { location, interpolation: None, sampling: None, @@ -834,13 +843,13 @@ impl<'a, W: Write> Writer<'a, W> { /// Adds a newline fn write_function( &mut self, - ty: FunctionType, - func: &Function, - info: &FunctionInfo, + ty: back::FunctionType, + func: &crate::Function, + info: &valid::FunctionInfo, name: &str, ) -> BackendResult { // Create a function context for the function being written - let ctx = FunctionCtx { + let ctx = back::FunctionCtx { ty, info, expressions: &func.expressions, @@ -862,7 +871,7 @@ impl<'a, W: Write> Writer<'a, W> { // Start by writing the return type if any otherwise write void // This is the only place where `void` is a valid type // (though it's more a keyword than a type) - if let FunctionType::EntryPoint(_) = ctx.ty { + if let back::FunctionType::EntryPoint(_) = ctx.ty { write!(self.out, "void")?; } else if let Some(ref result) = func.result { self.write_type(result.ty)?; @@ -878,8 +887,8 @@ impl<'a, W: Write> Writer<'a, W> { // We need access to `Self` here so we use the reference passed to the closure as an // argument instead of capturing as that would cause a borrow checker error let arguments = match ctx.ty { - FunctionType::EntryPoint(_) => &[][..], - FunctionType::Function(_) => &func.arguments, + back::FunctionType::EntryPoint(_) => &[][..], + back::FunctionType::Function(_) => &func.arguments, }; self.write_slice(arguments, |this, i, arg| { // Write the argument type @@ -897,10 +906,10 @@ impl<'a, W: Write> Writer<'a, W> { writeln!(self.out, ") {{")?; // Compose the function arguments from globals, in case of an entry point. - if let FunctionType::EntryPoint(ep_index) = ctx.ty { + if let back::FunctionType::EntryPoint(ep_index) = ctx.ty { let stage = self.module.entry_points[ep_index as usize].stage; for (index, arg) in func.arguments.iter().enumerate() { - write!(self.out, "{}", INDENT)?; + write!(self.out, "{}", back::INDENT)?; self.write_type(arg.ty)?; let name = &self.names[&NameKey::EntryPointArgument(ep_index, index as u32)]; write!(self.out, " {}", name)?; @@ -941,7 +950,7 @@ impl<'a, W: Write> Writer<'a, W> { for (handle, local) in func.local_variables.iter() { // Write indentation (only for readability) and the type // `write_type` adds no trailing space - write!(self.out, "{}", INDENT)?; + write!(self.out, "{}", back::INDENT)?; self.write_type(local.ty)?; // Write the local name @@ -1009,28 +1018,30 @@ impl<'a, W: Write> Writer<'a, W> { /// /// # Notes /// Adds no newlines or leading/trailing whitespace - fn write_constant(&mut self, constant: &Constant) -> BackendResult { + fn write_constant(&mut self, constant: &crate::Constant) -> BackendResult { + use crate::ScalarValue as Sv; + match constant.inner { - ConstantInner::Scalar { + crate::ConstantInner::Scalar { width: _, ref value, } => match *value { // Signed integers don't need anything special - ScalarValue::Sint(int) => write!(self.out, "{}", int)?, + Sv::Sint(int) => write!(self.out, "{}", int)?, // Unsigned integers need a `u` at the end // // While `core` doesn't necessarily need it, it's allowed and since `es` needs it we // always write it as the extra branch wouldn't have any benefit in readability - ScalarValue::Uint(int) => write!(self.out, "{}u", int)?, + Sv::Uint(int) => write!(self.out, "{}u", int)?, // Floats are written using `Debug` instead of `Display` because it always appends the // decimal part even it's zero which is needed for a valid glsl float constant - ScalarValue::Float(float) => write!(self.out, "{:?}", float)?, + Sv::Float(float) => write!(self.out, "{:?}", float)?, // Booleans are either `true` or `false` so nothing special needs to be done - ScalarValue::Bool(boolean) => write!(self.out, "{}", boolean)?, + Sv::Bool(boolean) => write!(self.out, "{}", boolean)?, }, // Composite constant are created using the same syntax as compose // `type(components)` where `components` is a comma separated list of constants - ConstantInner::Composite { ty, ref components } => { + crate::ConstantInner::Composite { ty, ref components } => { self.write_type(ty)?; write!(self.out, "(")?; @@ -1053,8 +1064,8 @@ impl<'a, W: Write> Writer<'a, W> { fn write_struct( &mut self, block: bool, - handle: Handle, - members: &[StructMember], + handle: Handle, + members: &[crate::StructMember], ) -> BackendResult { // glsl structs are written as in C // `struct name() { members };` @@ -1080,7 +1091,7 @@ impl<'a, W: Write> Writer<'a, W> { for (idx, member) in members.iter().enumerate() { // The indentation is only for readability - write!(self.out, "{}", INDENT)?; + write!(self.out, "{}", back::INDENT)?; match self.module.types[member.ty].inner { TypeInner::Array { @@ -1142,10 +1153,13 @@ impl<'a, W: Write> Writer<'a, W> { /// Always adds a newline fn write_stmt( &mut self, - sta: &Statement, - ctx: &FunctionCtx<'_>, + sta: &crate::Statement, + ctx: &back::FunctionCtx<'_>, indent: usize, ) -> BackendResult { + use crate::Statement; + use back::INDENT; + match *sta { // This is where we can generate intermediate constants for some expression types. Statement::Emit(ref range) => { @@ -1313,7 +1327,7 @@ impl<'a, W: Write> Writer<'a, W> { Statement::Return { value } => { write!(self.out, "{}", INDENT.repeat(indent))?; match ctx.ty { - FunctionType::Function(_) => { + back::FunctionType::Function(_) => { write!(self.out, "return")?; // Write the expression to be returned if needed if let Some(expr) = value { @@ -1322,14 +1336,16 @@ impl<'a, W: Write> Writer<'a, W> { } writeln!(self.out, ";")?; } - FunctionType::EntryPoint(ep_index) => { + back::FunctionType::EntryPoint(ep_index) => { let ep = &self.module.entry_points[ep_index as usize]; if let Some(ref result) = ep.function.result { let value = value.unwrap(); match self.module.types[result.ty].inner { crate::TypeInner::Struct { ref members, .. } => { let (mut is_temp_struct_used, mut return_struct) = (false, ""); - if let Expression::Compose { .. } = ctx.expressions[value] { + if let crate::Expression::Compose { .. } = + ctx.expressions[value] + { is_temp_struct_used = true; return_struct = "_tmp_return"; write!( @@ -1344,7 +1360,9 @@ impl<'a, W: Write> Writer<'a, W> { } for (index, member) in members.iter().enumerate() { // TODO: handle builtin in better way - if let Some(Binding::BuiltIn(builtin)) = member.binding { + if let Some(crate::Binding::BuiltIn(builtin)) = + member.binding + { match builtin { crate::BuiltIn::ClipDistance | crate::BuiltIn::CullDistance @@ -1461,7 +1479,13 @@ impl<'a, W: Write> Writer<'a, W> { /// /// # Notes /// Doesn't add any newlines or leading/trailing spaces - fn write_expr(&mut self, expr: Handle, ctx: &FunctionCtx<'_>) -> BackendResult { + fn write_expr( + &mut self, + expr: Handle, + ctx: &back::FunctionCtx<'_>, + ) -> BackendResult { + use crate::Expression; + if let Some(name) = self.named_expressions.get(&expr) { write!(self.out, "{}", name)?; return Ok(()); @@ -1494,7 +1518,7 @@ impl<'a, W: Write> Writer<'a, W> { match *resolved { TypeInner::Vector { .. } => { // Write vector access as a swizzle - write!(self.out, ".{}", COMPONENTS[index as usize])? + write!(self.out, ".{}", back::COMPONENTS[index as usize])? } TypeInner::Matrix { .. } | TypeInner::Array { .. } @@ -1534,7 +1558,7 @@ impl<'a, W: Write> Writer<'a, W> { self.write_expr(vector, ctx)?; write!(self.out, ".")?; for &sc in pattern[..size as usize].iter() { - self.out.write_char(COMPONENTS[sc as usize])?; + self.out.write_char(back::COMPONENTS[sc as usize])?; } } // `Compose` is pretty simple we just write `type(components)` where `components` is a @@ -1695,10 +1719,10 @@ impl<'a, W: Write> Writer<'a, W> { }; let fun_name = match class { - ImageClass::Sampled { .. } => "texelFetch", - ImageClass::Storage(_) => "imageLoad", + crate::ImageClass::Sampled { .. } => "texelFetch", + crate::ImageClass::Storage(_) => "imageLoad", // TODO: Is there even a function for this? - ImageClass::Depth => todo!(), + crate::ImageClass::Depth => todo!(), }; write!(self.out, "{}(", fun_name)?; @@ -1717,6 +1741,8 @@ impl<'a, W: Write> Writer<'a, W> { // - textureQueryLevels // - textureSamples/imageSamples Expression::ImageQuery { image, query } => { + use crate::ImageClass; + // This will only panic if the module is invalid let (dim, class) = match *ctx.info[image].ty.inner_with(&self.module.types) { TypeInner::Image { @@ -1764,7 +1790,7 @@ impl<'a, W: Write> Writer<'a, W> { }; write!(self.out, "{}(", fun_name)?; self.write_expr(image, ctx)?; - write!(self.out, ",0).{}", COMPONENTS[components])?; + write!(self.out, ",0).{}", back::COMPONENTS[components])?; } crate::ImageQuery::NumSamples => { // assumes ARB_shader_texture_image_samples @@ -1786,31 +1812,23 @@ impl<'a, W: Write> Writer<'a, W> { // // We also wrap the everything in parentheses to avoid precedence issues Expression::Unary { op, expr } => { + use crate::{ScalarKind as Sk, UnaryOperator as Uo}; + write!( self.out, "({} ", match op { - UnaryOperator::Negate => "-", - UnaryOperator::Not => - match *ctx.info[expr].ty.inner_with(&self.module.types) { - TypeInner::Scalar { - kind: ScalarKind::Sint, - .. - } => "~", - TypeInner::Scalar { - kind: ScalarKind::Uint, - .. - } => "~", - TypeInner::Scalar { - kind: ScalarKind::Bool, - .. - } => "!", - ref other => - return Err(Error::Custom(format!( - "Cannot apply not to type {:?}", - other - ))), - }, + Uo::Negate => "-", + Uo::Not => match *ctx.info[expr].ty.inner_with(&self.module.types) { + TypeInner::Scalar { kind: Sk::Sint, .. } => "~", + TypeInner::Scalar { kind: Sk::Uint, .. } => "~", + TypeInner::Scalar { kind: Sk::Bool, .. } => "!", + ref other => + return Err(Error::Custom(format!( + "Cannot apply not to type {:?}", + other + ))), + }, } )?; @@ -1825,17 +1843,19 @@ impl<'a, W: Write> Writer<'a, W> { Expression::Binary { op, left, right } => { // Holds `Some(function_name)` if the binary operation is // implemented as a function call + use crate::BinaryOperator as Bo; + let function = if let (&TypeInner::Vector { .. }, &TypeInner::Vector { .. }) = ( ctx.info[left].ty.inner_with(&self.module.types), ctx.info[right].ty.inner_with(&self.module.types), ) { match op { - BinaryOperator::Less => Some("lessThan"), - BinaryOperator::LessEqual => Some("lessThanEqual"), - BinaryOperator::Greater => Some("greaterThan"), - BinaryOperator::GreaterEqual => Some("greaterThanEqual"), - BinaryOperator::Equal => Some("equal"), - BinaryOperator::NotEqual => Some("notEqual"), + Bo::Less => Some("lessThan"), + Bo::LessEqual => Some("lessThanEqual"), + Bo::Greater => Some("greaterThan"), + Bo::GreaterEqual => Some("greaterThanEqual"), + Bo::Equal => Some("equal"), + Bo::NotEqual => Some("notEqual"), _ => None, } } else { @@ -1872,13 +1892,15 @@ impl<'a, W: Write> Writer<'a, W> { } // `Derivative` is a function call to a glsl provided function Expression::Derivative { axis, expr } => { + use crate::DerivativeAxis as Da; + write!( self.out, "{}(", match axis { - DerivativeAxis::X => "dFdx", - DerivativeAxis::Y => "dFdy", - DerivativeAxis::Width => "fwidth", + Da::X => "dFdx", + Da::Y => "dFdy", + Da::Width => "fwidth", } )?; self.write_expr(expr, ctx)?; @@ -1886,15 +1908,17 @@ impl<'a, W: Write> Writer<'a, W> { } // `Relational` is a normal function call to some glsl provided functions Expression::Relational { fun, argument } => { + use crate::RelationalFunction as Rf; + let fun_name = match fun { // There's no specific function for this but we can invert the result of `isinf` - RelationalFunction::IsFinite => "!isinf", - RelationalFunction::IsInf => "isinf", - RelationalFunction::IsNan => "isnan", + Rf::IsFinite => "!isinf", + Rf::IsInf => "isinf", + Rf::IsNan => "isnan", // There's also no function for this but we can invert `isnan` - RelationalFunction::IsNormal => "!isnan", - RelationalFunction::All => "all", - RelationalFunction::Any => "any", + Rf::IsNormal => "!isnan", + Rf::All => "all", + Rf::Any => "any", }; write!(self.out, "{}(", fun_name)?; @@ -2003,18 +2027,20 @@ impl<'a, W: Write> Writer<'a, W> { } } None => { + use crate::ScalarKind as Sk; + let source_kind = inner.scalar_kind().unwrap(); write!( self.out, "{}", match (source_kind, target_kind) { - (ScalarKind::Float, ScalarKind::Sint) => "floatBitsToInt", - (ScalarKind::Float, ScalarKind::Uint) => "floatBitsToUInt", - (ScalarKind::Sint, ScalarKind::Float) => "intBitsToFloat", - (ScalarKind::Uint, ScalarKind::Float) => "uintBitsToFloat", + (Sk::Float, Sk::Sint) => "floatBitsToInt", + (Sk::Float, Sk::Uint) => "floatBitsToUInt", + (Sk::Sint, Sk::Float) => "intBitsToFloat", + (Sk::Uint, Sk::Float) => "uintBitsToFloat", // There is no way to bitcast between Uint/Sint in glsl. Use constructor conversion - (ScalarKind::Uint, ScalarKind::Sint) => "int", - (ScalarKind::Sint, ScalarKind::Uint) => "uint", + (Sk::Uint, Sk::Sint) => "int", + (Sk::Sint, Sk::Uint) => "uint", _ => { return Err(Error::Custom(format!( "Cannot bitcast {:?} to {:?}", @@ -2044,18 +2070,20 @@ impl<'a, W: Write> Writer<'a, W> { fn write_texture_coordinates( &mut self, - coordinate: Handle, - array_index: Option>, + coordinate: Handle, + array_index: Option>, dim: crate::ImageDimension, - ctx: &FunctionCtx, + ctx: &back::FunctionCtx, ) -> Result<(), Error> { + use crate::ImageDimension as IDim; + match array_index { Some(layer_expr) => { let tex_coord_type = match dim { - crate::ImageDimension::D1 => "ivec2", - crate::ImageDimension::D2 => "ivec3", - crate::ImageDimension::D3 => "ivec4", - crate::ImageDimension::Cube => "ivec4", + IDim::D1 => "ivec2", + IDim::D2 => "ivec3", + IDim::D3 => "ivec4", + IDim::Cube => "ivec4", }; write!(self.out, "{}(", tex_coord_type)?; self.write_expr(coordinate, ctx)?; @@ -2072,12 +2100,12 @@ impl<'a, W: Write> Writer<'a, W> { fn write_named_expr( &mut self, - handle: Handle, + handle: Handle, name: String, - ctx: &FunctionCtx, + ctx: &back::FunctionCtx, ) -> BackendResult { match ctx.info[handle].ty { - TypeResolution::Handle(ty_handle) => match self.module.types[ty_handle].inner { + proc::TypeResolution::Handle(ty_handle) => match self.module.types[ty_handle].inner { TypeInner::Struct { .. } => { let ty_name = &self.names[&NameKey::Type(ty_handle)]; write!(self.out, "{}", ty_name)?; @@ -2086,7 +2114,7 @@ impl<'a, W: Write> Writer<'a, W> { self.write_type(ty_handle)?; } }, - TypeResolution::Value(ref inner) => { + proc::TypeResolution::Value(ref inner) => { self.write_value_type(inner)?; } } @@ -2117,8 +2145,8 @@ impl<'a, W: Write> Writer<'a, W> { fn collect_reflection_info(&self) -> Result { use std::collections::hash_map::Entry; let info = self.info.get_entry_point(self.entry_point_idx as usize); - let mut mappings = FastHashMap::default(); - let mut uniforms = FastHashMap::default(); + let mut mappings = crate::FastHashMap::default(); + let mut uniforms = crate::FastHashMap::default(); for sampling in info.sampling_set.iter() { let global = self.module.global_variables[sampling.image].clone(); @@ -2146,7 +2174,7 @@ impl<'a, W: Write> Writer<'a, W> { } match self.module.types[var.ty].inner { crate::TypeInner::Struct { .. } => match var.class { - StorageClass::Uniform | StorageClass::Storage => { + crate::StorageClass::Uniform | crate::StorageClass::Storage => { let name = self.reflection_names[&var.ty].clone(); uniforms.insert(handle, name); } @@ -2179,17 +2207,22 @@ struct ScalarString<'a> { /// /// # Errors /// If a [`Float`](crate::ScalarKind::Float) with an width that isn't 4 or 8 -fn glsl_scalar(kind: ScalarKind, width: Bytes) -> Result, Error> { +fn glsl_scalar( + kind: crate::ScalarKind, + width: crate::Bytes, +) -> Result, Error> { + use crate::ScalarKind as Sk; + Ok(match kind { - ScalarKind::Sint => ScalarString { + Sk::Sint => ScalarString { prefix: "i", full: "int", }, - ScalarKind::Uint => ScalarString { + Sk::Uint => ScalarString { prefix: "u", full: "uint", }, - ScalarKind::Float => match width { + Sk::Float => match width { 4 => ScalarString { prefix: "", full: "float", @@ -2200,7 +2233,7 @@ fn glsl_scalar(kind: ScalarKind, width: Bytes) -> Result, }, _ => return Err(Error::UnsupportedScalar(kind, width)), }, - ScalarKind::Bool => ScalarString { + Sk::Bool => ScalarString { prefix: "b", full: "bool", }, @@ -2208,9 +2241,11 @@ fn glsl_scalar(kind: ScalarKind, width: Bytes) -> Result, } /// Helper function that returns the glsl variable name for a builtin -fn glsl_built_in(built_in: BuiltIn, output: bool) -> &'static str { +fn glsl_built_in(built_in: crate::BuiltIn, output: bool) -> &'static str { + use crate::BuiltIn as Bi; + match built_in { - BuiltIn::Position => { + Bi::Position => { if output { "gl_Position" } else { @@ -2218,18 +2253,18 @@ fn glsl_built_in(built_in: BuiltIn, output: bool) -> &'static str { } } // vertex - BuiltIn::BaseInstance => "uint(gl_BaseInstance)", - BuiltIn::BaseVertex => "uint(gl_BaseVertex)", - BuiltIn::ClipDistance => "gl_ClipDistance", - BuiltIn::CullDistance => "gl_CullDistance", - BuiltIn::InstanceIndex => "uint(gl_InstanceID)", - BuiltIn::PointSize => "gl_PointSize", - BuiltIn::VertexIndex => "uint(gl_VertexID)", + Bi::BaseInstance => "uint(gl_BaseInstance)", + Bi::BaseVertex => "uint(gl_BaseVertex)", + Bi::ClipDistance => "gl_ClipDistance", + Bi::CullDistance => "gl_CullDistance", + Bi::InstanceIndex => "uint(gl_InstanceID)", + Bi::PointSize => "gl_PointSize", + Bi::VertexIndex => "uint(gl_VertexID)", // fragment - BuiltIn::FragDepth => "gl_FragDepth", - BuiltIn::FrontFacing => "gl_FrontFacing", - BuiltIn::SampleIndex => "gl_SampleID", - BuiltIn::SampleMask => { + Bi::FragDepth => "gl_FragDepth", + Bi::FrontFacing => "gl_FrontFacing", + Bi::SampleIndex => "gl_SampleID", + Bi::SampleMask => { if output { "gl_SampleMask" } else { @@ -2237,90 +2272,100 @@ fn glsl_built_in(built_in: BuiltIn, output: bool) -> &'static str { } } // compute - BuiltIn::GlobalInvocationId => "gl_GlobalInvocationID", - BuiltIn::LocalInvocationId => "gl_LocalInvocationID", - BuiltIn::LocalInvocationIndex => "gl_LocalInvocationIndex", - BuiltIn::WorkGroupId => "gl_WorkGroupID", - BuiltIn::WorkGroupSize => "gl_WorkGroupSize", + Bi::GlobalInvocationId => "gl_GlobalInvocationID", + Bi::LocalInvocationId => "gl_LocalInvocationID", + Bi::LocalInvocationIndex => "gl_LocalInvocationIndex", + Bi::WorkGroupId => "gl_WorkGroupID", + Bi::WorkGroupSize => "gl_WorkGroupSize", } } /// Helper function that returns the string corresponding to the storage class -fn glsl_storage_class(class: StorageClass) -> Option<&'static str> { +fn glsl_storage_class(class: crate::StorageClass) -> Option<&'static str> { + use crate::StorageClass as Sc; + match class { - StorageClass::Function => None, - StorageClass::Private => None, - StorageClass::Storage => Some("buffer"), - StorageClass::Uniform => Some("uniform"), - StorageClass::Handle => Some("uniform"), - StorageClass::WorkGroup => Some("shared"), - StorageClass::PushConstant => None, + Sc::Function => None, + Sc::Private => None, + Sc::Storage => Some("buffer"), + Sc::Uniform => Some("uniform"), + Sc::Handle => Some("uniform"), + Sc::WorkGroup => Some("shared"), + Sc::PushConstant => None, } } /// Helper function that returns the string corresponding to the glsl interpolation qualifier -fn glsl_interpolation(interpolation: Interpolation) -> &'static str { +fn glsl_interpolation(interpolation: crate::Interpolation) -> &'static str { + use crate::Interpolation as I; + match interpolation { - Interpolation::Perspective => "smooth", - Interpolation::Linear => "noperspective", - Interpolation::Flat => "flat", + I::Perspective => "smooth", + I::Linear => "noperspective", + I::Flat => "flat", } } /// Return the GLSL auxiliary qualifier for the given sampling value. -fn glsl_sampling(sampling: Sampling) -> Option<&'static str> { +fn glsl_sampling(sampling: crate::Sampling) -> Option<&'static str> { + use crate::Sampling as S; + match sampling { - Sampling::Center => None, - Sampling::Centroid => Some("centroid"), - Sampling::Sample => Some("sample"), + S::Center => None, + S::Centroid => Some("centroid"), + S::Sample => Some("sample"), } } /// Helper function that returns the glsl dimension string of [`ImageDimension`](crate::ImageDimension) fn glsl_dimension(dim: crate::ImageDimension) -> &'static str { + use crate::ImageDimension as IDim; + match dim { - crate::ImageDimension::D1 => "1D", - crate::ImageDimension::D2 => "2D", - crate::ImageDimension::D3 => "3D", - crate::ImageDimension::Cube => "Cube", + IDim::D1 => "1D", + IDim::D2 => "2D", + IDim::D3 => "3D", + IDim::Cube => "Cube", } } /// Helper function that returns the glsl storage format string of [`StorageFormat`](crate::StorageFormat) -fn glsl_storage_format(format: StorageFormat) -> &'static str { +fn glsl_storage_format(format: crate::StorageFormat) -> &'static str { + use crate::StorageFormat as Sf; + match format { - StorageFormat::R8Unorm => "r8", - StorageFormat::R8Snorm => "r8_snorm", - StorageFormat::R8Uint => "r8ui", - StorageFormat::R8Sint => "r8i", - StorageFormat::R16Uint => "r16ui", - StorageFormat::R16Sint => "r16i", - StorageFormat::R16Float => "r16f", - StorageFormat::Rg8Unorm => "rg8", - StorageFormat::Rg8Snorm => "rg8_snorm", - StorageFormat::Rg8Uint => "rg8ui", - StorageFormat::Rg8Sint => "rg8i", - StorageFormat::R32Uint => "r32ui", - StorageFormat::R32Sint => "r32i", - StorageFormat::R32Float => "r32f", - StorageFormat::Rg16Uint => "rg16ui", - StorageFormat::Rg16Sint => "rg16i", - StorageFormat::Rg16Float => "rg16f", - StorageFormat::Rgba8Unorm => "rgba8ui", - StorageFormat::Rgba8Snorm => "rgba8_snorm", - StorageFormat::Rgba8Uint => "rgba8ui", - StorageFormat::Rgba8Sint => "rgba8i", - StorageFormat::Rgb10a2Unorm => "rgb10_a2ui", - StorageFormat::Rg11b10Float => "r11f_g11f_b10f", - StorageFormat::Rg32Uint => "rg32ui", - StorageFormat::Rg32Sint => "rg32i", - StorageFormat::Rg32Float => "rg32f", - StorageFormat::Rgba16Uint => "rgba16ui", - StorageFormat::Rgba16Sint => "rgba16i", - StorageFormat::Rgba16Float => "rgba16f", - StorageFormat::Rgba32Uint => "rgba32ui", - StorageFormat::Rgba32Sint => "rgba32i", - StorageFormat::Rgba32Float => "rgba32f", + Sf::R8Unorm => "r8", + Sf::R8Snorm => "r8_snorm", + Sf::R8Uint => "r8ui", + Sf::R8Sint => "r8i", + Sf::R16Uint => "r16ui", + Sf::R16Sint => "r16i", + Sf::R16Float => "r16f", + Sf::Rg8Unorm => "rg8", + Sf::Rg8Snorm => "rg8_snorm", + Sf::Rg8Uint => "rg8ui", + Sf::Rg8Sint => "rg8i", + Sf::R32Uint => "r32ui", + Sf::R32Sint => "r32i", + Sf::R32Float => "r32f", + Sf::Rg16Uint => "rg16ui", + Sf::Rg16Sint => "rg16i", + Sf::Rg16Float => "rg16f", + Sf::Rgba8Unorm => "rgba8ui", + Sf::Rgba8Snorm => "rgba8_snorm", + Sf::Rgba8Uint => "rgba8ui", + Sf::Rgba8Sint => "rgba8i", + Sf::Rgb10a2Unorm => "rgb10_a2ui", + Sf::Rg11b10Float => "r11f_g11f_b10f", + Sf::Rg32Uint => "rg32ui", + Sf::Rg32Sint => "rg32i", + Sf::Rg32Float => "rg32f", + Sf::Rgba16Uint => "rgba16ui", + Sf::Rgba16Sint => "rgba16i", + Sf::Rgba16Float => "rgba16f", + Sf::Rgba32Uint => "rgba32ui", + Sf::Rgba32Sint => "rgba32i", + Sf::Rgba32Float => "rgba32f", } } @@ -2329,10 +2374,10 @@ fn glsl_storage_format(format: StorageFormat) -> &'static str { /// glsl allows adding both `readonly` and `writeonly` but this means that /// they can only be used to query information about the resource which isn't what /// we want here so when storage access is both `LOAD` and `STORE` add no modifiers -fn glsl_storage_access(storage_access: StorageAccess) -> Option<&'static str> { - if storage_access == StorageAccess::LOAD { +fn glsl_storage_access(storage_access: crate::StorageAccess) -> Option<&'static str> { + if storage_access == crate::StorageAccess::LOAD { Some("readonly") - } else if storage_access == StorageAccess::STORE { + } else if storage_access == crate::StorageAccess::STORE { Some("writeonly") } else { None @@ -2343,7 +2388,7 @@ fn glsl_storage_access(storage_access: StorageAccess) -> Option<&'static str> { fn zero_init_value_str(inner: &TypeInner) -> Option { match *inner { TypeInner::Scalar { kind, .. } => match kind { - ScalarKind::Bool => Some(String::from("false")), + crate::ScalarKind::Bool => Some(String::from("false")), _ => Some(String::from("0")), }, TypeInner::Vector { size, kind, width } => {