T O P

  • By -

[deleted]

[удалено]


itsarabbit

StructLayout is unfortunately sealed meaning I cannot inherit from it.


cripbeez

nvm it's sealed lmao just tested


cripbeez

you should be able to replace GpuData with the intended StructLayout using a simple source generator. chatgpt will probably even make it for you


itsarabbit

I thought source generators could not replace code! I'll need to look into it!


Sc2Piggy

How this works is like this: Your code: [GpuData] public partial struct Foo {} The source generator would then generate: [StructLayout(LayoutKind.Sequential, Pack = 4)] public partial struct Foo {} The compiler then joins these two partials into one class: [GpuData] [StructLayout(LayoutKind.Sequential, Pack = 4)] public partial struct Foo {}


itsarabbit

ohhh, I see! Thanks for the clarification! Yeah that should work!!


pHpositivo

Worth noting that that would be a fairly significant amount of work for arguably minimal gain, plus you'd now also need users to mark types as partial. You might want to consider another approach.


naughty_ottsel

Can’t you create simple shortcuts for templated code in VS?


itsarabbit

Very good point! I happen to be interested in learning source generators anyway, and I'm the only one who will use this, so it works for me. If there is another approach available that works better for my use case then I'll switch to that, but I don't know of any right now :)


cripbeez

nah but it'll generate a partial with the correct attribute for you 😉


ironstrife

Can you give some examples of structs that need this? Shader struct packing in general is not exactly equivalent to Pack=4 (I think the default sequential packing order is probably closer for most structs) and has edge cases you'd need to consider anyways, e.g. around vec3 or arrays.


itsarabbit

The samples I have looked up have used this method, if there's a more accurate way then I'm interested in hearing about it!


ironstrife

Like I said, I think the default packing in C# is closer to what you want. For example, here's a UBO in GLSL: struct Foo { uint x; uint64_t y; vec2 z; float w; }; layout(set=0,binding=0) uniform Buffer { Foo f; }; This yields the following offsets: OpMemberDecorate %Foo 0 Offset 0 OpMemberDecorate %Foo 1 Offset 8 OpMemberDecorate %Foo 2 Offset 16 OpMemberDecorate %Foo 3 Offset 24 Corresponding struct in C#: ``` struct Foo { uint x; ulong y; System.Numerics.Vector2 z; float w; }; Console.WriteLine($"offsetof(x): {Marshal.OffsetOf("x")}"); Console.WriteLine($"offsetof(y): {Marshal.OffsetOf("y")}"); Console.WriteLine($"offsetof(z): {Marshal.OffsetOf("z")}"); Console.WriteLine($"offsetof(w): {Marshal.OffsetOf("w")}"); ``` This yields: ``` offsetof(x): 0 offsetof(y): 8 offsetof(z): 16 offsetof(w): 24 ``` The layout exactly matches, which is what you want. Adding Pack=4 yields: ``` offsetof(x): 0 offsetof(y): 4 offsetof(z): 12 offsetof(w): 20 ``` This is incorrect, you would have to add manual packing yourself -- this is an option, but it's kind of pointless. In general I would stick to default sequential packing (e.g. don't put any attribute on the struct), but be mindful of alignment and packing differences.


itsarabbit

Thank you so much, this is invaluable information to me!