mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[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.
This commit is contained in:
committed by
Teodor Tanasoaia
parent
0dad15989f
commit
267bd488d3
@@ -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![],
|
||||
|
||||
@@ -516,13 +516,13 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
||||
ctx: &mut ExpressionContext<'source, '_, 'out>,
|
||||
) -> Result<Constructor<Handle<crate::Type>>, 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 } => {
|
||||
|
||||
@@ -2549,10 +2549,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
||||
ctx: &mut GlobalContext<'source, '_, '_>,
|
||||
) -> Result<Handle<crate::Type>, 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 }
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Type<'a>>,
|
||||
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<f32>(1.0)`.
|
||||
Vector {
|
||||
size: crate::VectorSize,
|
||||
kind: crate::ScalarKind,
|
||||
width: crate::Bytes,
|
||||
scalar: Scalar,
|
||||
},
|
||||
|
||||
/// A matrix construction whose component type is inferred from the
|
||||
|
||||
@@ -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<crate::AddressSpace, Error<'_>> {
|
||||
@@ -103,14 +104,30 @@ pub fn map_storage_format(word: &str, span: Span) -> Result<crate::StorageFormat
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_scalar_type(word: &str) -> Option<(crate::ScalarKind, crate::Bytes)> {
|
||||
pub fn get_scalar_type(word: &str) -> Option<Scalar> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 `<f32>`.
|
||||
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<Scalar, Error<'a>> {
|
||||
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)),
|
||||
}?;
|
||||
|
||||
@@ -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<Option<ast::ConstructorType<'a>>, 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<ast::Type<'a>, 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<Option<ast::Type<'a>>, 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 }),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user