diff --git a/jspd/src/lexer.rs b/jspd/src/lexer.rs index d261b3c2..199100e2 100644 --- a/jspd/src/lexer.rs +++ b/jspd/src/lexer.rs @@ -31,11 +31,11 @@ impl Deref for NodeReference { } pub(super) fn lex(node: &parser::Node, parser_program: &parser::ProgramState) -> Result { - let mut program = ProgramState { - types: HashMap::new(), - }; + return lex_parsed_node(None, None, node, parser_program,); +} - return lex_parsed_node(None, node, parser_program, &mut program); +pub(super) fn lex_with_root(root: NodeReference, node: &parser::Node, parser_program: &parser::ProgramState) -> Result { + return lex_parsed_node(Some(root.clone()), Some(Rc::downgrade(&root.0)), node, parser_program,); } #[derive(Clone, Debug)] @@ -52,7 +52,7 @@ impl Node { pub fn scope(name: String, children: Vec) -> NodeReference { Self::internal_new(Node { parent: None, - node: Nodes::Scope{ name, children }, + node: Nodes::Scope{ name, children, program_state: ProgramState { types: HashMap::new(), members: HashMap::new() } }, }) } @@ -107,6 +107,19 @@ impl Node { }) } + pub fn binding(name: String, set: u32, binding: u32, read: bool, write: bool) -> NodeReference { + Self::internal_new(Node { + parent: None, + node: Nodes::Binding { + name, + set, + binding, + read, + write, + }, + }) + } + pub fn new(node: Nodes) -> Node { Node { parent: None, @@ -194,12 +207,42 @@ impl Node { } } } + + pub fn node_mut(&mut self) -> &mut Nodes { + &mut self.node + } + + pub fn get_program_state(&self) -> Option<&ProgramState> { + match &self.node { + Nodes::Scope { program_state, .. } => { + Some(program_state) + } + _ => { + None + } + } + } + + pub fn get_program_state_mut(&mut self) -> Option<&mut ProgramState> { + match &mut self.node { + Nodes::Scope { program_state, .. } => { + Some(program_state) + } + _ => { + None + } + } + } } #[derive(Clone, Debug,)] pub enum Nodes { Null, - Scope{ name: String, children: Vec }, + Scope { + name: String, + children: Vec, + program_state: ProgramState, + }, Struct { name: String, template: Option, @@ -220,7 +263,14 @@ pub enum Nodes { Expression(Expressions), GLSL { code: String, - } + }, + Binding { + name: String, + set: u32, + binding: u32, + read: bool, + write: bool, + }, } #[derive(Clone, Debug)] @@ -241,8 +291,11 @@ pub enum Operators { #[derive(Clone, Debug,)] pub enum Expressions { - Member{ name: String }, - Literal { value: String }, + Member { + name: String, + source: Option, + }, + Literal { value: String, }, FunctionCall { function: NodeReference, name: String, @@ -267,6 +320,9 @@ pub enum Expressions { #[derive(Debug)] pub(crate) enum LexError { Undefined, + AccessingUndeclaredMember { + name: String, + }, NoSuchType{ type_name: String, }, @@ -275,9 +331,10 @@ pub(crate) enum LexError { type LexerReturn<'a> = Result<(Rc, std::slice::Iter<'a, String>), LexError>; type Lexer<'a> = fn(std::slice::Iter<'a, String>, &'a parser::ProgramState) -> LexerReturn<'a>; -#[derive(Clone)] +#[derive(Clone, Debug)] pub(crate) struct ProgramState { pub(crate) types: HashMap, + pub(crate) members: HashMap, } /// Execute a list of lexers on a stream of tokens. @@ -302,13 +359,13 @@ fn try_execute_lexers<'a>(lexers: &[Lexer<'a>], iterator: std::slice::Iter<'a, S None } -fn lex_parsed_node(parent_node: Option, parser_node: &parser::Node, parser_program: &parser::ProgramState, program: &mut ProgramState) -> Result { +fn lex_parsed_node(scope: Option, parent_node: Option, parser_node: &parser::Node, parser_program: &parser::ProgramState) -> Result { let node = match &parser_node.node { parser::Nodes::Scope{ name, children } => { let this = Node::scope(name.clone(), Vec::new()); let ch = children.iter().map(|child| { - lex_parsed_node(Some(Rc::downgrade(&this.0)), child, parser_program, program) + lex_parsed_node(Some(this.clone()), Some(Rc::downgrade(&this.0)), child, parser_program,) }).collect::, LexError>>()?; RefCell::borrow_mut(&this).add_children(ch); @@ -316,20 +373,20 @@ fn lex_parsed_node(parent_node: Option, parser_node: &parse this } parser::Nodes::Struct { name, fields } => { - if let Some(n) = program.types.get(name) { // If the type already exists, return it. + if let Some(n) = RefCell::borrow(&scope.clone().ok_or(LexError::Undefined)?.0).get_program_state().ok_or(LexError::Undefined)?.types.get(name) { // If the type already exists, return it. return Ok(n.clone()); } - + let this = Node::r#struct(name.clone(), Vec::new()); let ch = fields.iter().map(|field| { - lex_parsed_node(Some(Rc::downgrade(&this.0)), &field, parser_program, program) + lex_parsed_node(scope.clone(), Some(Rc::downgrade(&this.0)), &field, parser_program,) }).collect::, LexError>>()?; RefCell::borrow_mut(&this).add_children(ch); - program.types.insert(name.clone(), this.clone()); - program.types.insert(format!("{}*", name.clone()), this.clone()); + RefCell::borrow_mut(&scope.clone().ok_or(LexError::Undefined)?.0).get_program_state_mut().ok_or(LexError::Undefined)?.types.insert(name.clone(), this.clone()); + RefCell::borrow_mut(&scope.clone().ok_or(LexError::Undefined)?.0).get_program_state_mut().ok_or(LexError::Undefined)?.types.insert(format!("{}*", name.clone()), this.clone()); this } @@ -339,7 +396,7 @@ fn lex_parsed_node(parent_node: Option, parser_node: &parse let outer_type_name = s.next().ok_or(LexError::Undefined)?; - let outer_type = lex_parsed_node(None, parser_program.types.get(outer_type_name).ok_or(LexError::NoSuchType{ type_name: outer_type_name.to_string() })?, parser_program, program)?; + let outer_type = lex_parsed_node(scope.clone(), None, parser_program.types.get(outer_type_name).ok_or(LexError::NoSuchType{ type_name: outer_type_name.to_string() })?, parser_program,)?; let inner_type_name = s.next().ok_or(LexError::Undefined)?; @@ -356,14 +413,14 @@ fn lex_parsed_node(parent_node: Option, parser_node: &parse } ); - program.types.insert(format!("{}*", stripped), x.clone()); + RefCell::borrow_mut(&scope.clone().ok_or(LexError::Undefined)?.0).get_program_state_mut().ok_or(LexError::Undefined)?.types.insert(format!("{}*", stripped), x.clone()); x } else { - lex_parsed_node(parent_node.clone(), parser_program.types.get(inner_type_name).ok_or(LexError::NoSuchType{ type_name: inner_type_name.to_string() })?, parser_program, program)? + lex_parsed_node(scope.clone(), parent_node.clone(), parser_program.types.get(inner_type_name).ok_or(LexError::NoSuchType{ type_name: inner_type_name.to_string() })?, parser_program,)? }; - if let Some(n) = program.types.get(r#type) { // If the type already exists, return it. + if let Some(n) = RefCell::borrow_mut(&scope.clone().ok_or(LexError::Undefined)?.0).get_program_state_mut().ok_or(LexError::Undefined)?.types.get(r#type) { // If the type already exists, return it. return Ok(n.clone()); } @@ -385,24 +442,24 @@ fn lex_parsed_node(parent_node: Option, parser_node: &parse let node = Node::internal_new(struct_node); - program.types.insert(r#type.clone(), node.clone()); + RefCell::borrow_mut(&scope.clone().ok_or(LexError::Undefined)?.0).get_program_state_mut().ok_or(LexError::Undefined)?.types.insert(r#type.clone(), node.clone()); node } else { let t = parser_program.types.get(r#type.as_str()).ok_or(LexError::NoSuchType{ type_name: r#type.clone() })?; - lex_parsed_node(None, t, parser_program, program)? + lex_parsed_node(scope, None, t, parser_program,)? }; Node::member(name.clone(), t,) } parser::Nodes::Function { name, return_type, statements, raw, .. } => { let t = parser_program.types.get(return_type.as_str()).ok_or(LexError::NoSuchType{ type_name: return_type.clone() })?; - let t = lex_parsed_node(None, t, parser_program, program)?; + let t = lex_parsed_node(scope.clone(), None, t, parser_program,)?; let this = Node::function(parent_node.clone(), name.clone(), Vec::new(), t, Vec::new(), raw.clone(),); let st = statements.iter().map(|statement| { - lex_parsed_node(Some(Rc::downgrade(&this.0)), statement, parser_program, program) + lex_parsed_node(scope.clone(), Some(Rc::downgrade(&this.0)), statement, parser_program,) }).collect::, LexError>>()?; match RefCell::borrow_mut(&this).node { @@ -418,51 +475,56 @@ fn lex_parsed_node(parent_node: Option, parser_node: &parse match expression { parser::Expressions::Accessor{ left, right } => { Node::expression(Expressions::Accessor { - left: lex_parsed_node(None, left, parser_program, program)?, - right: lex_parsed_node(None, right, parser_program, program)?, - }) + left: lex_parsed_node(scope.clone(), None, left, parser_program,)?, + right: lex_parsed_node(scope.clone(), None, right, parser_program,)?, + }) } parser::Expressions::Member{ name } => { Node::expression(Expressions::Member { - name: name.clone(), - }) + source: Some(RefCell::borrow(&scope.clone().ok_or(LexError::Undefined)?.0).get_program_state().ok_or(LexError::Undefined)?.members.get(name).ok_or(LexError::AccessingUndeclaredMember{ name: name.clone() })?.clone()), + name: name.clone(), + }) } parser::Expressions::Literal{ value } => { Node::expression(Expressions::Literal { - value: value.clone(), - }) + value: value.clone(), + }) } parser::Expressions::FunctionCall{ name, parameters } => { let t = parser_program.types.get(name.as_str()).ok_or(LexError::NoSuchType{ type_name: name.clone() })?; - let function = lex_parsed_node(None, t, parser_program, program)?; + let function = lex_parsed_node(scope.clone(), None, t, parser_program,)?; Node::expression(Expressions::FunctionCall { function, name: name.clone(), - parameters: parameters.iter().map(|e| lex_parsed_node(None, e, parser_program, program).unwrap()).collect(), + parameters: parameters.iter().map(|e| lex_parsed_node(scope.clone(), None, e, parser_program,).unwrap()).collect(), }) } parser::Expressions::Operator{ name, left, right } => { Node::expression(Expressions::Operator { - operator: match name.as_str() { - "+" => Operators::Plus, - "-" => Operators::Minus, - "*" => Operators::Multiply, - "/" => Operators::Divide, - "%" => Operators::Modulo, - "=" => Operators::Assignment, - "==" => Operators::Equality, - _ => { panic!("Invalid operator") } - }, - left: lex_parsed_node(None, left, parser_program, program)?, - right: lex_parsed_node(None, right, parser_program, program)?, - }) + operator: match name.as_str() { + "+" => Operators::Plus, + "-" => Operators::Minus, + "*" => Operators::Multiply, + "/" => Operators::Divide, + "%" => Operators::Modulo, + "=" => Operators::Assignment, + "==" => Operators::Equality, + _ => { panic!("Invalid operator") } + }, + left: lex_parsed_node(scope.clone(), None, left, parser_program,)?, + right: lex_parsed_node(scope.clone(), None, right, parser_program,)?, + }) } parser::Expressions::VariableDeclaration{ name, r#type } => { - Node::expression(Expressions::VariableDeclaration { - name: name.clone(), - // r#type: lex_parsed_node(&r#type, parser_program, program)?, - r#type: r#type.clone(), - }) + let this = Node::expression(Expressions::VariableDeclaration { + name: name.clone(), + // r#type: lex_parsed_node(&r#type, parser_program, program)?, + r#type: r#type.clone(), + }); + + RefCell::borrow_mut(&scope.clone().ok_or(LexError::Undefined)?.0).get_program_state_mut().ok_or(LexError::Undefined)?.members.insert(name.clone(), this.clone()); + + this } } } @@ -490,8 +552,8 @@ mod tests { fn lex_function() { let source = " main: fn () -> void { - position: vec4f = vec4(0.0, 0.0, 0.0, 1.0); - gl_Position = position; + position: vec4f = vec4f(0.0, 0.0, 0.0, 1.0); + position = position; }"; let tokens = tokenizer::tokenize(source).expect("Failed to tokenize"); @@ -534,7 +596,7 @@ main: fn () -> void { match constructor.node() { Nodes::Expression(Expressions::FunctionCall{ name, parameters, .. }) => { - assert_eq!(name, "vec4"); + assert_eq!(name, "vec4f"); assert_eq!(parameters.len(), 4); } _ => { panic!("Expected expression"); } @@ -562,7 +624,7 @@ color: In; let node = node.borrow(); match node.node() { - Nodes::Scope{ name, children } => { + Nodes::Scope{ name, children, .. } => { assert_eq!(name, "root"); let color = children[0].borrow(); @@ -617,7 +679,7 @@ color: In; let node = node.borrow(); match node.node() { - Nodes::Scope{ name, children } => { + Nodes::Scope{ name, children, .. } => { assert_eq!(name, "root"); let vertex = children[0].borrow(); diff --git a/jspd/src/lib.rs b/jspd/src/lib.rs index fe867e9f..fd142ba1 100644 --- a/jspd/src/lib.rs +++ b/jspd/src/lib.rs @@ -15,14 +15,25 @@ pub use lexer::Nodes; pub use crate::lexer::NodeReference; -pub fn compile_to_jspd(source: &str) -> Result { +/// Compiles a BESL source code string into a JSPD. +/// +/// # Arguments +/// +/// * `source` - The source code to compile. +/// * `parent` - An optional reference to a parent Scope node where the source code will be compiled into. +pub fn compile_to_jspd(source: &str, parent: Option) -> Result { if source.split_whitespace().next() == None { return Ok(lexer::Node::scope("".to_string(), Vec::new())); } let tokens = tokenizer::tokenize(source).map_err(|_e| CompilationError::Undefined)?; let (parser_root_node, parser_program) = parser::parse(tokens).map_err(|_e| CompilationError::Undefined)?; - let jspd = lexer::lex(&parser_root_node, &parser_program).map_err(|_e| CompilationError::Undefined)?; + + let jspd = if let Some(parent) = parent { + lexer::lex_with_root(parent, &parser_root_node, &parser_program).map_err(|_e| CompilationError::Undefined)? + } else { + lexer::lex(&parser_root_node, &parser_program).map_err(|_e| CompilationError::Undefined)? + }; Ok(jspd) } @@ -201,7 +212,7 @@ mod tests { let jspd = jspd.borrow(); - if let lexer::Nodes::Scope { name, children } = jspd.node() { + if let lexer::Nodes::Scope { name, children, .. } = jspd.node() { assert_eq!(name, "root"); assert!(children.len() > 1); } else { diff --git a/jspd/src/parser.rs b/jspd/src/parser.rs index 5bc30bb0..61c0e1d5 100644 --- a/jspd/src/parser.rs +++ b/jspd/src/parser.rs @@ -350,8 +350,7 @@ fn parse_var_decl<'a>(mut iterator: std::slice::Iter<'a, String>, program: &Prog } fn parse_variable<'a>(mut iterator: std::slice::Iter<'a, String>, program: &ProgramState, mut expressions: Vec,) -> ExpressionParserResult<'a> { - let name = iterator.next().ok_or(ParsingFailReasons::NotMine)?; - name.chars().all(char::is_alphanumeric).then(|| ()).ok_or(ParsingFailReasons::NotMine)?; + let name = iterator.next().ok_or(ParsingFailReasons::NotMine).and_then(|v| if v.chars().all(is_identifier) { Ok(v) } else { Err(ParsingFailReasons::NotMine) })?; expressions.push(Atoms::Member{ name: name.clone() }); @@ -504,6 +503,13 @@ fn parse_function<'a>(mut iterator: std::slice::Iter<'a, String>, program: &Prog iterator = new_iterator; statements.push(expression); + } else { + if iterator.clone().peekable().peek().unwrap().as_str() == "}" { + iterator.next(); + break; + } else { + return Err(ParsingFailReasons::BadSyntax{ message: format!("Expected a }} after function {} declaration.", name) }); + } } // check if iter is close brace diff --git a/resource_management/src/asset/material_asset_handler.rs b/resource_management/src/asset/material_asset_handler.rs index 8145293d..27e6277f 100644 --- a/resource_management/src/asset/material_asset_handler.rs +++ b/resource_management/src/asset/material_asset_handler.rs @@ -102,7 +102,7 @@ async fn produce_shader(generator: &dyn ProgramGenerator, asset_resolver: &dyn A let shader_option = if format == "glsl" { Some((jspd::lexer::Node::glsl(shader_code), path.to_string())) } else if format == "besl" { - Some((jspd::compile_to_jspd(&shader_code).unwrap(), path.to_string())) + Some((jspd::compile_to_jspd(&shader_code, None).unwrap(), path.to_string())) } else { None }; @@ -122,93 +122,6 @@ async fn produce_shader(generator: &dyn ProgramGenerator, asset_resolver: &dyn A } } -fn generate_shader_internal(string: &mut String, main_function_node: &jspd::Node) { - let node = main_function_node; - if let Some(parent) = node.parent() { - if let Some(parent) = parent.upgrade() { - generate_shader_internal(string, RefCell::borrow(&parent).deref()); - } - } - - match node.node() { - jspd::Nodes::Null => {} - jspd::Nodes::Scope { name: _, children } => { - for child in children { - let child = RefCell::borrow(&child); - generate_shader_internal(string, &child,); - } - } - jspd::Nodes::Function { name, params: _, return_type: _, statements, raw: _ } => { - match name.as_str() { - _ => { - for statement in statements { - let statement = RefCell::borrow(&statement); - generate_shader_internal(string, &statement,); - string.push_str(";\n"); - } - } - } - } - jspd::Nodes::Struct { fields, .. } => { - for field in fields { - let field = RefCell::borrow(&field); - generate_shader_internal(string, &field,); - } - } - jspd::Nodes::Member { .. } => { - - } - jspd::Nodes::GLSL { code } => { - string.push_str(code); - } - jspd::Nodes::Expression(expression) => { - match expression { - jspd::Expressions::Operator { operator, left: _, right } => { - if operator == &jspd::Operators::Assignment { - string.push_str(&format!("albedo = vec3(")); - let right = RefCell::borrow(&right); - generate_shader_internal(string, &right,); - string.push_str(")"); - } - } - jspd::Expressions::FunctionCall { name, parameters, .. } => { - match name.as_str() { - "sample" => { - string.push_str(&format!("textureGrad(")); - for parameter in parameters { - let parameter = RefCell::borrow(¶meter); - generate_shader_internal(string, ¶meter,); - } - string.push_str(&format!(", uv, vec2(0.5), vec2(0.5f))")); - } - _ => { - string.push_str(&format!("{}(", name)); - for parameter in parameters { - let parameter = RefCell::borrow(¶meter); - generate_shader_internal(string, ¶meter,); - } - string.push_str(&format!(")")); - } - } - } - jspd::Expressions::Member { name } => { - string.push_str(name); - } - _ => panic!("Invalid expression") - } - } - } -} - -fn generate_shader(main_function_node: &jspd::Node) -> String { - // let mut string = shader_generator::generate_glsl_header_block(&shader_generator::ShaderGenerationSettings::new("Compute")); - let mut string = String::with_capacity(2048); - - generate_shader_internal(&mut string, main_function_node); - - string -} - fn treat_shader(generator: &dyn ProgramGenerator, path: &str, domain: &str, stage: &str, material: &json::JsonValue, shader_node: &jspd::NodeReference,) -> Option> { let visibility = generator; @@ -221,7 +134,7 @@ fn treat_shader(generator: &dyn ProgramGenerator, path: &str, domain: &str, stag } }; - let glsl = generate_shader(RefCell::borrow(&main).deref()); + let glsl = String::new(); log::debug!("Generated shader: {}", &glsl); diff --git a/resource_management/src/shader_generation.rs b/resource_management/src/shader_generation.rs index e6a52b10..469a5bb1 100644 --- a/resource_management/src/shader_generation.rs +++ b/resource_management/src/shader_generation.rs @@ -24,6 +24,15 @@ impl ShaderGenerator { } } +pub struct GLSLSettings { + version: String, +} + +pub struct ShaderGenerationSettings { + glsl: GLSLSettings, + stage: String, +} + struct ShaderCompilation { minified: bool, present_symbols: HashSet, @@ -39,6 +48,17 @@ impl ShaderCompilation { string } + pub fn generate_glsl_shader(&mut self, shader_compilation_settings: &ShaderGenerationSettings, main_function_node: &jspd::NodeReference) -> String { + // let mut string = shader_generator::generate_glsl_header_block(&shader_generator::ShaderGenerationSettings::new("Compute")); + let mut string = String::with_capacity(2048); + + self.generate_glsl_header_block(&mut string, shader_compilation_settings); + + self.generate_shader_internal(&mut string, main_function_node); + + string + } + fn generate_shader_internal(&mut self, string: &mut String, main_function_node: &jspd::NodeReference) { if self.present_symbols.contains(main_function_node) { return; } @@ -46,7 +66,7 @@ impl ShaderCompilation { match node.node() { jspd::Nodes::Null => {} - jspd::Nodes::Scope { name: _, children } => { + jspd::Nodes::Scope { children, .. } => { for child in children { self.generate_shader_internal(string, &child,); } @@ -129,7 +149,7 @@ impl ShaderCompilation { } string.push_str(&format!(")")); } - jspd::Expressions::Member { name } => { + jspd::Expressions::Member { name, .. } => { string.push_str(name); } jspd::Expressions::VariableDeclaration { name, r#type } => { @@ -141,7 +161,60 @@ impl ShaderCompilation { _ => panic!("Invalid expression") } } + jspd::Nodes::Binding { name, set, binding, read, write } => { + string.push_str(&format!("layout(set={}, binding={}) uniform ", set, binding)); + if *read && !*write { string.push_str("readonly "); } + if *write && !*read { string.push_str("writeonly "); } + string.push_str(&name); + if !self.minified { string.push_str(";\n"); } else { string.push(';'); } + } + } + } + + fn generate_glsl_header_block(&self, glsl_block: &mut String, compilation_settings: &ShaderGenerationSettings) { + let glsl_version = &compilation_settings.glsl.version; + + glsl_block.push_str(&format!("#version {glsl_version} core\n")); + + // shader type + + let shader_stage = compilation_settings.stage.as_str(); + + match shader_stage { + "Vertex" => glsl_block.push_str("#pragma shader_stage(vertex)\n"), + "Fragment" => glsl_block.push_str("#pragma shader_stage(fragment)\n"), + "Compute" => glsl_block.push_str("#pragma shader_stage(compute)\n"), + "Mesh" => glsl_block.push_str("#pragma shader_stage(mesh)\n"), + _ => glsl_block.push_str("#define BE_UNKNOWN_SHADER_TYPE\n") + } + + // extensions + + glsl_block.push_str("#extension GL_EXT_shader_16bit_storage:require\n"); + glsl_block.push_str("#extension GL_EXT_shader_explicit_arithmetic_types:require\n"); + glsl_block.push_str("#extension GL_EXT_nonuniform_qualifier:require\n"); + glsl_block.push_str("#extension GL_EXT_scalar_block_layout:require\n"); + glsl_block.push_str("#extension GL_EXT_buffer_reference:enable\n"); + glsl_block.push_str("#extension GL_EXT_buffer_reference2:enable\n"); + glsl_block.push_str("#extension GL_EXT_shader_image_load_formatted:enable\n"); + + match shader_stage { + "Compute" => { + glsl_block.push_str("#extension GL_KHR_shader_subgroup_basic:enable\n"); + glsl_block.push_str("#extension GL_KHR_shader_subgroup_arithmetic:enable\n"); + glsl_block.push_str("#extension GL_KHR_shader_subgroup_ballot:enable\n"); + glsl_block.push_str("#extension GL_KHR_shader_subgroup_shuffle:enable\n"); + } + "Mesh" => { + glsl_block.push_str("#extension GL_EXT_mesh_shader:require\n"); + } + _ => {} } + // memory layout declarations + + glsl_block.push_str("layout(row_major) uniform; layout(row_major) buffer;\n"); + + glsl_block.push_str("const float PI = 3.14159265359;"); } } @@ -156,11 +229,33 @@ mod tests { let script = r#" "#; - let main_function_node = jspd::compile_to_jspd(&script).unwrap(); + let script_node = jspd::compile_to_jspd(&script, None).unwrap(); let shader_generator = ShaderGenerator::new(); - let shader = shader_generator.compilation().generate_shader(&main_function_node); + let shader = shader_generator.compilation().generate_shader(&script_node); + + println!("{}", shader); + } + + #[test] + fn binding() { + let script = r#" + use_buffer: fn () -> void {} + main: fn () -> void { + use_buffer(buffer); + } + "#; + + let root_node = jspd::Node::scope("root".to_string(), vec![jspd::Node::binding("buffer".to_string(), 0, 0, true, false)]); + + let script_node = jspd::compile_to_jspd(&script, Some(root_node)).unwrap(); + + let main = RefCell::borrow(&script_node).get_child("main").unwrap(); + + let shader_generator = ShaderGenerator::new(); + + let shader = shader_generator.compilation().generate_shader(&main); println!("{}", shader); } @@ -173,9 +268,9 @@ mod tests { } "#; - let main_function_node = jspd::compile_to_jspd(&script).unwrap(); + let script_node = jspd::compile_to_jspd(&script, None).unwrap(); - let main = RefCell::borrow(&main_function_node).get_child("main").unwrap(); + let main = RefCell::borrow(&script_node).get_child("main").unwrap(); let shader_generator = ShaderGenerator::new(); @@ -204,7 +299,7 @@ mod tests { } "#; - let main_function_node = jspd::compile_to_jspd(&script).unwrap(); + let main_function_node = jspd::compile_to_jspd(&script, None).unwrap(); let main = RefCell::borrow(&main_function_node).get_child("main").unwrap(); @@ -230,7 +325,7 @@ mod tests { } "#; - let main_function_node = jspd::compile_to_jspd(&script).unwrap(); + let main_function_node = jspd::compile_to_jspd(&script, None).unwrap(); let main = RefCell::borrow(&main_function_node).get_child("main").unwrap(); diff --git a/src/rendering/visibility_shader_generator.rs b/src/rendering/visibility_shader_generator.rs index 8874b2df..f745e750 100644 --- a/src/rendering/visibility_shader_generator.rs +++ b/src/rendering/visibility_shader_generator.rs @@ -80,7 +80,7 @@ impl ProgramGenerator for VisibilityShaderGenerator { let mut node = jspd::json_to_jspd(&value).unwrap(); - if let jspd::lexer::Nodes::Scope { name, children } = &mut node.node { + if let jspd::lexer::Nodes::Scope { name, children, .. } = &mut node.node { children.append(&mut parent_children); }; @@ -375,7 +375,7 @@ mod tests { let shader_source = "main: fn () -> void { out_color = albedo; }"; - let shader_node = jspd::compile_to_jspd(shader_source).unwrap(); + let shader_node = jspd::compile_to_jspd(shader_source, None).unwrap(); let shader_generator = super::VisibilityShaderGenerator::new(); @@ -401,7 +401,7 @@ mod tests { let shader_source = "main: fn () -> void { out_color = sample(albedo); }"; - let shader_node = jspd::compile_to_jspd(shader_source).unwrap(); + let shader_node = jspd::compile_to_jspd(shader_source, None).unwrap(); let shader_generator = super::VisibilityShaderGenerator::new();