[glsl.new] Add initial declaration support

Focus on handling global in/out vars
This commit is contained in:
Pelle Johnsen
2020-08-07 15:25:34 +00:00
committed by Dzmitry Malyshau
parent f98054afdd
commit 482c6d042d
5 changed files with 147 additions and 9 deletions

View File

@@ -1,6 +1,6 @@
use crate::{
Arena, Constant, Expression, FastHashMap, Function, GlobalVariable, Handle, LocalVariable,
ShaderStage, Statement, Type,
Arena, Binding, Constant, Expression, FastHashMap, Function, GlobalVariable, Handle,
LocalVariable, ShaderStage, Statement, StorageClass, Type,
};
#[derive(Debug)]
@@ -14,6 +14,7 @@ pub struct Program {
pub types: Arena<Type>,
pub constants: Arena<Constant>,
pub global_variables: Arena<GlobalVariable>,
pub lookup_global_variables: FastHashMap<String, Handle<GlobalVariable>>,
pub context: Context,
}
@@ -29,6 +30,7 @@ impl Program {
types: Arena::<Type>::new(),
constants: Arena::<Constant>::new(),
global_variables: Arena::<GlobalVariable>::new(),
lookup_global_variables: FastHashMap::default(),
context: Context {
expressions: Arena::<Expression>::new(),
local_variables: Arena::<LocalVariable>::new(),
@@ -53,3 +55,9 @@ pub struct ExpressionRule {
pub expression: Handle<Expression>,
pub statements: Vec<Statement>,
}
#[derive(Debug)]
pub enum TypeQualifier {
StorageClass(StorageClass),
Binding(Binding),
}

View File

@@ -13,6 +13,9 @@ pub enum ErrorKind {
ParserFail,
ParserStackOverflow,
NotImplemented(&'static str),
UnknownVariable(TokenMetadata, String),
ExpectedConstant,
SemanticError(&'static str),
}
impl fmt::Display for ErrorKind {
@@ -31,6 +34,11 @@ impl fmt::Display for ErrorKind {
ErrorKind::ParserFail => write!(f, "Parser failed"),
ErrorKind::ParserStackOverflow => write!(f, "Parser stack overflow"),
ErrorKind::NotImplemented(msg) => write!(f, "Not implemented: {}", msg),
ErrorKind::UnknownVariable(meta, val) => {
write!(f, "Unknown variable {} at {:?}", val, meta)
}
ErrorKind::ExpectedConstant => write!(f, "Expected constant"),
ErrorKind::SemanticError(msg) => write!(f, "Semantic error: {}", msg),
}
}
}

View File

@@ -110,6 +110,10 @@ pub fn consume_token(mut input: &str) -> (Option<Token>, &str) {
let (word, rest, pos) = consume_any(input, |c| c.is_ascii_alphanumeric() || c == '_');
meta.chars.end = start + pos;
match word {
"layout" => (Some(Token::Layout(meta)), rest),
"in" => (Some(Token::In(meta)), rest),
"out" => (Some(Token::Out(meta)), rest),
// types
"void" => (Some(Token::Void(meta)), rest),
"vec2" => (Some(Token::Vec2(meta)), rest),
"vec3" => (Some(Token::Vec3(meta)), rest),

View File

@@ -45,6 +45,7 @@ pomelo! {
%type function_declarator Function;
%type function_header Function;
%type function_definition Function;
// statements
%type compound_statement Block;
%type compound_statement_no_new_scope Block;
@@ -52,6 +53,7 @@ pomelo! {
%type statement Statement;
%type simple_statement Statement;
%type expression_statement Statement;
%type declaration_statement Statement;
// expressions
%type unary_expression ExpressionRule;
@@ -82,9 +84,18 @@ pomelo! {
%type assignment_expression ExpressionRule;
%type assignment_operator BinaryOperator;
%type expression ExpressionRule;
%type constant_expression Handle<Constant>;
// decalartions
%type layout_qualifier Binding;
%type layout_qualifier_id_list Binding;
%type layout_qualifier_id Binding;
%type type_qualifier Vec<TypeQualifier>;
%type single_type_qualifier TypeQualifier;
%type storage_qualifier StorageClass;
// types
%type fully_specified_type Option<Handle<Type>>;
%type fully_specified_type (Vec<TypeQualifier>, Option<Handle<Type>>);
%type type_specifier Option<Handle<Type>>;
%type type_specifier_nonarray Option<Type>;
@@ -116,7 +127,7 @@ pomelo! {
extra.shader_stage == ShaderStage::Fragment) {
let h = extra.global_variables.fetch_or_append(
GlobalVariable {
name: Some(v.1),
name: Some(v.1.clone()),
class: match extra.shader_stage {
ShaderStage::Vertex => StorageClass::Output,
ShaderStage::Fragment => StorageClass::Input,
@@ -133,12 +144,21 @@ pomelo! {
}),
},
);
extra.lookup_global_variables.insert(v.1, h);
ExpressionRule{
expression: extra.context.expressions.append(Expression::GlobalVariable(h)),
statements: vec![],
}
} else {
return Err(ErrorKind::NotImplemented("var"))
// try global vars
if let Some(global_var) = extra.lookup_global_variables.get(&v.1) {
ExpressionRule{
expression: extra.context.expressions.append(Expression::GlobalVariable(global_var.clone())),
statements: vec![],
}
} else {
return Err(ErrorKind::UnknownVariable(v.0, v.1))
}
}
}
@@ -401,12 +421,108 @@ pomelo! {
}
}
constant_expression ::= conditional_expression(e) {
if let Expression::Constant(h) = extra.context.expressions[e] {
h
} else {
return Err(ErrorKind::ExpectedConstant)
}
}
// declaration
declaration ::= init_declarator_list Semicolon;
init_declarator_list ::= single_declaration;
single_declaration ::= fully_specified_type;
single_declaration ::= fully_specified_type(t) Identifier(i) {
//TODO: global or local? For now always global
if let Some(ty) = t.1 {
if let Some(TypeQualifier::StorageClass(sc)) = t.0.iter().find(|tq| {
if let TypeQualifier::StorageClass(_) = tq { true } else { false }
}) {
let binding = t.0.iter().find_map(|tq| {
if let TypeQualifier::Binding(b) = tq { Some(b.clone()) } else { None }
});
let h = extra.global_variables.fetch_or_append(
GlobalVariable {
name: Some(i.1.clone()),
class: *sc,
binding: binding,
ty: ty,
},
);
extra.lookup_global_variables.insert(i.1, h);
} else {
return Err(ErrorKind::SemanticError("Missing storage class for declaration"))
}
} else {
return Err(ErrorKind::SemanticError("Empty type for declaration"))
}
}
fully_specified_type ::= type_specifier(t) {(vec![], t)}
fully_specified_type ::= type_qualifier(q) type_specifier(t) {(q,t)}
layout_qualifier ::= Layout LeftParen layout_qualifier_id_list(l) RightParen {l}
layout_qualifier_id_list ::= layout_qualifier_id;
layout_qualifier_id_list ::= layout_qualifier_id_list Comma layout_qualifier_id(l) {
//TODO: for now always pick last
l
}
// layout_qualifier_id ::= Identifier;
layout_qualifier_id ::= Identifier(i) Equal constant_expression(c) {
if i.1.as_str() == "location" {
if let ConstantInner::Sint(loc) = extra.constants[c].inner {
Binding::Location(loc as u32)
} else {
return Err(ErrorKind::NotImplemented("location not Sint"));
}
} else {
return Err(ErrorKind::NotImplemented("non location layout qualifier"));
}
}
// layout_qualifier_id ::= Shared;
// precise_qualifier ::= Precise;
type_qualifier ::= single_type_qualifier(t) {
vec![t]
}
type_qualifier ::= type_qualifier(mut l) single_type_qualifier(t) {
l.push(t);
l
}
single_type_qualifier ::= storage_qualifier(s) {
TypeQualifier::StorageClass(s)
}
single_type_qualifier ::= layout_qualifier(l) {
TypeQualifier::Binding(l)
}
// single_type_qualifier ::= precision_qualifier;
// single_type_qualifier ::= interpolation_qualifier;
// single_type_qualifier ::= invariant_qualifier;
// single_type_qualifier ::= precise_qualifier;
storage_qualifier ::= Const {StorageClass::Constant}
// storage_qualifier ::= InOut;
storage_qualifier ::= In {StorageClass::Input}
storage_qualifier ::= Out {StorageClass::Output}
//TODO: other storage qualifiers
declaration_statement ::= declaration {
//TODO: Should declarations be able to genereate expression/statements?
Statement::Empty
}
// statement
statement ::= compound_statement(cs) {Statement::Block(cs)}
statement ::= simple_statement;
// Grammar Note: labeled statements for SWITCH only; 'goto' is not supported.
//simple_statement ::= declaration_statement;
simple_statement ::= declaration_statement;
simple_statement ::= expression_statement;
//simple_statement ::= selection_statement;
//simple_statement ::= switch_statement;
@@ -440,7 +556,7 @@ pomelo! {
Function {
name: Some(n.1),
parameter_types: vec![],
return_type: t,
return_type: t.1,
global_usage: vec![],
local_variables: Arena::<LocalVariable>::new(),
expressions: Arena::<Expression>::new(),
@@ -449,7 +565,6 @@ pomelo! {
}
// type
fully_specified_type ::= type_specifier;
type_specifier ::= type_specifier_nonarray(t) {
t.map(|t| {
let name = t.name.clone();
@@ -505,6 +620,7 @@ pomelo! {
extra.lookup_function.insert(name, handle);
}
}
external_declaration ::= declaration;
function_definition ::= function_prototype(mut f) compound_statement_no_new_scope(cs) {
std::mem::swap(&mut f.expressions, &mut extra.context.expressions);

View File

@@ -1,5 +1,7 @@
#version 450 core
layout(location = 0) in vec2 position;
void main() {
gl_Position = vec4(1.0);
gl_Position = vec4(position, 0.0, 1.0);
}