mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[glsl-in] Add support for precision qualifiers
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -246,6 +246,15 @@ fn declarations() {
|
||||
&entry_points,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let _program = parse_program(
|
||||
r#"
|
||||
#version 450
|
||||
precision highp float;
|
||||
"#,
|
||||
&entry_points,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user