mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[glsl-in] block declarations
This commit is contained in:
committed by
Dzmitry Malyshau
parent
14f2caf6b0
commit
4e40a75843
@@ -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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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()?;
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user