If we start from AoS layout, AoS structs can be easily initialized as such:
struct Position { float x; float y; };
struct Position positions[] = {
{ .x = 1.f, .y = 2.f },
{ .x = 20.f, .y = 30.f },
{ .x = 150.f, .y = 200.f },
{ .x = 1000.f, .y = 2000.f },
};
The data is always grouped as I want, two values in each AoS struct. In memory it looks like:
| 1.f 2.f | 20.f 30.f | 150.f 200.f | 1000.f 2000.f |
If I swap it to SoA layout, SoA data can be just as easily initialized as such:
float position_x[] = { 1.f, 20.f, 150.f, 1000.f },
float position_y[] = { 2.f, 30.f, 200.f, 2000.f };
This data is always grouped as I want it to be, one value in each SoA array. In memory it looks like:
| 1.f 20.f 150.f 1000.f |
| 2.f 30.f 200.f 2000.f |
When it comes to AoSoA layout, it works if the width is fixed, here [2]:
struct Position { float x[2]; float y[2]; };
struct Position positions[] = {
{ .x = { 1.f, 20.f },
.y = { 2.f, 3.f } },
{ .x = { 150.f, 1000.f },
.y = { 200.f, 2000.f } },
};
The grouping here is 2 pairs [2] of 2 values (x,y) in each AoSoA struct. In memory it looks like:
| 1.f 20.f | 150.f 1000.f |
| 2.f 30.f | 200.f 1000.f |
But if I want to change the width to [4], the previous code leaves the AoSoA structs half 'empty'. A AoSoA width of [4] is meant to be used as 4 pairs [4] of 2 values (x,y), but the previous code will still only give me 2 pairs of 2 values in the lower parts of each AoSoA struct, leaving the upper slots of the subarrays empty (initialized to zero). Like this:
| 1.f 20.f ZERO ZERO | 150.f 1000.f ZERO ZERO |
| 2.f 30.f ZERO ZERO | 200.f 1000.f ZERO ZERO |
If I want my data to stay grouped such that all [4] spaces of the subarrays are filled with my data, I have to rewrite the initializer like this:
struct Position { float x[4]; float y[4]; };
struct Position positions[] = {
{ .x = { 1.f, 20.f, 150.f, 1000.f },
.y = { 2.f, 3.0f, 200.f, 2000.f } },
};
And in memory, it will look like this:
| 1.f 20.f 150.f 1000.f |
| 2.f 30.f 200.f 1000.f |
If I change the width of my AoSoA, zeros start showing up in the data, but I want no zeros. I want the data to stay tightly grouped no matter what the width of the AoSoA is. I'm searching for a way to write my initializer such that the data will stay grouped automatically.
Is there a way that would allow me to have an initializer list for my AoSoA data such that I can change the width of the AoSoA and get the desired behavior?
The rule for partial initializers in the C language is that all remaining objects are initialized as if assigned 0, 0.0 or NULL (depending on type, and recursively). So no, if you declare the array larger than the number of initializers you provide, you will always get the rest assigned with 0.
You might be able to use dynamic memory allocation (e.g. malloc) if you don't know at compile time, how big your arrays will be.