Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using inverse in GLSL appears to cause an issue when parsing resulting WGSL (wgpu v0.8.1) #893

Closed
mitchmindtree opened this issue May 21, 2021 · 1 comment
Labels
area: front-end Input formats for conversion help wanted Extra attention is needed kind: feature New feature or request lang: SPIR-V Binary SPIR-V input and output

Comments

@mitchmindtree
Copy link

While updating one of nannou's camera/teapot examples from 0.7 to 0.8.1, I ran into the following parser error:

wgpu error: Validation Error

Caused by:
    In Device::create_shader_module
      note: label = `nannou_shader_module`
    Failed to parse WGSL


thread 'main' panicked at 'Handling wgpu errors as fatal by default', /home/mindtree/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-0.8.1/src/backend/direct.rs:1955:5
stack backtrace:
   0: std::panicking::begin_panic
             at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:519:12
   1: wgpu::backend::direct::default_error_handler
             at /home/mindtree/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-0.8.1/src/backend/direct.rs:1955:5
   2: core::ops::function::Fn::call
             at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/ops/function.rs:70:5
   3: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
             at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/alloc/src/boxed.rs:1535:9
   4: wgpu::backend::direct::ErrorSinkRaw::handle_error
             at /home/mindtree/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-0.8.1/src/backend/direct.rs:1942:9
   5: wgpu::backend::direct::Context::handle_error
             at /home/mindtree/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-0.8.1/src/backend/direct.rs:93:9
   6: <wgpu::backend::direct::Context as wgpu::Context>::device_create_shader_module
             at /home/mindtree/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-0.8.1/src/backend/direct.rs:819:13
   7: wgpu::Device::create_shader_module
             at /home/mindtree/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-0.8.1/src/lib.rs:1537:17
   8: nannou::wgpu::shader_from_spirv_bytes
             at /home/mindtree/programming/rust/nannou/nannou/src/wgpu/mod.rs:95:5
   9: wgpu_teapot_camera::model
             at /home/mindtree/programming/rust/nannou/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs:102:18
  10: nannou::app::Builder<M,E>::run
             at /home/mindtree/programming/rust/nannou/nannou/src/app.rs:484:21
  11: wgpu_teapot_camera::main
             at /home/mindtree/programming/rust/nannou/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs:81:5
  12: core::ops::function::FnOnce::call_once
             at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

The issue seems to be related to the use of the GLSL inverse function within the example's vertex shader:

#version 450

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;

layout(location = 0) out vec3 v_normal;

layout(set = 0, binding = 0) uniform Data {
    mat4 world;
    mat4 view;
    mat4 proj;
} uniforms;

void main() {
    mat4 worldview = uniforms.view * uniforms.world;
    v_normal = transpose(inverse(mat3(worldview))) * normal;
    gl_Position = uniforms.proj * worldview * vec4(position, 1.0);
}

Here's the SPIR-V generated via glslangValidator:

; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 10
; Bound: 62
; Schema: 0
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Vertex %main "main" %v_normal %normal %_ %position
               OpSource GLSL 450
               OpName %main "main"
               OpName %worldview "worldview"
               OpName %Data "Data"
               OpMemberName %Data 0 "world"
               OpMemberName %Data 1 "view"
               OpMemberName %Data 2 "proj"
               OpName %uniforms "uniforms"
               OpName %v_normal "v_normal"
               OpName %normal "normal"
               OpName %gl_PerVertex "gl_PerVertex"
               OpMemberName %gl_PerVertex 0 "gl_Position"
               OpMemberName %gl_PerVertex 1 "gl_PointSize"
               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
               OpName %_ ""
               OpName %position "position"
               OpMemberDecorate %Data 0 ColMajor
               OpMemberDecorate %Data 0 Offset 0
               OpMemberDecorate %Data 0 MatrixStride 16
               OpMemberDecorate %Data 1 ColMajor
               OpMemberDecorate %Data 1 Offset 64
               OpMemberDecorate %Data 1 MatrixStride 16
               OpMemberDecorate %Data 2 ColMajor
               OpMemberDecorate %Data 2 Offset 128
               OpMemberDecorate %Data 2 MatrixStride 16
               OpDecorate %Data Block
               OpDecorate %uniforms DescriptorSet 0
               OpDecorate %uniforms Binding 0
               OpDecorate %v_normal Location 0
               OpDecorate %normal Location 1
               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
               OpDecorate %gl_PerVertex Block
               OpDecorate %position Location 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
      %float = OpTypeFloat 32
    %v4float = OpTypeVector %float 4
