gfx-rs / wgpu

A cross-platform, safe, pure-Rust graphics API.
https://wgpu.rs
Apache License 2.0
12.12k stars 880 forks source link

[glsl-in] Struct layout handling is overly simplistic #4475

Open fintelia opened 1 year ago

fintelia commented 1 year ago

Because naga assumes that structs have layout std140, this shader:

#version 460 core

struct A {
    float x[2];
};

layout(std430, set = 0, binding = 0) buffer DataBuffer {
    A a;
};

void main() {
    A b = a;
}

Produces this error:

error: 
   ┌─ shader.vert:11:1
   │
11 │ void main() {
   │ ^^^^^^^^^^^ naga::Function [1]
12 │     A b = a;
   │       ^^^^^
   │       │   │
   │       │   naga::Expression [3]
   │       naga::Expression [4]

Function [1] 'main' is invalid: 
    Store of [3] into [4] doesn't have matching types
fintelia commented 1 year ago

Note that it isn't enough to infer whether std140 or std430 layouts are needed for a given local variable, GLSL actually allows the layout to vary based on conditionals...

#version 460 core

struct A {
    float b[2];
};

layout(std140, set = 0, binding = 0) uniform Data {
    A a;
    bool flag;
};

layout(std430, set = 0, binding = 1) buffer DataBuffer {
    A b;
};

void main() {
    A c = flag ? a : b;
}
teoxoy commented 1 year ago

The solution here is to generate the structs with the correct layout as needed, unfortunately this also requires auto casting between the different layouts in some situations (for example a function picked to accept std430 structs and you pass it a std140 struct).

quoting @JCapucho in https://github.com/gfx-rs/naga/pull/2212#issuecomment-1386072710