shader-slang / slang

Making it easier to work with shaders
MIT License
1.98k stars 168 forks source link

Layout for structs with a single field #928

Open tangent-vector opened 5 years ago

tangent-vector commented 5 years ago

We already special-case the layout for a struct type with no fields, so that they don't affect layout at all (they are treated as consuming zero bytes, with one-byte alignment). This isn't a match for standard HLSL rules, but empty struct types are uncommon in HLSL, but can become common in Slang once users use struct types to encapsulate shading features (which might have resource parameters, but no uniform/ordinary data).

An additional special case we might want to consider is when a struct type has a single field:

struct MyData { int val; }
cbuffer C { int x; MyData y; }

It is a bit silly that C.y.val gets an offset of 16 bytes, instead of 4, just because it is wrapped in a struct. If we added an IR pass that rewrites all single-field structs into their field type, then we could emit code that gives a more compact layout in cases like this.

One benefit of handling single-field struct types this way is that we could emit IR for enum types as struct types with a single field for their "tag." This would scale more naturally to eventually allowing enum types to be used for tagged unions as in Rust and Swift.

cshenton commented 1 year ago

Is this still the case on the current compiler?

I would like to be able to define a generic MyBuffer<T> type, which internally just contains a uint handle; member which is used to index into a RWByteAddressBuffer bufs[]; bindless buffer heap.

If the alignment of that struct is 16 and not 4, that would mean I can't neatly have a push_constants struct that uses the type directly in the fields like:

struct PushConstants {
    MyBuffer<float> buffer0;
    MyBuffer<float2> buffer1;
};

With an associated [[vk::push_constant]] PushConstants constants;

cshenton commented 1 year ago

So it looks like this is the case on the current compiler, and is causing these push constants to be laid out incorrectly. Instead I have to assign them to int and manually construct the user-type in the shader which is not very ergonomic. Is there an annotation I can user on the user side to force this alignment to be correct?

natduca commented 9 months ago

Language cleanup, Q3

csyonghe commented 1 month ago

@cshenton I think you can use -fvk-use-scalar-layout to get rid of the additional alignment.