2

在 Vulkan 标头vulkan.h中有一个结构定义为

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;

我使用以下代码查看每个字段的对齐方式(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;

并得到了这些结果

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

字段之间flags存在surface8 个字节的间隙,即使flags其底层类型为uint32_t. queueFamilyIndexCount字段和也是如此pQueueFamilyIndices。当它们只有 4 个字节宽并且每个其他类型的字段只占用4 个字节时flags,为什么要占用 8 个字节?这些偏移量的内存对齐要求有什么特别之处吗?queueFamilyIndexCountuint32_t

4

2 回答 2

4

VkSurfaceKHR是不可调度的句柄。根据 Vulkan 的定义,它是一个 64 位整数。因此它必须有 8 字节对齐。

在布局结构时,编译器将确保每个成员都获得类型所需的对齐。如果surface紧跟在 之后flags,它将没有 8 字节对齐。因此,编译器在两者之​​间插入 4 个字节的填充。

于 2016-08-09T22:10:48.017 回答
1

所有类型都有大小sizeof(T)和对齐要求alignof(T)。它的实例总是需要在内存中的多个alignof(T).

在结构中,编译器会自动在元素之间插入填充,以便其所有元素都满足这一要求,相对于结构的起始地址(即offsetof值)。这是后续结构元素之间的空白空间。

它还设置alignof整个结构的 ,以便其所有元素在内存中正确对齐。例如在典型的 64 位平台上:

struct A {
    char c;    // sizeof(char) == 1; alignof(char) == 1
    int* ptr;  // sizeof(char) == 8; alignof(char) == 8
}

指针的大小为 8 字节(64 位),并且还有 8 字节的对齐要求。c在此结构中, and之间将有 7 个字节的填充ptr,例如offsetof(A, c) == 0and offsetof(A, ptr) == 8。和alignof(A) == 8。每当A a创建实例时(在堆栈或堆上),&a % 8 == 0等等&(a.ptr) % 8 == 0


这样做是因为一些 CPU 指令(例如 SIMD 向量指令)要求它们的操作数在字边界处对齐,即内存中 8 的倍数(或 4 对 32 位)。如果没有适当的对齐,这些指令不能直接使用,程序会变慢。


在这个例子中VkSurfaceKHRpQueueFamilyIndices是带有 的指针alignof == 8

于 2016-08-09T22:23:40.557 回答