From 96f9cb4ce1941e89cc0f6e4adbd9c62dd1ceef65 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 14 Apr 2021 10:05:48 -0400 Subject: [PATCH] [wgsl] Add support for simplified vector construction, add a snapshot test --- src/back/glsl/mod.rs | 6 ++- src/front/wgsl/mod.rs | 9 ++++ tests/in/operators.param.ron | 7 +++ tests/in/operators.wgsl | 6 +++ tests/out/operators.Vertex.glsl | 11 ++++ tests/out/operators.msl | 12 +++++ tests/out/operators.spvasm | 48 +++++++++++++++++ tests/out/shadow.Fragment.glsl | 2 +- tests/snapshots.rs | 96 +++++++++++---------------------- 9 files changed, 131 insertions(+), 66 deletions(-) create mode 100644 tests/in/operators.param.ron create mode 100644 tests/in/operators.wgsl create mode 100644 tests/out/operators.Vertex.glsl create mode 100644 tests/out/operators.msl create mode 100644 tests/out/operators.spvasm diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index fb686d5b0f..97b40f5466 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -1477,9 +1477,13 @@ impl<'a, W: Write> Writer<'a, W> { Expression::Constant(constant) => { self.write_constant(&self.module.constants[constant])? } - // `Splat` is just writing `value` + // `Splat` needs to actually write down a vector, it's not always inferred in GLSL. Expression::Splat { size: _, value } => { + let resolved = ctx.info[expr].ty.inner_with(&self.module.types); + self.write_value_type(resolved)?; + write!(self.out, "(")?; self.write_expr(value, ctx)?; + write!(self.out, ")")? } // `Compose` is pretty simple we just write `type(components)` where `components` is a // comma separated list of expressions diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index dfde4f2735..e9f21a2919 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -1132,6 +1132,13 @@ impl Parser { let expr = if components.is_empty() { let last_component_inner = ctx.resolve_type(last_component)?; match (&inner, last_component_inner) { + ( + &crate::TypeInner::Vector { size, .. }, + &crate::TypeInner::Scalar { .. }, + ) => crate::Expression::Splat { + size, + value: last_component, + }, ( &crate::TypeInner::Scalar { .. }, &crate::TypeInner::Scalar { .. }, @@ -1215,6 +1222,7 @@ impl Parser { crate::TypeInner::Vector { size, kind, width } => { match Composition::make(handle, size, name, name_span, ctx.expressions)? { + //TODO: Swizzling in IR Composition::Multi(size, components) => { let inner = crate::TypeInner::Vector { size, kind, width }; crate::Expression::Compose { @@ -1238,6 +1246,7 @@ impl Parser { name_span, ctx.expressions, )? { + //TODO: is this really supported? Composition::Multi(columns, components) => { let inner = crate::TypeInner::Matrix { columns, diff --git a/tests/in/operators.param.ron b/tests/in/operators.param.ron new file mode 100644 index 0000000000..bd5e5acc29 --- /dev/null +++ b/tests/in/operators.param.ron @@ -0,0 +1,7 @@ +( + spv_version: (1, 0), + spv_capabilities: [ Shader ], + spv_debug: false, + spv_adjust_coordinate_space: false, + msl_custom: false, +) diff --git a/tests/in/operators.wgsl b/tests/in/operators.wgsl new file mode 100644 index 0000000000..958924c3e5 --- /dev/null +++ b/tests/in/operators.wgsl @@ -0,0 +1,6 @@ +[[stage(vertex)]] +fn splat() -> [[builtin(position)]] vec4 { + let a = (1.0 + vec2(2.0) - 3.0) / 4.0; + let b = vec4(5) % 2; + return a.xyxy + vec4(b); +} diff --git a/tests/out/operators.Vertex.glsl b/tests/out/operators.Vertex.glsl new file mode 100644 index 0000000000..97d6d3c20e --- /dev/null +++ b/tests/out/operators.Vertex.glsl @@ -0,0 +1,11 @@ +#version 310 es + +precision highp float; + + +void main() { + vec2 _expr10 = (((vec2(1.0) + vec2(2.0)) - vec2(3.0)) / vec2(4.0)); + gl_Position = (vec4(_expr10[0], _expr10[1], _expr10[0], _expr10[1]) + vec4((ivec4(5) % ivec4(2)))); + return; +} + diff --git a/tests/out/operators.msl b/tests/out/operators.msl new file mode 100644 index 0000000000..2b21eab624 --- /dev/null +++ b/tests/out/operators.msl @@ -0,0 +1,12 @@ +#include +#include + + +struct splatOutput { + metal::float4 member [[position]]; +}; +vertex splatOutput splat( +) { + metal::float2 _e10 = ((1.0 + 2.0) - 3.0) / 4.0; + return splatOutput { metal::float4(_e10.x, _e10.y, _e10.x, _e10.y) + static_cast(5 % 2) }; +} diff --git a/tests/out/operators.spvasm b/tests/out/operators.spvasm new file mode 100644 index 0000000000..6ee2477c36 --- /dev/null +++ b/tests/out/operators.spvasm @@ -0,0 +1,48 @@ +; SPIR-V +; Version: 1.0 +; Generator: rspirv +; Bound: 37 +OpCapability Shader +%1 = OpExtInstImport "GLSL.std.450" +OpMemoryModel Logical GLSL450 +OpEntryPoint Vertex %15 "splat" %13 +OpDecorate %13 BuiltIn Position +%2 = OpTypeVoid +%4 = OpTypeFloat 32 +%3 = OpConstant %4 1.0 +%5 = OpConstant %4 2.0 +%6 = OpConstant %4 3.0 +%7 = OpConstant %4 4.0 +%9 = OpTypeInt 32 1 +%8 = OpConstant %9 5 +%10 = OpConstant %9 2 +%11 = OpTypeVector %4 4 +%14 = OpTypePointer Output %11 +%13 = OpVariable %14 Output +%16 = OpTypeFunction %2 +%18 = OpTypeVector %4 2 +%26 = OpTypeVector %9 4 +%15 = OpFunction %2 None %16 +%12 = OpLabel +OpBranch %17 +%17 = OpLabel +%19 = OpCompositeConstruct %18 %5 %5 +%20 = OpCompositeConstruct %18 %3 %3 +%21 = OpFAdd %18 %20 %19 +%22 = OpCompositeConstruct %18 %6 %6 +%23 = OpFSub %18 %21 %22 +%24 = OpCompositeConstruct %18 %7 %7 +%25 = OpFDiv %18 %23 %24 +%27 = OpCompositeConstruct %26 %8 %8 %8 %8 +%28 = OpCompositeConstruct %26 %10 %10 %10 %10 +%29 = OpSMod %26 %27 %28 +%30 = OpCompositeExtract %4 %25 0 +%31 = OpCompositeExtract %4 %25 1 +%32 = OpCompositeExtract %4 %25 0 +%33 = OpCompositeExtract %4 %25 1 +%34 = OpCompositeConstruct %11 %30 %31 %32 %33 +%35 = OpConvertSToF %11 %29 +%36 = OpFAdd %11 %34 %35 +OpStore %13 %36 +OpReturn +OpFunctionEnd \ No newline at end of file diff --git a/tests/out/shadow.Fragment.glsl b/tests/out/shadow.Fragment.glsl index 25087bcffe..be7f69466e 100644 --- a/tests/out/shadow.Fragment.glsl +++ b/tests/out/shadow.Fragment.glsl @@ -26,7 +26,7 @@ float fetch_shadow(uint light_id, vec4 homogeneous_coords) { if((homogeneous_coords[3] <= 0.0)) { return 1.0; } - float _expr28 = textureGrad(_group_0_binding_2, vec4((((vec2(homogeneous_coords[0], homogeneous_coords[1]) * vec2(0.5, -0.5)) / homogeneous_coords[3]) + vec2(0.5, 0.5)), int(light_id), (homogeneous_coords[2] / homogeneous_coords[3])), vec2(0, 0), vec2(0,0)); + float _expr28 = textureGrad(_group_0_binding_2, vec4((((vec2(homogeneous_coords[0], homogeneous_coords[1]) * vec2(0.5, -0.5)) / vec2(homogeneous_coords[3])) + vec2(0.5, 0.5)), int(light_id), (homogeneous_coords[2] / homogeneous_coords[3])), vec2(0, 0), vec2(0,0)); return _expr28; } diff --git a/tests/snapshots.rs b/tests/snapshots.rs index e54f389c3c..1a24b9151d 100644 --- a/tests/snapshots.rs +++ b/tests/snapshots.rs @@ -195,72 +195,40 @@ fn check_output_hlsl(module: &naga::Module, destination: &PathBuf) { } #[cfg(feature = "wgsl-in")] -fn convert_wgsl(name: &str, targets: Targets) { +#[test] +fn convert_wgsl() { let root = env!("CARGO_MANIFEST_DIR"); - let module = naga::front::wgsl::parse_str( - &fs::read_to_string(format!("{}/{}/{}.wgsl", root, DIR_IN, name)) - .expect("Couldn't find wgsl file"), - ) - .unwrap(); - check_targets(&module, name, targets); -} + let inputs = [ + ( + "empty", + Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::HLSL, + ), + ( + "quad", + Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::DOT, + ), + ("boids", Targets::SPIRV | Targets::METAL), + ("skybox", Targets::SPIRV | Targets::METAL | Targets::GLSL), + ( + "collatz", + Targets::SPIRV | Targets::METAL | Targets::IR | Targets::ANALYSIS, + ), + ("shadow", Targets::SPIRV | Targets::METAL | Targets::GLSL), + //SPIR-V is blocked by https://github.com/gfx-rs/naga/issues/646 + ("image-copy", Targets::METAL), + ("texture-array", Targets::SPIRV | Targets::METAL), + ("operators", Targets::SPIRV | Targets::METAL | Targets::GLSL), + ]; -#[cfg(feature = "wgsl-in")] -#[test] -fn convert_wgsl_quad() { - convert_wgsl( - "quad", - Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::DOT, - ); -} - -#[cfg(feature = "wgsl-in")] -#[test] -fn convert_wgsl_empty() { - convert_wgsl( - "empty", - Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::HLSL, - ); -} - -#[cfg(feature = "wgsl-in")] -#[test] -fn convert_wgsl_boids() { - convert_wgsl("boids", Targets::SPIRV | Targets::METAL); -} - -#[cfg(feature = "wgsl-in")] -#[test] -fn convert_wgsl_skybox() { - convert_wgsl("skybox", Targets::SPIRV | Targets::METAL | Targets::GLSL); -} - -#[cfg(feature = "wgsl-in")] -#[test] -fn convert_wgsl_collatz() { - convert_wgsl( - "collatz", - Targets::SPIRV | Targets::METAL | Targets::IR | Targets::ANALYSIS, - ); -} - -#[cfg(feature = "wgsl-in")] -#[test] -fn convert_wgsl_shadow() { - convert_wgsl("shadow", Targets::SPIRV | Targets::METAL | Targets::GLSL); -} - -#[cfg(feature = "wgsl-in")] -#[test] -fn convert_wgsl_image_copy() { - //SPIR-V is blocked by https://github.com/gfx-rs/naga/issues/646 - convert_wgsl("image-copy", Targets::METAL); -} - -#[cfg(feature = "wgsl-in")] -#[test] -fn convert_wgsl_texture_array() { - convert_wgsl("texture-array", Targets::SPIRV | Targets::METAL); + for &(name, targets) in inputs.iter() { + println!("Processing '{}'", name); + let file = fs::read_to_string(format!("{}/{}/{}.wgsl", root, DIR_IN, name)) + .expect("Couldn't find wgsl file"); + match naga::front::wgsl::parse_str(&file) { + Ok(module) => check_targets(&module, name, targets), + Err(e) => panic!("{}", e), + } + } } #[cfg(feature = "spv-in")]