I have recently come across an issue porting some C code to Odin, specifically copying data from a struct into a UniformBuffer for the Vulkan API.
Original C code:
typedef struct {
float t;
mat4 mvps[1000];
} UniformBufferObject;
// SNIP
memcpy(uniform_buffers_mapped[current_frame], &ubo, sizeof(ubo));
printf("\nHEX DUMP:\n");
for (int i=0; i<256; i++) {
printf("%02X", ((unsigned char*)uniform_buffers_mapped[current_frame])[i]);
if (i % 16 == 15) {
printf("\n");
}
else if (i % 4 == 3) {
printf(" ");
}
}
printf("\n");
Result:
HEX DUMP:
B1D3AA40 00000000 00000000 00000000
0000803F 00000000 00000000 00000000
00000000 0000803F 00000000 00000000
00000000 00000000 0000803F 00000000
00000000 00000000 00000000 0000803F
0000803F 00000000 00000000 00000000
00000000 0000803F 00000000 00000000
00000000 00000000 0000803F 00000000
00000000 00000000 00000000 0000803F
Odin Version:
UniformBufferObject :: struct {
t: f32,
mvps: [1000]glsl.mat4,
}
// SNIP
intrinsics.mem_copy(uniform_buffers_mapped[current_frame], &ubo, size_of(ubo))
fmt.println("\nHEX DUMP:")
bytes := slice.bytes_from_ptr(uniform_buffers_mapped[current_frame], size_of(ubo))
for i := 0; i < 265; i += 1 {
if i >= len(bytes) {
fmt.printfln("Broke at %d", i)
break
}
v := bytes[i]
fmt.printf("%02X", v)
if i % 16 == 15 {
fmt.print("\n")
} else if i % 4 == 3 {
fmt.print(" ")
}
}
fmt.print("\n")
Output:
HEX DUMP:
4685853F 00000000 00000000 00000000
00000000 00000000 00000000 00000000
0000803F 00000000 00000000 00000000
00000000 0000803F 00000000 00000000
00000000 00000000 0000803F 00000000
00000000 00000000 00000000 0000803F
0000803F 00000000 00000000 00000000
00000000 0000803F 00000000 00000000
00000000 00000000 0000803F 00000000
00000000 00000000 00000000 0000803F
Notice the row of zeroes on the second line in the above.
Fixed Version
UniformBufferObject :: struct #packed {
t: f32,
// Alignment issues...
_: f32,
_: f32,
_: f32,
mvps: [1000]glsl.mat4,
}
On this page: https://odin-lang.org/news/binding-to-c/#structs it says:
Odin structs with fields that are the same size as their C equivalents, (see
core:c
) Odin structs have the same layout as the equivalent C struct.
But when I ported the code, the alignment seems to be different (16 bytes vs 32). Is this:
- Something I’m doing wrong?
- A bug in the compiler?
- The documentation is not accurate?
- Something else entirely?