[glsl-in] block declarations

This commit is contained in:
João Capucho
2021-05-14 19:18:01 +01:00
committed by Dzmitry Malyshau
parent 14f2caf6b0
commit 4e40a75843
4 changed files with 199 additions and 72 deletions

View File

@@ -1,15 +1,16 @@
use super::{super::Typifier, constants::ConstantSolver, error::ErrorKind, TokenMetadata};
use crate::{
proc::ResolveContext, Arena, ArraySize, BinaryOperator, Block, BuiltIn, Constant, Expression,
FastHashMap, Function, FunctionArgument, GlobalVariable, Handle, Interpolation, LocalVariable,
Module, RelationalFunction, ResourceBinding, Sampling, ShaderStage, Statement, StorageClass,
Type, TypeInner, UnaryOperator,
proc::ResolveContext, Arena, BinaryOperator, Block, BuiltIn, Constant, Expression, FastHashMap,
Function, FunctionArgument, GlobalVariable, Handle, Interpolation, LocalVariable, Module,
RelationalFunction, ResourceBinding, Sampling, ShaderStage, Statement, StorageClass, Type,
TypeInner, UnaryOperator,
};
#[derive(Debug)]
pub enum GlobalLookup {
Variable(Handle<GlobalVariable>),
Select(u32),
InOutSelect(u32),
BlockSelect(Handle<GlobalVariable>, u32),
}
#[derive(Debug, PartialEq, Eq, Hash)]
@@ -162,52 +163,6 @@ impl<'a> Program<'a> {
vec![ParameterQualifier::In],
)
}
#[allow(dead_code)] // FIXME: Remove after implementing structs
pub fn type_size(&self, ty: Handle<Type>) -> Result<u8, ErrorKind> {
Ok(match self.module.types[ty].inner {
crate::TypeInner::Scalar { width, .. } => width,
crate::TypeInner::Vector { size, width, .. } => size as u8 * width,
crate::TypeInner::Matrix {
columns,
rows,
width,
} => columns as u8 * rows as u8 * width,
crate::TypeInner::Pointer { .. } => {
return Err(ErrorKind::NotImplemented("type size of pointer"))
}
crate::TypeInner::ValuePointer { .. } => {
return Err(ErrorKind::NotImplemented("type size of value pointer"))
}
crate::TypeInner::Array { size, stride, .. } => {
stride as u8
* match size {
ArraySize::Dynamic => {
return Err(ErrorKind::NotImplemented("type size of dynamic array"))
}
ArraySize::Constant(constant) => {
match self.module.constants[constant].inner {
crate::ConstantInner::Scalar { width, .. } => width,
crate::ConstantInner::Composite { .. } => {
return Err(ErrorKind::NotImplemented(
"type size of array with composite item size",
))
}
}
}
}
}
crate::TypeInner::Struct { .. } => {
return Err(ErrorKind::NotImplemented("type size of struct"))
}
crate::TypeInner::Image { .. } => {
return Err(ErrorKind::NotImplemented("type size of image"))
}
crate::TypeInner::Sampler { .. } => {
return Err(ErrorKind::NotImplemented("type size of sampler"))
}
})
}
}
#[derive(Debug)]
@@ -265,9 +220,14 @@ impl<'function> Context<'function> {
self.lookup_global_var_exps.get(name).cloned().or_else(|| {
let expr = match *program.lookup_global_variables.get(name)? {
GlobalLookup::Variable(v) => Expression::GlobalVariable(v),
GlobalLookup::Select(index) => {
GlobalLookup::InOutSelect(index) => {
let base = self.expressions.append(Expression::FunctionArgument(0));
Expression::AccessIndex { base, index }
}
GlobalLookup::BlockSelect(handle, index) => {
let base = self.expressions.append(Expression::GlobalVariable(handle));
Expression::AccessIndex { base, index }
}
};

View File

@@ -1,7 +1,7 @@
use super::{
ast::{
Context, Expr, ExprKind, FunctionCall, FunctionCallKind, ParameterQualifier, Profile,
StorageQualifier, StructLayout, TypeQualifier,
Context, Expr, ExprKind, FunctionCall, FunctionCallKind, GlobalLookup, ParameterQualifier,
Profile, StorageQualifier, StructLayout, TypeQualifier,
},
error::ErrorKind,
lex::Lexer,
@@ -10,8 +10,8 @@ use super::{
};
use crate::{
arena::Handle, Arena, ArraySize, BinaryOperator, Block, Constant, ConstantInner, Expression,
Function, FunctionResult, ResourceBinding, ScalarValue, Statement, StorageClass, SwitchCase,
Type, TypeInner, UnaryOperator,
Function, FunctionResult, GlobalVariable, ResourceBinding, ScalarValue, Statement,
StorageAccess, StorageClass, StructMember, SwitchCase, Type, TypeInner, UnaryOperator,
};
use core::convert::TryFrom;
use std::{iter::Peekable, mem};
@@ -627,7 +627,16 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
// ```
let token = self.bump()?;
match token.value {
TokenValue::Identifier(_) => todo!(),
TokenValue::Identifier(ty_name) => {
if self.bump_if(TokenValue::LeftBrace).is_some() {
self.parse_block_declaration(&qualifiers, ty_name)
} else {
//TODO: declaration
// type_qualifier IDENTIFIER SEMICOLON
// type_qualifier IDENTIFIER identifier_list SEMICOLON
todo!()
}
}
TokenValue::Semicolon => Ok(true),
_ => Err(ErrorKind::InvalidToken(token)),
}
@@ -638,6 +647,147 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
}
}
fn parse_block_declaration(
&mut self,
qualifiers: &[TypeQualifier],
ty_name: String,
) -> Result<bool> {
let mut class = StorageClass::Function;
let mut binding = None;
let mut layout = None;
for qualifier in qualifiers {
match *qualifier {
TypeQualifier::StorageQualifier(StorageQualifier::StorageClass(c)) => {
if StorageClass::Function != class {
return Err(ErrorKind::SemanticError(
"Cannot use more than one storage qualifier per declaration".into(),
));
}
class = c;
}
TypeQualifier::ResourceBinding(ref r) => {
if binding.is_some() {
return Err(ErrorKind::SemanticError(
"Cannot use more than one storage qualifier per declaration".into(),
));
}
binding = Some(r.clone());
}
TypeQualifier::Layout(ref l) => {
if layout.is_some() {
return Err(ErrorKind::SemanticError(
"Cannot use more than one storage qualifier per declaration".into(),
));
}
layout = Some(l);
}
_ => {
return Err(ErrorKind::SemanticError(
"Qualifier not supported in block declarations".into(),
));
}
}
}
let mut members = Vec::new();
let span = self.parse_struct_declaration_list(&mut members)?;
self.expect(TokenValue::RightBrace)?;
let mut ty = self.program.module.types.append(Type {
name: Some(ty_name),
inner: TypeInner::Struct {
top_level: true,
members: members.clone(),
span,
},
});
let token = self.bump()?;
let name = match token.value {
TokenValue::Semicolon => None,
TokenValue::Identifier(name) => {
if let Some(size) = self.parse_array_specifier()? {
ty = self.program.module.types.append(Type {
name: None,
inner: TypeInner::Array {
base: ty,
size,
stride: self.program.module.types[ty]
.inner
.span(&self.program.module.constants),
},
});
}
self.expect(TokenValue::Semicolon)?;
Some(name)
}
_ => return Err(ErrorKind::InvalidToken(token)),
};
let handle = self.program.module.global_variables.append(GlobalVariable {
name: name.clone(),
class,
binding,
ty,
init: None,
// TODO
storage_access: StorageAccess::all(),
});
if let Some(k) = name {
self.program
.lookup_global_variables
.insert(k, GlobalLookup::Variable(handle));
}
for (i, k) in members
.into_iter()
.enumerate()
.filter_map(|(i, m)| m.name.map(|s| (i as u32, s)))
{
self.program
.lookup_global_variables
.insert(k, GlobalLookup::BlockSelect(handle, i));
}
Ok(true)
}
// TODO: Accept layout arguments
fn parse_struct_declaration_list(&mut self, members: &mut Vec<StructMember>) -> Result<u32> {
let mut span = 0;
loop {
// TODO: type_qualifier
if !self.peek_type_name() {
break;
}
let ty = self.parse_type_non_void()?;
let name = self.expect_ident()?.0;
self.expect(TokenValue::Semicolon)?;
members.push(StructMember {
name: Some(name),
ty,
binding: None,
offset: span,
});
span = self.program.module.types[ty]
.inner
.span(&self.program.module.constants);
}
Ok(span)
}
fn parse_primary(&mut self, ctx: &mut Context) -> Result<Expr> {
let mut token = self.bump()?;

View File

@@ -187,20 +187,37 @@ fn declarations() {
)
.unwrap();
// TODO: Reenable tests later
// let _program = parse_program(
// r#"
// #version 450
// layout(std140, set = 2, binding = 0)
// uniform u_locals {
// vec3 model_offs;
// float load_time;
// ivec4 atlas_offs;
// };
// "#,
// &entry_points,
// )
// .unwrap();
let _program = parse_program(
r#"
#version 450
layout(std140, set = 2, binding = 0)
uniform u_locals {
vec3 model_offs;
float load_time;
ivec4 atlas_offs;
};
"#,
&entry_points,
)
.unwrap();
let _program = parse_program(
r#"
#version 450
layout(std140, set = 2, binding = 0)
uniform u_locals {
vec3 model_offs;
float load_time;
} block_var;
void main() {
load_time * model_offs;
block_var.load_time * block_var.model_offs;
}
"#,
&entry_points,
)
.unwrap();
}
#[test]

View File

@@ -301,7 +301,7 @@ impl Program<'_> {
);
self.lookup_global_variables
.insert(name, GlobalLookup::Select(index));
.insert(name, GlobalLookup::InOutSelect(index));
let base = ctx.expressions.append(Expression::FunctionArgument(0));
return Ok(ctx