[glsl-in] Add support for precision qualifiers

This commit is contained in:
João Capucho
2021-06-21 21:27:55 +01:00
parent 898c2e7c68
commit d3fe1c978b
6 changed files with 86 additions and 6 deletions

View File

@@ -955,6 +955,7 @@ pub enum TypeQualifier {
WorkGroupSize(usize, u32),
Sampling(Sampling),
Layout(StructLayout),
Precision(Precision),
EarlyFragmentTests,
}
@@ -984,6 +985,14 @@ pub enum StructLayout {
Std430,
}
// TODO: Encode precision hints in the IR
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum Precision {
Low,
Medium,
High,
}
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum ParameterQualifier {
In,

View File

@@ -1,4 +1,5 @@
use super::{
ast::Precision,
token::{SourceMetadata, Token, TokenValue},
types::parse_type,
};
@@ -58,6 +59,7 @@ impl<'a> Iterator for Lexer<'a> {
PPTokenValue::Float(float) => TokenValue::FloatConstant(float),
PPTokenValue::Ident(ident) => {
match ident.as_str() {
// Qualifiers
"layout" => TokenValue::Layout,
"in" => TokenValue::In,
"out" => TokenValue::Out,
@@ -70,6 +72,10 @@ impl<'a> Iterator for Lexer<'a> {
"sample" => TokenValue::Sampling(crate::Sampling::Sample),
"const" => TokenValue::Const,
"inout" => TokenValue::InOut,
"precision" => TokenValue::Precision,
"highp" => TokenValue::PrecisionQualifier(Precision::High),
"mediump" => TokenValue::PrecisionQualifier(Precision::Medium),
"lowp" => TokenValue::PrecisionQualifier(Precision::Low),
// values
"true" => TokenValue::BoolConstant(true),
"false" => TokenValue::BoolConstant(false),

View File

@@ -10,9 +10,11 @@ use super::{
Program,
};
use crate::{
arena::Handle, front::glsl::error::ExpectedToken, Arena, ArraySize, BinaryOperator, Block,
Constant, ConstantInner, Expression, Function, FunctionResult, ResourceBinding, ScalarValue,
Statement, StorageClass, StructMember, SwitchCase, Type, TypeInner, UnaryOperator,
arena::Handle,
front::glsl::{ast::Precision, error::ExpectedToken},
Arena, ArraySize, BinaryOperator, Block, Constant, ConstantInner, Expression, Function,
FunctionResult, ResourceBinding, ScalarKind, ScalarValue, Statement, StorageClass,
StructMember, SwitchCase, Type, TypeInner, UnaryOperator,
};
use core::convert::TryFrom;
use std::{iter::Peekable, mem};
@@ -206,6 +208,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
self.lexer.peek().map_or(false, |t| match t.value {
TokenValue::Interpolation(_)
| TokenValue::Sampling(_)
| TokenValue::PrecisionQualifier(_)
| TokenValue::Const
| TokenValue::In
| TokenValue::Out
@@ -241,7 +244,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
StorageQualifier::StorageClass(StorageClass::Storage),
),
TokenValue::Sampling(s) => TypeQualifier::Sampling(s),
TokenValue::PrecisionQualifier(p) => TypeQualifier::Precision(p),
_ => unreachable!(),
},
token.meta,
@@ -829,7 +832,51 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
}
}
} else {
Ok(false)
match self.lexer.peek().map(|t| &t.value) {
Some(&TokenValue::Precision) => {
// PRECISION precision_qualifier type_specifier SEMICOLON
self.bump()?;
let token = self.bump()?;
let _ = match token.value {
TokenValue::PrecisionQualifier(p) => p,
_ => {
return Err(ErrorKind::InvalidToken(
token,
vec![
TokenValue::PrecisionQualifier(Precision::High).into(),
TokenValue::PrecisionQualifier(Precision::Medium).into(),
TokenValue::PrecisionQualifier(Precision::Low).into(),
],
))
}
};
let (ty, meta) = self.parse_type_non_void()?;
match self.program.module.types[ty].inner {
TypeInner::Scalar {
kind: ScalarKind::Float,
..
}
| TypeInner::Scalar {
kind: ScalarKind::Sint,
..
} => {}
_ => {
return Err(ErrorKind::SemanticError(
meta,
"Precision statement can only work on floats and ints".into(),
))
}
}
self.expect(TokenValue::Semicolon)?;
Ok(true)
}
_ => Ok(false),
}
}
}

View File

@@ -246,6 +246,15 @@ fn declarations() {
&entry_points,
)
.unwrap();
let _program = parse_program(
r#"
#version 450
precision highp float;
"#,
&entry_points,
)
.unwrap();
}
#[test]

View File

@@ -1,5 +1,6 @@
pub use pp_rs::token::{Float, Integer, PreprocessorError};
use super::ast::Precision;
use crate::{Interpolation, Sampling, Type};
use std::{fmt, ops::Range};
@@ -57,6 +58,8 @@ pub enum TokenValue {
Const,
Interpolation(Interpolation),
Sampling(Sampling),
Precision,
PrecisionQualifier(Precision),
Continue,
Break,

View File

@@ -302,6 +302,7 @@ impl Program<'_> {
let mut location = None;
let mut sampling = None;
let mut layout = None;
let mut precision = None;
for &(ref qualifier, meta) in qualifiers {
match *qualifier {
@@ -350,7 +351,12 @@ impl Program<'_> {
meta,
"Cannot use more than one layout qualifier per declaration"
),
TypeQualifier::Precision(ref p) => qualifier_arm!(
p,
precision,
meta,
"Cannot use more than one precision qualifier per declaration"
),
_ => {
return Err(ErrorKind::SemanticError(
meta,