Search code examples
c++cstructmemory-alignmentstruct-member-alignment

What's the reason for this struct's alignment?


In the Vulkan header vulkan.h there is a struct defined as

typedef struct VkSwapchainCreateInfoKHR {
    VkStructureType                  sType;
    const void*                      pNext;
    VkSwapchainCreateFlagsKHR        flags;
    VkSurfaceKHR                     surface;
    uint32_t                         minImageCount;
    VkFormat                         imageFormat;
    VkColorSpaceKHR                  imageColorSpace;
    VkExtent2D                       imageExtent;
    uint32_t                         imageArrayLayers;
    VkImageUsageFlags                imageUsage;
    VkSharingMode                    imageSharingMode;
    uint32_t                         queueFamilyIndexCount;
    const uint32_t*                  pQueueFamilyIndices;
    VkSurfaceTransformFlagBitsKHR    preTransform;
    VkCompositeAlphaFlagBitsKHR      compositeAlpha;
    VkPresentModeKHR                 presentMode;
    VkBool32                         clipped;
    VkSwapchainKHR                   oldSwapchain;
} VkSwapchainCreateInfoKHR;

I've used the following code to see each field's alignment (Visual Studio 2015)

    std::cout <<
        "sType: " << offsetof(VkSwapchainCreateInfoKHR, sType) << std::endl <<
        "pNext: " << offsetof(VkSwapchainCreateInfoKHR, pNext) << std::endl <<
        "flags: " << offsetof(VkSwapchainCreateInfoKHR, flags) << std::endl <<
        "surface: " << offsetof(VkSwapchainCreateInfoKHR, surface) << std::endl <<
        "minImageCount: " << offsetof(VkSwapchainCreateInfoKHR, minImageCount) << std::endl <<
        "imageFormat: " << offsetof(VkSwapchainCreateInfoKHR, imageFormat) << std::endl <<
        "imageColorSpace: " << offsetof(VkSwapchainCreateInfoKHR, imageColorSpace) << std::endl <<
        "imageExtent: " << offsetof(VkSwapchainCreateInfoKHR, imageExtent) << std::endl <<
        "imageArrayLayers: " << offsetof(VkSwapchainCreateInfoKHR, imageArrayLayers) << std::endl <<
        "imageUsage: " << offsetof(VkSwapchainCreateInfoKHR, imageUsage) << std::endl <<
        "imageSharingMode: " << offsetof(VkSwapchainCreateInfoKHR, imageSharingMode) << std::endl <<
        "queueFamilyIndexCount: " << offsetof(VkSwapchainCreateInfoKHR, queueFamilyIndexCount) << std::endl <<
        "pQueueFamilyIndices: " << offsetof(VkSwapchainCreateInfoKHR, pQueueFamilyIndices) << std::endl <<
        "preTransform: " << offsetof(VkSwapchainCreateInfoKHR, preTransform) << std::endl <<
        "compositeAlpha: " << offsetof(VkSwapchainCreateInfoKHR, compositeAlpha) << std::endl <<
        "presentMode: " << offsetof(VkSwapchainCreateInfoKHR, presentMode) << std::endl <<
        "clipped: " << offsetof(VkSwapchainCreateInfoKHR, clipped) << std::endl <<
        "oldSwapchain: " << offsetof(VkSwapchainCreateInfoKHR, oldSwapchain) << std::endl <<
        std::endl;

And got these results

sType: 0
pNext: 8
flags: 16
surface: 24
minImageCount: 32
imageFormat: 36
imageColorSpace: 40
imageExtent: 44
imageArrayLayers: 52
imageUsageFlags: 56
imageSharingMode: 60
queueFamilyIndexCount: 64
pQueueFamilyIndices: 72
preTransform: 80
compositeAlpha: 84
presentMode: 88
clipped: 92
oldSwapchain: 96

Between the fields flags and surface there is an 8 byte gap, even though flags has an underlying type of uint32_t. The same is true with the fields queueFamilyIndexCount and pQueueFamilyIndices. Why do flags and queueFamilyIndexCount take up 8 bytes when they are only 4 bytes wide and every other field of type uint32_t takes up only 4 bytes? Is there something special about the memory alignment requirements at those offsets?


Solution

  • VkSurfaceKHR is a non-dispatchable handle. Which, by Vulkan's definitions, is a 64-bit integer. And therefore it must have 8-byte alignment.

    When structures are being laid out, the compiler will ensure that each member gets the alignment that the type requires. If surface had come immediately after flags, it would not have 8-byte alignment. Thus, the compiler inserts 4 bytes of padding between the two.