From bcfe1f6f2817639d85e761266afcf0a7a41ebcc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Sun, 1 Aug 2021 18:34:32 +0100 Subject: [PATCH] [glsl-in] Parse some more memory qualifiers --- src/front/glsl/ast.rs | 3 ++- src/front/glsl/lex.rs | 5 ++++- src/front/glsl/parser.rs | 27 ++++++++++++++++++++++----- src/front/glsl/token.rs | 4 ++++ src/front/glsl/variables.rs | 7 +++---- 5 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index be1ebf704d..f90e6ebbc9 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -8,7 +8,7 @@ use crate::{ proc::ResolveContext, Arena, BinaryOperator, Binding, Block, Constant, Expression, FastHashMap, Function, FunctionArgument, GlobalVariable, Handle, Interpolation, LocalVariable, Module, RelationalFunction, ResourceBinding, Sampling, ScalarKind, ScalarValue, ShaderStage, Statement, - StorageClass, Type, TypeInner, UnaryOperator, VectorSize, + StorageAccess, StorageClass, Type, TypeInner, UnaryOperator, VectorSize, }; use core::convert::TryFrom; use std::ops::Index; @@ -1054,6 +1054,7 @@ pub enum TypeQualifier { Layout(StructLayout), Precision(Precision), EarlyFragmentTests, + StorageAccess(StorageAccess), } #[derive(Debug, Clone)] diff --git a/src/front/glsl/lex.rs b/src/front/glsl/lex.rs index e12cb5e3ef..07c4d45071 100644 --- a/src/front/glsl/lex.rs +++ b/src/front/glsl/lex.rs @@ -3,7 +3,7 @@ use super::{ token::{SourceMetadata, Token, TokenValue}, types::parse_type, }; -use crate::FastHashMap; +use crate::{FastHashMap, StorageAccess}; use pp_rs::{ pp::Preprocessor, token::{Punct, Token as PPToken, TokenValue as PPTokenValue}, @@ -76,6 +76,9 @@ impl<'a> Iterator for Lexer<'a> { "highp" => TokenValue::PrecisionQualifier(Precision::High), "mediump" => TokenValue::PrecisionQualifier(Precision::Medium), "lowp" => TokenValue::PrecisionQualifier(Precision::Low), + "restrict" => TokenValue::Restrict, + "readonly" => TokenValue::StorageAccess(StorageAccess::LOAD), + "writeonly" => TokenValue::StorageAccess(StorageAccess::STORE), // values "true" => TokenValue::BoolConstant(true), "false" => TokenValue::BoolConstant(false), diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index a5b62e8caf..bb87a620e8 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -18,7 +18,7 @@ use crate::{ StructMember, SwitchCase, Type, TypeInner, UnaryOperator, }; use core::convert::TryFrom; -use std::{iter::Peekable, mem}; +use std::iter::Peekable; type Result = std::result::Result; @@ -216,6 +216,8 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { | TokenValue::Out | TokenValue::Uniform | TokenValue::Buffer + | TokenValue::Restrict + | TokenValue::StorageAccess(_) | TokenValue::Layout => true, _ => false, }) @@ -249,6 +251,8 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { ), TokenValue::Sampling(s) => TypeQualifier::Sampling(s), TokenValue::PrecisionQualifier(p) => TypeQualifier::Precision(p), + TokenValue::StorageAccess(access) => TypeQualifier::StorageAccess(access), + TokenValue::Restrict => continue, _ => unreachable!(), }, token.meta, @@ -1601,9 +1605,15 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { } } - let fall_through = body.iter().any(|s| { - mem::discriminant(s) == mem::discriminant(&Statement::Break) - }); + let mut fall_through = true; + + for (i, stmt) in body.iter().enumerate() { + if let Statement::Break = *stmt { + fall_through = false; + body.drain(i..); + break; + } + } cases.push(SwitchCase { value, @@ -1625,7 +1635,14 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { loop { match self.expect_peek()?.value { TokenValue::Case | TokenValue::RightBrace => break, - _ => self.parse_statement(ctx, &mut &mut default)?, + _ => self.parse_statement(ctx, &mut default)?, + } + } + + for (i, stmt) in default.iter().enumerate() { + if let Statement::Break = *stmt { + default.drain(i..); + break; } } } diff --git a/src/front/glsl/token.rs b/src/front/glsl/token.rs index b1f147ab7d..616c7d2d3e 100644 --- a/src/front/glsl/token.rs +++ b/src/front/glsl/token.rs @@ -56,6 +56,10 @@ pub enum TokenValue { Uniform, Buffer, Const, + + Restrict, + StorageAccess(crate::StorageAccess), + Interpolation(Interpolation), Sampling(Sampling), Precision, diff --git a/src/front/glsl/variables.rs b/src/front/glsl/variables.rs index 99a410a57c..da857cd09f 100644 --- a/src/front/glsl/variables.rs +++ b/src/front/glsl/variables.rs @@ -339,6 +339,7 @@ impl Program<'_> { let mut sampling = None; let mut layout = None; let mut precision = None; + let mut access = StorageAccess::all(); for &(ref qualifier, meta) in qualifiers { match *qualifier { @@ -393,6 +394,7 @@ impl Program<'_> { meta, "Cannot use more than one precision qualifier per declaration" ), + TypeQualifier::StorageAccess(a) => access &= a, _ => { return Err(ErrorKind::SemanticError( meta, @@ -488,15 +490,12 @@ impl Program<'_> { return Ok(GlobalOrConstant::Constant(init)); } - // TODO: Add support for qualifiers such as readonly, writeonly and readwrite let class = match self.module.types[ty].inner { TypeInner::Image { .. } => StorageClass::Handle, TypeInner::Sampler { .. } => StorageClass::Handle, _ => { if let StorageQualifier::StorageClass(StorageClass::Storage { .. }) = storage { - StorageClass::Storage { - access: StorageAccess::all(), - } + StorageClass::Storage { access } } else { match storage { StorageQualifier::StorageClass(class) => class,