diff --git a/src/back/glsl.rs b/src/back/glsl.rs index c54282cc5f..135675129a 100644 --- a/src/back/glsl.rs +++ b/src/back/glsl.rs @@ -268,7 +268,6 @@ pub fn write<'a>( { match module.types[global.ty].inner { TypeInner::Image { - kind, dim, arrayed, class, @@ -300,22 +299,10 @@ pub fn write<'a>( let name = namer(global.name.as_ref()); - let comparison = if let Some(sampler) = mapping.1 { - if let TypeInner::Sampler { comparison } = - module.types[module.global_variables[*sampler].ty].inner - { - comparison - } else { - false - } - } else { - unreachable!() - }; - writeln!( out, "uniform {} {};", - write_image_type(kind, dim, arrayed, class, comparison, features)?, + write_image_type(dim, arrayed, class, features)?, name )?; @@ -814,34 +801,28 @@ fn write_expression<'a, 'b>( let coordinate_expr = write_expression(&builder.expressions[coordinate], module, builder)?; - let (kind, dim, arrayed, class) = match *builder.typifier.get(image, &module.types) { + let (dim, arrayed, class) = match *builder.typifier.get(image, &module.types) { TypeInner::Image { - kind, dim, arrayed, class, - } => (kind, dim, arrayed, class), + } => (dim, arrayed, class), ref other => return Err(Error::Custom(format!("Cannot load {:?}", other))), }; Cow::Owned(match class { - ImageClass::Sampled | ImageClass::Multisampled => { - let ms = match class { - crate::ImageClass::Multisampled => true, - _ => false, - }; - + ImageClass::Sampled { kind, multi } => { //TODO: fix this let sampler_constructor = format!( "{}sampler{}{}{}({})", map_scalar(kind, 4, builder.features)?.prefix, ImageDimension(dim), - if ms { "MS" } else { "" }, + if multi { "MS" } else { "" }, if arrayed { "Array" } else { "" }, image_expr, ); - if !ms { + if !multi { format!("texelFetch({},{})", sampler_constructor, coordinate_expr) } else { let index_expr = @@ -1188,11 +1169,9 @@ fn write_type<'a>( } fn write_image_type( - kind: ScalarKind, dim: crate::ImageDimension, arrayed: bool, class: ImageClass, - comparison: bool, features: SupportedFeatures, ) -> Result { if arrayed @@ -1204,16 +1183,33 @@ fn write_image_type( ))); } + let (base, kind, ms, comparison) = match class { + ImageClass::Sampled { kind, multi: true } => { + if !features.contains(SupportedFeatures::MULTISAMPLED_TEXTURES) { + return Err(Error::Custom(String::from( + "Multi sampled textures aren't supported", + ))); + } + if arrayed && !features.contains(SupportedFeatures::MULTISAMPLED_TEXTURE_ARRAYS) { + return Err(Error::Custom(String::from( + "Multi sampled texture arrays aren't supported", + ))); + } + ("sampler", kind, "MS", "") + } + ImageClass::Sampled { kind, multi: false } => ("sampler", kind, "", ""), + ImageClass::Depth => ("sampler", crate::ScalarKind::Float, "", "Shadow"), + ImageClass::Storage(format) => ("image", format.into(), "", ""), + }; + Ok(format!( - "{}{}{}{}{}", + "{}{}{}{}{}{}", map_scalar(kind, 4, features)?.prefix, - match class { - ImageClass::Storage(_) => "image", - _ => "sampler", - }, + base, ImageDimension(dim), - write_image_flags(arrayed, class, features)?, - if comparison { "Shadow" } else { "" } + ms, + if arrayed { "Array" } else { "" }, + comparison )) } @@ -1271,33 +1267,6 @@ fn write_array_size(size: ArraySize) -> Result { }) } -fn write_image_flags( - arrayed: bool, - class: ImageClass, - features: SupportedFeatures, -) -> Result { - let ms = match class { - ImageClass::Multisampled => { - if !features.contains(SupportedFeatures::MULTISAMPLED_TEXTURES) { - return Err(Error::Custom(String::from( - "Multi sampled textures aren't supported", - ))); - } - if arrayed && !features.contains(SupportedFeatures::MULTISAMPLED_TEXTURE_ARRAYS) { - return Err(Error::Custom(String::from( - "Multi sampled texture arrays aren't supported", - ))); - } - "MS" - } - _ => "", - }; - - let array = if arrayed { "Array" } else { "" }; - - Ok(format!("{}{}", ms, array)) -} - struct ImageDimension(crate::ImageDimension); impl fmt::Display for ImageDimension { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/back/msl.rs b/src/back/msl.rs index 7bcf3dbdf8..2910089ea0 100644 --- a/src/back/msl.rs +++ b/src/back/msl.rs @@ -839,35 +839,30 @@ impl Writer { write!(self.out, "}}")?; } crate::TypeInner::Image { - kind, dim, arrayed, class, } => { - let base_name = scalar_kind_string(kind); let dim_str = match dim { crate::ImageDimension::D1 => "1d", crate::ImageDimension::D2 => "2d", crate::ImageDimension::D3 => "3d", crate::ImageDimension::Cube => "Cube", }; - let texture_str = match class { - crate::ImageClass::Depth => "depth", - _ => "texture", - }; - let msaa_str = match class { - crate::ImageClass::Multisampled => "_ms", - _ => "", - }; - let array_str = if arrayed { "_array" } else { "" }; - let access = match class { - crate::ImageClass::Storage(_) => { + let (texture_str, msaa_str, kind, access) = match class { + crate::ImageClass::Sampled { kind, multi } => { + ("texture", if multi { "_ms" } else { "" }, kind, "sample") + } + crate::ImageClass::Depth => { + ("depth", "", crate::ScalarKind::Float, "sample") + } + crate::ImageClass::Storage(format) => { let (_, global) = module .global_variables .iter() .find(|(_, var)| var.ty == handle) .expect("Unable to find a global variable using the image type"); - if global + let access = if global .storage_access .contains(crate::StorageAccess::LOAD | crate::StorageAccess::STORE) { @@ -878,10 +873,12 @@ impl Writer { "read" } else { return Err(Error::InvalidImageAccess(global.storage_access)); - } + }; + ("texture", "", format.into(), access) } - _ => "sample", }; + let base_name = scalar_kind_string(kind); + let array_str = if arrayed { "_array" } else { "" }; write!( self.out, "typedef {}{}{}{}<{}, access::{}> {}", diff --git a/src/back/spv/instructions.rs b/src/back/spv/instructions.rs index 35914c33cd..9a4f5bb4aa 100644 --- a/src/back/spv/instructions.rs +++ b/src/back/spv/instructions.rs @@ -179,11 +179,11 @@ pub(super) fn instruction_type_image( }); instruction.add_operand(arrayed as u32); instruction.add_operand(match image_class { - crate::ImageClass::Multisampled => 1, + crate::ImageClass::Sampled { multi: true, .. } => 1, _ => 0, }); instruction.add_operand(match image_class { - crate::ImageClass::Sampled => 1, + crate::ImageClass::Sampled { .. } => 1, _ => 0, }); @@ -800,7 +800,10 @@ mod tests { 1, spirv::Dim::Dim3D, true, - crate::ImageClass::Multisampled, + crate::ImageClass::Sampled { + kind: crate::ScalarKind::Float, + multi: true, + }, ); let mut output = vec![]; diff --git a/src/back/spv/writer.rs b/src/back/spv/writer.rs index b757aab8db..a0939d73b5 100644 --- a/src/back/spv/writer.rs +++ b/src/back/spv/writer.rs @@ -490,19 +490,28 @@ impl Writer { super::instructions::instruction_type_matrix(id, vector_id, columns) } crate::TypeInner::Image { - kind, dim, arrayed, class, } => { - let type_id = self.get_type_id( - arena, - LookupType::Local(LocalType::Vector { + let width = 4; + let local_type = match class { + crate::ImageClass::Sampled { kind, multi: _ } => LocalType::Vector { size: crate::VectorSize::Quad, kind, - width: 4, - }), - ); + width, + }, + crate::ImageClass::Depth => LocalType::Scalar { + kind: crate::ScalarKind::Float, + width, + }, + crate::ImageClass::Storage(format) => LocalType::Vector { + size: crate::VectorSize::Quad, + kind: format.into(), + width, + }, + }; + let type_id = self.get_type_id(arena, LookupType::Local(local_type)); let dim = map_dim(dim); self.try_add_capabilities(dim.required_capabilities()); super::instructions::instruction_type_image(id, type_id, dim, arrayed, class) diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index c4c75f69e8..d88f6ec1dd 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -899,10 +899,13 @@ impl> Parser { match type_arena[image_type_handle].inner { //TODO: compare the result type crate::TypeInner::Image { - kind: _, dim, arrayed, - class: crate::ImageClass::Sampled, + class: + crate::ImageClass::Sampled { + kind: _, + multi: false, + }, } => { if !check_sample_coordinates( &type_arena[coord_type_handle], @@ -982,7 +985,6 @@ impl> Parser { match type_arena[image_type_handle].inner { //TODO: compare the result type crate::TypeInner::Image { - kind: _, dim, arrayed, class: crate::ImageClass::Depth, @@ -1473,10 +1475,6 @@ impl> Parser { }; *comparison = true; } - crate::TypeInner::Image { ref mut class, .. } => { - assert_eq!(*class, crate::ImageClass::Sampled); - *class = crate::ImageClass::Multisampled; - } _ => panic!("Unexpected comparison type {:?}", ty), } } @@ -2034,17 +2032,17 @@ impl> Parser { let class = if format != 0 { crate::ImageClass::Storage(map_image_format(format)?) - } else if is_msaa { - crate::ImageClass::Multisampled } else { - crate::ImageClass::Sampled + crate::ImageClass::Sampled { + kind, + multi: is_msaa, + } }; let decor = self.future_decor.remove(&id).unwrap_or_default(); let inner = crate::TypeInner::Image { class, - kind, dim: map_image_dim(dim)?, arrayed: is_array, }; diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index 0dc6730da5..17f3fe1d29 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -1207,95 +1207,83 @@ impl Parser { Token::Word("texture_sampled_1d") => { let (kind, _) = lexer.next_scalar_generic()?; crate::TypeInner::Image { - kind, dim: crate::ImageDimension::D1, arrayed: false, - class: crate::ImageClass::Sampled, + class: crate::ImageClass::Sampled { kind, multi: false }, } } Token::Word("texture_sampled_1d_array") => { let (kind, _) = lexer.next_scalar_generic()?; crate::TypeInner::Image { - kind, dim: crate::ImageDimension::D1, arrayed: true, - class: crate::ImageClass::Sampled, + class: crate::ImageClass::Sampled { kind, multi: false }, } } Token::Word("texture_sampled_2d") => { let (kind, _) = lexer.next_scalar_generic()?; crate::TypeInner::Image { - kind, dim: crate::ImageDimension::D2, arrayed: false, - class: crate::ImageClass::Sampled, + class: crate::ImageClass::Sampled { kind, multi: false }, } } Token::Word("texture_sampled_2d_array") => { let (kind, _) = lexer.next_scalar_generic()?; crate::TypeInner::Image { - kind, dim: crate::ImageDimension::D2, arrayed: true, - class: crate::ImageClass::Sampled, + class: crate::ImageClass::Sampled { kind, multi: false }, } } Token::Word("texture_sampled_3d") => { let (kind, _) = lexer.next_scalar_generic()?; crate::TypeInner::Image { - kind, dim: crate::ImageDimension::D3, arrayed: false, - class: crate::ImageClass::Sampled, + class: crate::ImageClass::Sampled { kind, multi: false }, } } Token::Word("texture_sampled_cube") => { let (kind, _) = lexer.next_scalar_generic()?; crate::TypeInner::Image { - kind, dim: crate::ImageDimension::Cube, arrayed: false, - class: crate::ImageClass::Sampled, + class: crate::ImageClass::Sampled { kind, multi: false }, } } Token::Word("texture_sampled_cube_array") => { let (kind, _) = lexer.next_scalar_generic()?; crate::TypeInner::Image { - kind, dim: crate::ImageDimension::Cube, arrayed: true, - class: crate::ImageClass::Sampled, + class: crate::ImageClass::Sampled { kind, multi: false }, } } Token::Word("texture_multisampled_2d") => { let (kind, _) = lexer.next_scalar_generic()?; crate::TypeInner::Image { - kind, dim: crate::ImageDimension::D2, arrayed: false, - class: crate::ImageClass::Multisampled, + class: crate::ImageClass::Sampled { kind, multi: true }, } } Token::Word("texture_depth_2d") => crate::TypeInner::Image { - kind: crate::ScalarKind::Float, dim: crate::ImageDimension::D2, arrayed: false, class: crate::ImageClass::Depth, }, Token::Word("texture_depth_2d_array") => crate::TypeInner::Image { - kind: crate::ScalarKind::Float, dim: crate::ImageDimension::D2, arrayed: true, class: crate::ImageClass::Depth, }, Token::Word("texture_depth_cube") => crate::TypeInner::Image { - kind: crate::ScalarKind::Float, dim: crate::ImageDimension::Cube, arrayed: false, class: crate::ImageClass::Depth, }, Token::Word("texture_depth_cube_array") => crate::TypeInner::Image { - kind: crate::ScalarKind::Float, dim: crate::ImageDimension::Cube, arrayed: true, class: crate::ImageClass::Depth, @@ -1303,7 +1291,6 @@ impl Parser { Token::Word("texture_ro_1d") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D1, arrayed: false, class: crate::ImageClass::Storage(format), @@ -1312,7 +1299,6 @@ impl Parser { Token::Word("texture_ro_1d_array") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D1, arrayed: true, class: crate::ImageClass::Storage(format), @@ -1321,7 +1307,6 @@ impl Parser { Token::Word("texture_ro_2d") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D2, arrayed: false, class: crate::ImageClass::Storage(format), @@ -1330,7 +1315,6 @@ impl Parser { Token::Word("texture_ro_2d_array") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D2, arrayed: true, class: crate::ImageClass::Storage(format), @@ -1339,7 +1323,6 @@ impl Parser { Token::Word("texture_ro_3d") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D3, arrayed: false, class: crate::ImageClass::Storage(format), @@ -1348,7 +1331,6 @@ impl Parser { Token::Word("texture_wo_1d") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D1, arrayed: false, class: crate::ImageClass::Storage(format), @@ -1357,7 +1339,6 @@ impl Parser { Token::Word("texture_wo_1d_array") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D1, arrayed: true, class: crate::ImageClass::Storage(format), @@ -1366,7 +1347,6 @@ impl Parser { Token::Word("texture_wo_2d") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D2, arrayed: false, class: crate::ImageClass::Storage(format), @@ -1375,7 +1355,6 @@ impl Parser { Token::Word("texture_wo_2d_array") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D2, arrayed: true, class: crate::ImageClass::Storage(format), @@ -1384,7 +1363,6 @@ impl Parser { Token::Word("texture_wo_3d") => { let format = lexer.next_format_generic()?; crate::TypeInner::Image { - kind: format.into(), dim: crate::ImageDimension::D3, arrayed: false, class: crate::ImageClass::Storage(format), diff --git a/src/lib.rs b/src/lib.rs index 7086834c2f..e1e884edb8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -315,9 +315,12 @@ pub enum StorageFormat { #[cfg_attr(feature = "deserialize", derive(Deserialize))] pub enum ImageClass { /// Regular sampled image. - Sampled, - /// Multi-sampled image. - Multisampled, + Sampled { + /// Kind of values to sample. + kind: ScalarKind, + // Multi-sampled. + multi: bool, + }, /// Depth comparison image. Depth, /// Storage image. @@ -370,7 +373,6 @@ pub enum TypeInner { Struct { members: Vec }, /// Possibly multidimensional array of texels. Image { - kind: ScalarKind, dim: ImageDimension, arrayed: bool, class: ImageClass, diff --git a/src/proc/typifier.rs b/src/proc/typifier.rs index 461bfa1bbd..0a0fc86959 100644 --- a/src/proc/typifier.rs +++ b/src/proc/typifier.rs @@ -136,18 +136,22 @@ impl Typifier { crate::Expression::Load { .. } => unimplemented!(), crate::Expression::ImageSample { image, .. } | crate::Expression::ImageLoad { image, .. } => match *self.get(image, types) { - crate::TypeInner::Image { - kind, - class: crate::ImageClass::Depth, - .. - } => Resolution::Value(crate::TypeInner::Scalar { kind, width: 4 }), - crate::TypeInner::Image { kind, .. } => { - Resolution::Value(crate::TypeInner::Vector { + crate::TypeInner::Image { class, .. } => Resolution::Value(match class { + crate::ImageClass::Depth => crate::TypeInner::Scalar { + kind: crate::ScalarKind::Float, + width: 4, + }, + crate::ImageClass::Sampled { kind, multi: _ } => crate::TypeInner::Vector { kind, width: 4, size: crate::VectorSize::Quad, - }) - } + }, + crate::ImageClass::Storage(format) => crate::TypeInner::Vector { + kind: format.into(), + width: 4, + size: crate::VectorSize::Quad, + }, + }), _ => unreachable!(), }, crate::Expression::Unary { expr, .. } => self.resolutions[expr.index()].clone(),