From 602367c062e37819501168ca7063ab41dc6e4879 Mon Sep 17 00:00:00 2001 From: Pelle Johnsen Date: Sun, 1 Nov 2020 13:46:21 +0000 Subject: [PATCH] [glsl-in] Add initial texture handling --- src/front/glsl/ast.rs | 7 +-- src/front/glsl/parser.rs | 78 +++++++++++++++++++++++++--------- src/front/glsl/parser_tests.rs | 18 ++++++++ src/front/glsl/types.rs | 15 +++++++ 4 files changed, 95 insertions(+), 23 deletions(-) diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index ce63dee0be..cd7abfdeaa 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -138,6 +138,7 @@ impl Context { pub struct ExpressionRule { pub expression: Handle, pub statements: Vec, + pub sampler: Option>, } impl ExpressionRule { @@ -145,6 +146,7 @@ impl ExpressionRule { ExpressionRule { expression, statements: vec![], + sampler: None, } } } @@ -166,12 +168,11 @@ pub struct VarDeclaration { #[derive(Debug)] pub enum FunctionCallKind { TypeConstructor(Handle), - Function(Handle), + Function(String), } #[derive(Debug)] pub struct FunctionCall { pub kind: FunctionCallKind, - pub args: Vec>, - pub statements: Vec, + pub args: Vec, } diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index 4cb212fdc8..2914c5de5a 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -7,7 +7,7 @@ pomelo! { use super::super::{error::ErrorKind, token::*, ast::*}; use crate::{proc::Typifier, Arena, BinaryOperator, Binding, Block, Constant, ConstantInner, EntryPoint, Expression, FallThrough, FastHashMap, Function, GlobalVariable, Handle, Interpolation, - LocalVariable, MemberOrigin, ScalarKind, Statement, StorageAccess, + LocalVariable, MemberOrigin, SampleLevel, ScalarKind, Statement, StorageAccess, StorageClass, StructMember, Type, TypeInner}; } %token #[derive(Debug)] #[cfg_attr(test, derive(PartialEq))] pub enum Token {}; @@ -230,7 +230,7 @@ pomelo! { postfix_expression ::= postfix_expression(e) Dot Identifier(i) /* FieldSelection in spec */ { //TODO: how will this work as l-value? let expression = extra.field_selection(e.expression, &*i.1, i.0)?; - ExpressionRule { expression, statements: e.statements } + ExpressionRule { expression, statements: e.statements, sampler: None } } postfix_expression ::= postfix_expression(pe) IncOp { //TODO @@ -244,17 +244,49 @@ pomelo! { integer_expression ::= expression; function_call ::= function_call_or_method(fc) { - if let FunctionCallKind::TypeConstructor(ty) = fc.kind { - let h = extra.context.expressions.append(Expression::Compose{ - ty, - components: fc.args, - }); - ExpressionRule{ - expression: h, - statements: fc.statements, + match fc.kind { + FunctionCallKind::TypeConstructor(ty) => { + let h = extra.context.expressions.append(Expression::Compose{ + ty, + components: fc.args.iter().map(|a| a.expression).collect(), + }); + ExpressionRule{ + expression: h, + statements: fc.args.into_iter().map(|a| a.statements).flatten().collect(), + sampler: None + } + } + FunctionCallKind::Function(name) => { + match name.as_str() { + "sampler2D" => { + //TODO: check args len + ExpressionRule{ + expression: fc.args[0].expression, + sampler: Some(fc.args[1].expression), + statements: fc.args.into_iter().map(|a| a.statements).flatten().collect(), + } + } + "texture" => { + //TODO: check args len + if let Some(sampler) = fc.args[0].sampler { + ExpressionRule{ + expression: extra.context.expressions.append(Expression::ImageSample{ + image: fc.args[0].expression, + sampler, + coordinate: fc.args[1].expression, + level: SampleLevel::Auto, + depth_ref: None, + }), + sampler: None, + statements: fc.args.into_iter().map(|a| a.statements).flatten().collect(), + } + } else { + return Err(ErrorKind::SemanticError("Bad call to texture")); + } + } + _ => { return Err(ErrorKind::NotImplemented("Function call")); } + } } - } else { - return Err(ErrorKind::NotImplemented("Function call")); } } function_call_or_method ::= function_call_generic; @@ -269,26 +301,22 @@ pomelo! { } function_call_header_no_parameters ::= function_call_header; function_call_header_with_parameters ::= function_call_header(mut h) assignment_expression(ae) { - h.args.push(ae.expression); - h.statements.extend(ae.statements); + h.args.push(ae); h } function_call_header_with_parameters ::= function_call_header_with_parameters(mut h) Comma assignment_expression(ae) { - h.args.push(ae.expression); - h.statements.extend(ae.statements); + h.args.push(ae); h } function_call_header ::= function_identifier(i) LeftParen { FunctionCall { kind: i, args: vec![], - statements: vec![], } } // Grammar Note: Constructors look like functions, but lexical analysis recognized most of them as // keywords. They are now recognized through “type_specifier”. - // Methods (.length), subroutine array calls, and identifiers are recognized through postfix_expression. function_identifier ::= type_specifier(t) { if let Some(ty) = t { FunctionCallKind::TypeConstructor(ty) @@ -296,10 +324,19 @@ pomelo! { return Err(ErrorKind::NotImplemented("bad type ctor")) } } - function_identifier ::= postfix_expression(e) { - FunctionCallKind::Function(e.expression) + + //TODO + // Methods (.length), subroutine array calls, and identifiers are recognized through postfix_expression. + // function_identifier ::= postfix_expression(e) { + // FunctionCallKind::Function(e.expression) + // } + + // Simplification of above + function_identifier ::= Identifier(i) { + FunctionCallKind::Function(i.1) } + unary_expression ::= postfix_expression; unary_expression ::= IncOp unary_expression { @@ -452,6 +489,7 @@ pomelo! { ExpressionRule{ expression: e.expression, statements: ae.statements, + sampler: None, } } diff --git a/src/front/glsl/parser_tests.rs b/src/front/glsl/parser_tests.rs index f564c679d2..ccdc657a78 100644 --- a/src/front/glsl/parser_tests.rs +++ b/src/front/glsl/parser_tests.rs @@ -162,3 +162,21 @@ fn control_flow() { ) .unwrap(); } + +#[test] +fn textures() { + let _program = parse_program( + r#" + #version 450 + layout(location = 0) in vec2 v_uv; + layout(location = 0) out vec4 o_color; + layout(set = 1, binding = 1) uniform texture2D tex; + layout(set = 1, binding = 2) uniform sampler tex_sampler; + void main() { + o_color = texture(sampler2D(tex, tex_sampler), v_uv); + } + "#, + ShaderStage::Fragment, + ) + .unwrap(); +} diff --git a/src/front/glsl/types.rs b/src/front/glsl/types.rs index dceb230b83..715c0c7430 100644 --- a/src/front/glsl/types.rs +++ b/src/front/glsl/types.rs @@ -37,6 +37,21 @@ pub fn parse_type(type_name: &str) -> Option { width: 4, }, }), + "texture2D" => Some(Type { + name: None, + inner: TypeInner::Image { + dim: crate::ImageDimension::D2, + arrayed: false, + class: crate::ImageClass::Sampled { + kind: ScalarKind::Float, + multi: false, + }, + }, + }), + "sampler" => Some(Type { + name: None, + inner: TypeInner::Sampler { comparison: false }, + }), word => { fn kind_width_parse(ty: &str) -> Option<(ScalarKind, u8)> { Some(match ty {