I've just learned from Bug in VC++ 14.0 (2015) compiler? that one shouldn't make assumptions about how a struct's layout will end up in memory. However, I don't understand how it is common practice in a lot of code I've seen. For example, the Vulkan graphics API does the following:
Defines a struct
struct {
glm::mat4 projection;
glm::mat4 model;
glm::vec4 lightPos;
} uboVS;
Then fills up its fields:
uboVS.model = ...
uboVS....
Then just copies over the struct (in host memory) to device memory via memcpy:
uint8_t *pData;
vkMapMemory(device, memory, 0, sizeof(uboVS), 0, (void **)&pData);
memcpy(pData, &uboVS, sizeof(uboVS));
vkUnmapMemory(device, memory);
Then over to the GPU, it defines a UBO to match that struct:
layout (binding = 0) uniform UBO
{
mat4 projection;
mat4 model;
vec4 lightPos;
} ubo;
Then, on the GPU side, ubo will always match uboVS.
Is this the same undefined behavior? Doesn't that code rely on the uboVS struct to be laid out exactly as defined, or for both sides (the compiled C++ code and the compiled SPIR-V shader) to basically generate the same different struct layout? (similar to the first example in https://www.securecoding.cert.org/confluence/display/c/EXP11-C.+Do+not+make+assumptions+regarding+the+layout+of+structures+with+bit-fields)
This question is not specific to Vulkan or graphics APIs, I am curious as to what exactly can one assume and when is it ok to just use a struct as a chunk of memory. I understand struct packing and alignment, but is there more to it?
Thanks
memcpy
on structs (among other things) – Affixation