From b1fa7471d205499511afcbb5415548a112386dea Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 5 Feb 2021 10:27:01 -0500 Subject: [PATCH] Basic image query support in SPV and WGSL frontends --- src/back/msl/writer.rs | 2 + src/front/spv/mod.rs | 84 +++++++++++++++++++++++++++++++++++++++++ src/front/wgsl/mod.rs | 46 ++++++++++++++++++++++ src/front/wgsl/tests.rs | 18 ++++++++- 4 files changed, 149 insertions(+), 1 deletion(-) diff --git a/src/back/msl/writer.rs b/src/back/msl/writer.rs index ee3a5e9871..7ad3bd9b3f 100644 --- a/src/back/msl/writer.rs +++ b/src/back/msl/writer.rs @@ -351,6 +351,8 @@ impl Writer { // so a conversion is needed. crate::Expression::ImageQuery { image, query } => match query { crate::ImageQuery::Size { level } => { + //Note: MSL only has separate width/height/depth queries, + // so compose the result of them. let dim = match *self.typifier.get(image, &context.module.types) { crate::TypeInner::Image { dim, .. } => dim, ref other => unreachable!("Unexpected type {:?}", other), diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index 1396221f03..783245cb39 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -1113,6 +1113,90 @@ impl> Parser { }, ); } + Op::ImageQuerySize => { + inst.expect(4)?; + let result_type_id = self.next()?; + let result_id = self.next()?; + let image_id = self.next()?; + + //TODO: handle arrays and cubes + let image_lexp = self.lookup_expression.lookup(image_id)?.clone(); + + let expr = crate::Expression::ImageQuery { + image: image_lexp.handle, + query: crate::ImageQuery::Size { level: None }, + }; + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: expressions.append(expr), + type_id: result_type_id, + }, + ); + } + Op::ImageQuerySizeLod => { + inst.expect(5)?; + let result_type_id = self.next()?; + let result_id = self.next()?; + let image_id = self.next()?; + let level_id = self.next()?; + + //TODO: handle arrays and cubes + let image_lexp = self.lookup_expression.lookup(image_id)?.clone(); + let level_lexp = self.lookup_expression.lookup(level_id)?.clone(); + + let expr = crate::Expression::ImageQuery { + image: image_lexp.handle, + query: crate::ImageQuery::Size { + level: Some(level_lexp.handle), + }, + }; + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: expressions.append(expr), + type_id: result_type_id, + }, + ); + } + Op::ImageQueryLevels => { + let result_type_id = self.next()?; + let result_id = self.next()?; + let image_id = self.next()?; + + let image_lexp = self.lookup_expression.lookup(image_id)?.clone(); + + let expr = crate::Expression::ImageQuery { + image: image_lexp.handle, + query: crate::ImageQuery::NumLevels, + }; + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: expressions.append(expr), + type_id: result_type_id, + }, + ); + } + Op::ImageQuerySamples => { + let result_type_id = self.next()?; + let result_id = self.next()?; + let image_id = self.next()?; + + let image_lexp = self.lookup_expression.lookup(image_id)?.clone(); + + let expr = crate::Expression::ImageQuery { + image: image_lexp.handle, + query: crate::ImageQuery::NumSamples, + }; + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: expressions.append(expr), + type_id: result_type_id, + }, + ); + } Op::Select => { inst.expect(6)?; let result_type_id = self.next()?; diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index e807ec5d2c..508d01e4d3 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -604,6 +604,52 @@ impl Parser { index, }) } + "textureDimensions" => { + lexer.expect(Token::Paren('('))?; + let image_name = lexer.next_ident()?; + let image = ctx.lookup_ident.lookup(image_name)?; + let level = if lexer.skip(Token::Separator(',')) { + let expr = self.parse_general_expression(lexer, ctx.reborrow())?; + Some(expr) + } else { + None + }; + lexer.expect(Token::Paren(')'))?; + Some(crate::Expression::ImageQuery { + image, + query: crate::ImageQuery::Size { level }, + }) + } + "textureNumLevels" => { + lexer.expect(Token::Paren('('))?; + let image_name = lexer.next_ident()?; + let image = ctx.lookup_ident.lookup(image_name)?; + lexer.expect(Token::Paren(')'))?; + Some(crate::Expression::ImageQuery { + image, + query: crate::ImageQuery::NumLevels, + }) + } + "textureNumLayers" => { + lexer.expect(Token::Paren('('))?; + let image_name = lexer.next_ident()?; + let image = ctx.lookup_ident.lookup(image_name)?; + lexer.expect(Token::Paren(')'))?; + Some(crate::Expression::ImageQuery { + image, + query: crate::ImageQuery::NumLayers, + }) + } + "textureNumSamples" => { + lexer.expect(Token::Paren('('))?; + let image_name = lexer.next_ident()?; + let image = ctx.lookup_ident.lookup(image_name)?; + lexer.expect(Token::Paren(')'))?; + Some(crate::Expression::ImageQuery { + image, + query: crate::ImageQuery::NumSamples, + }) + } _ => { match ctx.functions.iter().find(|(_, fun)| match fun.name { Some(ref string) => string == name, diff --git a/src/front/wgsl/tests.rs b/src/front/wgsl/tests.rs index 434a46059b..2bb6707f1d 100644 --- a/src/front/wgsl/tests.rs +++ b/src/front/wgsl/tests.rs @@ -155,7 +155,7 @@ fn parse_texture_load() { " var t: texture_multisampled_2d_array; fn foo() { - const r: vec4 = textureLoad(t, vec2(10, 20), 2, 3); + const r: vec4 = textureLoad(t, vec2(10, 20), 2, 3); } ", ) @@ -171,6 +171,22 @@ fn parse_texture_load() { .unwrap(); } +#[test] +fn parse_texture_query() { + parse_str( + " + var t: texture_multisampled_2d_array; + fn foo() { + var dim: vec2 = textureDimensions(t); + dim = textureDimensions(t, 0); + const layers: i32 = textureNumLayers(t); + const samples: i32 = textureNumSamples(t); + } + ", + ) + .unwrap(); +} + #[test] fn parse_postfix() { parse_str("fn foo() { const x: f32 = vec4(1.0, 2.0, 3.0, 4.0).xyz.rgbr.aaaa.wz.g; }")