From 267bd488d385ce2d35158195562624eda7ec85d1 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Sun, 5 Nov 2023 15:18:55 -0800 Subject: [PATCH] [naga wgsl-in] Introduce `Scalar` type. Introduce a new struct `Scalar`, holding a scalar kind and width, and use it as appropriate in the WGSL front end. This consolidates many (kind, width) pairs, and lets us name the two components. Ideally, `Scalar` would be used throughout Naga, but this would be a large change, touching hundreds of use sites. This patch begins by introducing `Scalar` to the WGSL front end only. --- naga/src/front/wgsl/error.rs | 14 +- naga/src/front/wgsl/lower/construction.rs | 8 +- naga/src/front/wgsl/lower/mod.rs | 8 +- naga/src/front/wgsl/mod.rs | 57 ++++- naga/src/front/wgsl/parse/ast.rs | 22 +- naga/src/front/wgsl/parse/conv.rs | 31 ++- naga/src/front/wgsl/parse/lexer.rs | 9 +- naga/src/front/wgsl/parse/mod.rs | 252 +++++++++++++--------- 8 files changed, 251 insertions(+), 150 deletions(-) diff --git a/naga/src/front/wgsl/error.rs b/naga/src/front/wgsl/error.rs index 9143a8c07e..e4d3e6d325 100644 --- a/naga/src/front/wgsl/error.rs +++ b/naga/src/front/wgsl/error.rs @@ -1,4 +1,5 @@ use crate::front::wgsl::parse::lexer::Token; +use crate::front::wgsl::Scalar; use crate::proc::{Alignment, ConstantEvaluatorError, ResolveError}; use crate::{SourceLocation, Span}; use codespan_reporting::diagnostic::{Diagnostic, Label}; @@ -139,7 +140,7 @@ pub enum Error<'a> { UnexpectedComponents(Span), UnexpectedOperationInConstContext(Span), BadNumber(Span, NumberError), - BadMatrixScalarKind(Span, crate::ScalarKind, u8), + BadMatrixScalarKind(Span, Scalar), BadAccessor(Span), BadTexture(Span), BadTypeCast { @@ -149,8 +150,7 @@ pub enum Error<'a> { }, BadTextureSampleType { span: Span, - kind: crate::ScalarKind, - width: u8, + scalar: Scalar, }, BadIncrDecrReferenceType(Span), InvalidResolve(ResolveError), @@ -304,10 +304,10 @@ impl<'a> Error<'a> { labels: vec![(bad_span, err.to_string().into())], notes: vec![], }, - Error::BadMatrixScalarKind(span, kind, width) => ParseError { + Error::BadMatrixScalarKind(span, scalar) => ParseError { message: format!( "matrix scalar type must be floating-point, but found `{}`", - kind.to_wgsl(width) + scalar.to_wgsl() ), labels: vec![(span, "must be floating-point (e.g. `f32`)".into())], notes: vec![], @@ -327,10 +327,10 @@ impl<'a> Error<'a> { labels: vec![(bad_span, "unknown scalar type".into())], notes: vec!["Valid scalar types are f32, f64, i32, u32, bool".into()], }, - Error::BadTextureSampleType { span, kind, width } => ParseError { + Error::BadTextureSampleType { span, scalar } => ParseError { message: format!( "texture sample type must be one of f32, i32 or u32, but found {}", - kind.to_wgsl(width) + scalar.to_wgsl() ), labels: vec![(span, "must be one of f32, i32 or u32".into())], notes: vec![], diff --git a/naga/src/front/wgsl/lower/construction.rs b/naga/src/front/wgsl/lower/construction.rs index 912713f911..1393022f8b 100644 --- a/naga/src/front/wgsl/lower/construction.rs +++ b/naga/src/front/wgsl/lower/construction.rs @@ -516,13 +516,13 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { ctx: &mut ExpressionContext<'source, '_, 'out>, ) -> Result>, Error<'source>> { let handle = match *constructor { - ast::ConstructorType::Scalar { width, kind } => { - let ty = ctx.ensure_type_exists(crate::TypeInner::Scalar { width, kind }); + ast::ConstructorType::Scalar(scalar) => { + let ty = ctx.ensure_type_exists(scalar.to_inner_scalar()); Constructor::Type(ty) } ast::ConstructorType::PartialVector { size } => Constructor::PartialVector { size }, - ast::ConstructorType::Vector { size, kind, width } => { - let ty = ctx.ensure_type_exists(crate::TypeInner::Vector { size, kind, width }); + ast::ConstructorType::Vector { size, scalar } => { + let ty = ctx.ensure_type_exists(scalar.to_inner_vector(size)); Constructor::Type(ty) } ast::ConstructorType::PartialMatrix { columns, rows } => { diff --git a/naga/src/front/wgsl/lower/mod.rs b/naga/src/front/wgsl/lower/mod.rs index c48413aba6..567360b5d8 100644 --- a/naga/src/front/wgsl/lower/mod.rs +++ b/naga/src/front/wgsl/lower/mod.rs @@ -2549,10 +2549,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { ctx: &mut GlobalContext<'source, '_, '_>, ) -> Result, Error<'source>> { let inner = match ctx.types[handle] { - ast::Type::Scalar { kind, width } => crate::TypeInner::Scalar { kind, width }, - ast::Type::Vector { size, kind, width } => { - crate::TypeInner::Vector { size, kind, width } - } + ast::Type::Scalar(scalar) => scalar.to_inner_scalar(), + ast::Type::Vector { size, scalar } => scalar.to_inner_vector(size), ast::Type::Matrix { rows, columns, @@ -2562,7 +2560,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { rows, width, }, - ast::Type::Atomic { kind, width } => crate::TypeInner::Atomic { kind, width }, + ast::Type::Atomic(scalar) => scalar.to_inner_atomic(), ast::Type::Pointer { base, space } => { let base = self.resolve_ast_type(base, ctx)?; crate::TypeInner::Pointer { base, space } diff --git a/naga/src/front/wgsl/mod.rs b/naga/src/front/wgsl/mod.rs index 56834d5d92..c1d263ee69 100644 --- a/naga/src/front/wgsl/mod.rs +++ b/naga/src/front/wgsl/mod.rs @@ -104,9 +104,10 @@ impl crate::TypeInner { use crate::TypeInner as Ti; match *self { - Ti::Scalar { kind, width } => kind.to_wgsl(width), + Ti::Scalar { kind, width } => Scalar { kind, width }.to_wgsl(), Ti::Vector { size, kind, width } => { - format!("vec{}<{}>", size as u32, kind.to_wgsl(width)) + let scalar = Scalar { kind, width }; + format!("vec{}<{}>", size as u32, scalar.to_wgsl()) } Ti::Matrix { columns, @@ -117,11 +118,15 @@ impl crate::TypeInner { "mat{}x{}<{}>", columns as u32, rows as u32, - crate::ScalarKind::Float.to_wgsl(width), + Scalar { + kind: crate::ScalarKind::Float, + width + } + .to_wgsl(), ) } Ti::Atomic { kind, width } => { - format!("atomic<{}>", kind.to_wgsl(width)) + format!("atomic<{}>", Scalar { kind, width }.to_wgsl()) } Ti::Pointer { base, .. } => { let base = &gctx.types[base]; @@ -129,7 +134,7 @@ impl crate::TypeInner { format!("ptr<{name}>") } Ti::ValuePointer { kind, width, .. } => { - format!("ptr<{}>", kind.to_wgsl(width)) + format!("ptr<{}>", Scalar { kind, width }.to_wgsl()) } Ti::Array { base, size, .. } => { let member_type = &gctx.types[base]; @@ -169,7 +174,7 @@ impl crate::TypeInner { // Note: The only valid widths are 4 bytes wide. // The lexer has already verified this, so we can safely assume it here. // https://gpuweb.github.io/gpuweb/wgsl/#sampled-texture-type - let element_type = kind.to_wgsl(4); + let element_type = Scalar { kind, width: 4 }.to_wgsl(); format!("<{element_type}>") } crate::ImageClass::Depth { multi: _ } => String::new(), @@ -287,17 +292,49 @@ mod type_inner_tests { } } -impl crate::ScalarKind { +/// 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. /// /// Examples: `f32`, `u64`, `bool`. - fn to_wgsl(self, width: u8) -> String { - let prefix = match self { + fn to_wgsl(self) -> String { + let prefix = match self.kind { crate::ScalarKind::Sint => "i", crate::ScalarKind::Uint => "u", crate::ScalarKind::Float => "f", crate::ScalarKind::Bool => return "bool".to_string(), }; - format!("{}{}", prefix, width * 8) + 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, + } } } diff --git a/naga/src/front/wgsl/parse/ast.rs b/naga/src/front/wgsl/parse/ast.rs index f88e880a3f..dbaac523cb 100644 --- a/naga/src/front/wgsl/parse/ast.rs +++ b/naga/src/front/wgsl/parse/ast.rs @@ -1,4 +1,5 @@ use crate::front::wgsl::parse::number::Number; +use crate::front::wgsl::Scalar; use crate::{Arena, FastIndexSet, Handle, Span}; use std::hash::Hash; @@ -212,24 +213,17 @@ pub enum ArraySize<'a> { #[derive(Debug)] pub enum Type<'a> { - Scalar { - kind: crate::ScalarKind, - width: crate::Bytes, - }, + Scalar(Scalar), Vector { size: crate::VectorSize, - kind: crate::ScalarKind, - width: crate::Bytes, + scalar: Scalar, }, Matrix { columns: crate::VectorSize, rows: crate::VectorSize, width: crate::Bytes, }, - Atomic { - kind: crate::ScalarKind, - width: crate::Bytes, - }, + Atomic(Scalar), Pointer { base: Handle>, space: crate::AddressSpace, @@ -344,10 +338,7 @@ pub struct SwitchCase<'a> { #[derive(Debug)] pub enum ConstructorType<'a> { /// A scalar type or conversion: `f32(1)`. - Scalar { - kind: crate::ScalarKind, - width: crate::Bytes, - }, + Scalar(Scalar), /// A vector construction whose component type is inferred from the /// argument: `vec3(1.0)`. @@ -357,8 +348,7 @@ pub enum ConstructorType<'a> { /// `vec3(1.0)`. Vector { size: crate::VectorSize, - kind: crate::ScalarKind, - width: crate::Bytes, + scalar: Scalar, }, /// A matrix construction whose component type is inferred from the diff --git a/naga/src/front/wgsl/parse/conv.rs b/naga/src/front/wgsl/parse/conv.rs index 51977173d6..08f1e39285 100644 --- a/naga/src/front/wgsl/parse/conv.rs +++ b/naga/src/front/wgsl/parse/conv.rs @@ -1,4 +1,5 @@ use super::Error; +use crate::front::wgsl::Scalar; use crate::Span; pub fn map_address_space(word: &str, span: Span) -> Result> { @@ -103,14 +104,30 @@ pub fn map_storage_format(word: &str, span: Span) -> Result Option<(crate::ScalarKind, crate::Bytes)> { +pub fn get_scalar_type(word: &str) -> Option { + use crate::ScalarKind as Sk; match word { - // "f16" => Some((crate::ScalarKind::Float, 2)), - "f32" => Some((crate::ScalarKind::Float, 4)), - "f64" => Some((crate::ScalarKind::Float, 8)), - "i32" => Some((crate::ScalarKind::Sint, 4)), - "u32" => Some((crate::ScalarKind::Uint, 4)), - "bool" => Some((crate::ScalarKind::Bool, crate::BOOL_WIDTH)), + // "f16" => Some(Scalar { kind: Sk::Float, width: 2 }), + "f32" => Some(Scalar { + kind: Sk::Float, + width: 4, + }), + "f64" => Some(Scalar { + kind: Sk::Float, + width: 8, + }), + "i32" => Some(Scalar { + kind: Sk::Sint, + width: 4, + }), + "u32" => Some(Scalar { + kind: Sk::Uint, + width: 4, + }), + "bool" => Some(Scalar { + kind: Sk::Bool, + width: crate::BOOL_WIDTH, + }), _ => None, } } diff --git a/naga/src/front/wgsl/parse/lexer.rs b/naga/src/front/wgsl/parse/lexer.rs index ed273fbbb1..dc229bb5fa 100644 --- a/naga/src/front/wgsl/parse/lexer.rs +++ b/naga/src/front/wgsl/parse/lexer.rs @@ -1,6 +1,7 @@ use super::{number::consume_number, Error, ExpectedToken}; use crate::front::wgsl::error::NumberError; use crate::front::wgsl::parse::{conv, Number}; +use crate::front::wgsl::Scalar; use crate::Span; type TokenSpan<'a> = (Token<'a>, Span); @@ -374,9 +375,7 @@ impl<'a> Lexer<'a> { } /// Parses a generic scalar type, for example ``. - pub(in crate::front::wgsl) fn next_scalar_generic( - &mut self, - ) -> Result<(crate::ScalarKind, crate::Bytes), Error<'a>> { + pub(in crate::front::wgsl) fn next_scalar_generic(&mut self) -> Result> { self.expect_generic_paren('<')?; let pair = match self.next() { (Token::Word(word), span) => { @@ -393,11 +392,11 @@ impl<'a> Lexer<'a> { /// Returns the span covering the inner type, excluding the brackets. pub(in crate::front::wgsl) fn next_scalar_generic_with_span( &mut self, - ) -> Result<(crate::ScalarKind, crate::Bytes, Span), Error<'a>> { + ) -> Result<(Scalar, Span), Error<'a>> { self.expect_generic_paren('<')?; let pair = match self.next() { (Token::Word(word), span) => conv::get_scalar_type(word) - .map(|(a, b)| (a, b, span)) + .map(|scalar| (scalar, span)) .ok_or(Error::UnknownScalarType(span)), (_, span) => Err(Error::UnknownScalarType(span)), }?; diff --git a/naga/src/front/wgsl/parse/mod.rs b/naga/src/front/wgsl/parse/mod.rs index ae690018f1..bd635b9189 100644 --- a/naga/src/front/wgsl/parse/mod.rs +++ b/naga/src/front/wgsl/parse/mod.rs @@ -1,6 +1,7 @@ use crate::front::wgsl::error::{Error, ExpectedToken}; use crate::front::wgsl::parse::lexer::{Lexer, Token}; use crate::front::wgsl::parse::number::Number; +use crate::front::wgsl::Scalar; use crate::front::SymbolTable; use crate::{Arena, FastIndexSet, Handle, ShaderStage, Span}; @@ -277,8 +278,8 @@ impl Parser { span: Span, ctx: &mut ExpressionContext<'a, '_, '_>, ) -> Result>, Error<'a>> { - if let Some((kind, width)) = conv::get_scalar_type(word) { - return Ok(Some(ast::ConstructorType::Scalar { kind, width })); + if let Some(scalar) = conv::get_scalar_type(word) { + return Ok(Some(ast::ConstructorType::Scalar(scalar))); } let partial = match word { @@ -288,22 +289,28 @@ impl Parser { "vec2i" => { return Ok(Some(ast::ConstructorType::Vector { size: crate::VectorSize::Bi, - kind: crate::ScalarKind::Sint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Sint, + width: 4, + }, })) } "vec2u" => { return Ok(Some(ast::ConstructorType::Vector { size: crate::VectorSize::Bi, - kind: crate::ScalarKind::Uint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Uint, + width: 4, + }, })) } "vec2f" => { return Ok(Some(ast::ConstructorType::Vector { size: crate::VectorSize::Bi, - kind: crate::ScalarKind::Float, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Float, + width: 4, + }, })) } "vec3" => ast::ConstructorType::PartialVector { @@ -312,22 +319,28 @@ impl Parser { "vec3i" => { return Ok(Some(ast::ConstructorType::Vector { size: crate::VectorSize::Tri, - kind: crate::ScalarKind::Sint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Sint, + width: 4, + }, })) } "vec3u" => { return Ok(Some(ast::ConstructorType::Vector { size: crate::VectorSize::Tri, - kind: crate::ScalarKind::Uint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Uint, + width: 4, + }, })) } "vec3f" => { return Ok(Some(ast::ConstructorType::Vector { size: crate::VectorSize::Tri, - kind: crate::ScalarKind::Float, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Float, + width: 4, + }, })) } "vec4" => ast::ConstructorType::PartialVector { @@ -336,22 +349,28 @@ impl Parser { "vec4i" => { return Ok(Some(ast::ConstructorType::Vector { size: crate::VectorSize::Quad, - kind: crate::ScalarKind::Sint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Sint, + width: 4, + }, })) } "vec4u" => { return Ok(Some(ast::ConstructorType::Vector { size: crate::VectorSize::Quad, - kind: crate::ScalarKind::Uint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Uint, + width: 4, + }, })) } "vec4f" => { return Ok(Some(ast::ConstructorType::Vector { size: crate::VectorSize::Quad, - kind: crate::ScalarKind::Float, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Float, + width: 4, + }, })) } "mat2x2" => ast::ConstructorType::PartialMatrix { @@ -483,18 +502,18 @@ impl Parser { // parse component type if present match (lexer.peek().0, partial) { (Token::Paren('<'), ast::ConstructorType::PartialVector { size }) => { - let (kind, width) = lexer.next_scalar_generic()?; - Ok(Some(ast::ConstructorType::Vector { size, kind, width })) + let scalar = lexer.next_scalar_generic()?; + Ok(Some(ast::ConstructorType::Vector { size, scalar })) } (Token::Paren('<'), ast::ConstructorType::PartialMatrix { columns, rows }) => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - match kind { + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + match scalar.kind { crate::ScalarKind::Float => Ok(Some(ast::ConstructorType::Matrix { columns, rows, - width, + width: scalar.width, })), - _ => Err(Error::BadMatrixScalarKind(span, kind, width)), + _ => Err(Error::BadMatrixScalarKind(span, scalar)), } } (Token::Paren('<'), ast::ConstructorType::PartialArray) => { @@ -1045,14 +1064,14 @@ impl Parser { columns: crate::VectorSize, rows: crate::VectorSize, ) -> Result, Error<'a>> { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - match kind { + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + match scalar.kind { crate::ScalarKind::Float => Ok(ast::Type::Matrix { columns, rows, - width, + width: scalar.width, }), - _ => Err(Error::BadMatrixScalarKind(span, kind, width)), + _ => Err(Error::BadMatrixScalarKind(span, scalar)), } } @@ -1062,79 +1081,94 @@ impl Parser { word: &'a str, ctx: &mut ExpressionContext<'a, '_, '_>, ) -> Result>, Error<'a>> { - if let Some((kind, width)) = conv::get_scalar_type(word) { - return Ok(Some(ast::Type::Scalar { kind, width })); + if let Some(scalar) = conv::get_scalar_type(word) { + return Ok(Some(ast::Type::Scalar(scalar))); } Ok(Some(match word { "vec2" => { - let (kind, width) = lexer.next_scalar_generic()?; + let scalar = lexer.next_scalar_generic()?; ast::Type::Vector { size: crate::VectorSize::Bi, - kind, - width, + scalar, } } "vec2i" => ast::Type::Vector { size: crate::VectorSize::Bi, - kind: crate::ScalarKind::Sint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Sint, + width: 4, + }, }, "vec2u" => ast::Type::Vector { size: crate::VectorSize::Bi, - kind: crate::ScalarKind::Uint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Uint, + width: 4, + }, }, "vec2f" => ast::Type::Vector { size: crate::VectorSize::Bi, - kind: crate::ScalarKind::Float, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Float, + width: 4, + }, }, "vec3" => { - let (kind, width) = lexer.next_scalar_generic()?; + let scalar = lexer.next_scalar_generic()?; ast::Type::Vector { size: crate::VectorSize::Tri, - kind, - width, + scalar, } } "vec3i" => ast::Type::Vector { size: crate::VectorSize::Tri, - kind: crate::ScalarKind::Sint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Sint, + width: 4, + }, }, "vec3u" => ast::Type::Vector { size: crate::VectorSize::Tri, - kind: crate::ScalarKind::Uint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Uint, + width: 4, + }, }, "vec3f" => ast::Type::Vector { size: crate::VectorSize::Tri, - kind: crate::ScalarKind::Float, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Float, + width: 4, + }, }, "vec4" => { - let (kind, width) = lexer.next_scalar_generic()?; + let scalar = lexer.next_scalar_generic()?; ast::Type::Vector { size: crate::VectorSize::Quad, - kind, - width, + scalar, } } "vec4i" => ast::Type::Vector { size: crate::VectorSize::Quad, - kind: crate::ScalarKind::Sint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Sint, + width: 4, + }, }, "vec4u" => ast::Type::Vector { size: crate::VectorSize::Quad, - kind: crate::ScalarKind::Uint, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Uint, + width: 4, + }, }, "vec4f" => ast::Type::Vector { size: crate::VectorSize::Quad, - kind: crate::ScalarKind::Float, - width: 4, + scalar: Scalar { + kind: crate::ScalarKind::Float, + width: 4, + }, }, "mat2x2" => { self.matrix_scalar_type(lexer, crate::VectorSize::Bi, crate::VectorSize::Bi)? @@ -1209,8 +1243,8 @@ impl Parser { width: 4, }, "atomic" => { - let (kind, width) = lexer.next_scalar_generic()?; - ast::Type::Atomic { kind, width } + let scalar = lexer.next_scalar_generic()?; + ast::Type::Atomic(scalar) } "ptr" => { lexer.expect_generic_paren('<')?; @@ -1257,84 +1291,111 @@ impl Parser { "sampler" => ast::Type::Sampler { comparison: false }, "sampler_comparison" => ast::Type::Sampler { comparison: true }, "texture_1d" => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - Self::check_texture_sample_type(kind, width, span)?; + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + Self::check_texture_sample_type(scalar, span)?; ast::Type::Image { dim: crate::ImageDimension::D1, arrayed: false, - class: crate::ImageClass::Sampled { kind, multi: false }, + class: crate::ImageClass::Sampled { + kind: scalar.kind, + multi: false, + }, } } "texture_1d_array" => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - Self::check_texture_sample_type(kind, width, span)?; + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + Self::check_texture_sample_type(scalar, span)?; ast::Type::Image { dim: crate::ImageDimension::D1, arrayed: true, - class: crate::ImageClass::Sampled { kind, multi: false }, + class: crate::ImageClass::Sampled { + kind: scalar.kind, + multi: false, + }, } } "texture_2d" => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - Self::check_texture_sample_type(kind, width, span)?; + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + Self::check_texture_sample_type(scalar, span)?; ast::Type::Image { dim: crate::ImageDimension::D2, arrayed: false, - class: crate::ImageClass::Sampled { kind, multi: false }, + class: crate::ImageClass::Sampled { + kind: scalar.kind, + multi: false, + }, } } "texture_2d_array" => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - Self::check_texture_sample_type(kind, width, span)?; + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + Self::check_texture_sample_type(scalar, span)?; ast::Type::Image { dim: crate::ImageDimension::D2, arrayed: true, - class: crate::ImageClass::Sampled { kind, multi: false }, + class: crate::ImageClass::Sampled { + kind: scalar.kind, + multi: false, + }, } } "texture_3d" => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - Self::check_texture_sample_type(kind, width, span)?; + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + Self::check_texture_sample_type(scalar, span)?; ast::Type::Image { dim: crate::ImageDimension::D3, arrayed: false, - class: crate::ImageClass::Sampled { kind, multi: false }, + class: crate::ImageClass::Sampled { + kind: scalar.kind, + multi: false, + }, } } "texture_cube" => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - Self::check_texture_sample_type(kind, width, span)?; + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + Self::check_texture_sample_type(scalar, span)?; ast::Type::Image { dim: crate::ImageDimension::Cube, arrayed: false, - class: crate::ImageClass::Sampled { kind, multi: false }, + class: crate::ImageClass::Sampled { + kind: scalar.kind, + multi: false, + }, } } "texture_cube_array" => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - Self::check_texture_sample_type(kind, width, span)?; + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + Self::check_texture_sample_type(scalar, span)?; ast::Type::Image { dim: crate::ImageDimension::Cube, arrayed: true, - class: crate::ImageClass::Sampled { kind, multi: false }, + class: crate::ImageClass::Sampled { + kind: scalar.kind, + multi: false, + }, } } "texture_multisampled_2d" => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - Self::check_texture_sample_type(kind, width, span)?; + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + Self::check_texture_sample_type(scalar, span)?; ast::Type::Image { dim: crate::ImageDimension::D2, arrayed: false, - class: crate::ImageClass::Sampled { kind, multi: true }, + class: crate::ImageClass::Sampled { + kind: scalar.kind, + multi: true, + }, } } "texture_multisampled_2d_array" => { - let (kind, width, span) = lexer.next_scalar_generic_with_span()?; - Self::check_texture_sample_type(kind, width, span)?; + let (scalar, span) = lexer.next_scalar_generic_with_span()?; + Self::check_texture_sample_type(scalar, span)?; ast::Type::Image { dim: crate::ImageDimension::D2, arrayed: true, - class: crate::ImageClass::Sampled { kind, multi: true }, + class: crate::ImageClass::Sampled { + kind: scalar.kind, + multi: true, + }, } } "texture_depth_2d" => ast::Type::Image { @@ -1410,16 +1471,15 @@ impl Parser { })) } - const fn check_texture_sample_type( - kind: crate::ScalarKind, - width: u8, - span: Span, - ) -> Result<(), Error<'static>> { + const fn check_texture_sample_type(scalar: Scalar, span: Span) -> Result<(), Error<'static>> { use crate::ScalarKind::*; // Validate according to https://gpuweb.github.io/gpuweb/wgsl/#sampled-texture-type - match (kind, width) { - (Float | Sint | Uint, 4) => Ok(()), - _ => Err(Error::BadTextureSampleType { span, kind, width }), + match scalar { + Scalar { + kind: Float | Sint | Uint, + width: 4, + } => Ok(()), + _ => Err(Error::BadTextureSampleType { span, scalar }), } }