%mat4v4float = OpTypeMatrix %v4float 4
%_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
       %Data = OpTypeStruct %mat4v4float %mat4v4float %mat4v4float
%_ptr_Uniform_Data = OpTypePointer Uniform %Data
   %uniforms = OpVariable %_ptr_Uniform_Data Uniform
        %int = OpTypeInt 32 1
      %int_1 = OpConstant %int 1
%_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
      %int_0 = OpConstant %int 0
    %v3float = OpTypeVector %float 3
%_ptr_Output_v3float = OpTypePointer Output %v3float
   %v_normal = OpVariable %_ptr_Output_v3float Output
%mat3v3float = OpTypeMatrix %v3float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
     %normal = OpVariable %_ptr_Input_v3float Input
       %uint = OpTypeInt 32 0
     %uint_1 = OpConstant %uint 1
%_arr_float_uint_1 = OpTypeArray %float %uint_1
%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
          %_ = OpVariable %_ptr_Output_gl_PerVertex Output
      %int_2 = OpConstant %int 2
   %position = OpVariable %_ptr_Input_v3float Input
    %float_1 = OpConstant %float 1
%_ptr_Output_v4float = OpTypePointer Output %v4float
       %main = OpFunction %void None %3
          %5 = OpLabel
  %worldview = OpVariable %_ptr_Function_mat4v4float Function
         %17 = OpAccessChain %_ptr_Uniform_mat4v4float %uniforms %int_1
         %18 = OpLoad %mat4v4float %17
         %20 = OpAccessChain %_ptr_Uniform_mat4v4float %uniforms %int_0
         %21 = OpLoad %mat4v4float %20
         %22 = OpMatrixTimesMatrix %mat4v4float %18 %21
               OpStore %worldview %22
         %26 = OpLoad %mat4v4float %worldview
         %28 = OpCompositeExtract %v4float %26 0
         %29 = OpVectorShuffle %v3float %28 %28 0 1 2
         %30 = OpCompositeExtract %v4float %26 1
         %31 = OpVectorShuffle %v3float %30 %30 0 1 2
         %32 = OpCompositeExtract %v4float %26 2
         %33 = OpVectorShuffle %v3float %32 %32 0 1 2
         %34 = OpCompositeConstruct %mat3v3float %29 %31 %33
         %35 = OpExtInst %mat3v3float %1 MatrixInverse %34
         %36 = OpTranspose %mat3v3float %35
         %39 = OpLoad %v3float %normal
         %40 = OpMatrixTimesVector %v3float %36 %39
               OpStore %v_normal %40
         %48 = OpAccessChain %_ptr_Uniform_mat4v4float %uniforms %int_2
         %49 = OpLoad %mat4v4float %48
         %50 = OpLoad %mat4v4float %worldview
         %51 = OpMatrixTimesMatrix %mat4v4float %49 %50
         %53 = OpLoad %v3float %position
         %55 = OpCompositeExtract %float %53 0
         %56 = OpCompositeExtract %float %53 1
         %57 = OpCompositeExtract %float %53 2
         %58 = OpCompositeConstruct %v4float %55 %56 %57 %float_1
         %59 = OpMatrixTimesVector %v4float %51 %58
         %61 = OpAccessChain %_ptr_Output_v4float %_ %int_0
               OpStore %61 %59
               OpReturn
               OpFunctionEnd

If I remove the inverse call the shader appears to pass validation successfully.

Tested on NixOS, GNOME Wayland.

Possibly related:

gfx-rs/wgpu#4330
#469
gfx-rs/wgpu#4336

@kvark kvark added area: front-end Input formats for conversion help wanted Extra attention is needed kind: feature New feature or request lang: SPIR-V Binary SPIR-V input and output labels May 22, 2021
@JCapucho
Copy link
Collaborator

Tested on e1552fd, the wgsl backend seems to no longer generate shaders which use inverse (since wgsl doesn't support it) and spirv consumes the input well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: front-end Input formats for conversion help wanted Extra attention is needed kind: feature New feature or request lang: SPIR-V Binary SPIR-V input and output
Projects
None yet
Development

No branches or pull requests

3 participants