在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
和surface
之间存在8个字节的间隔,即使flags
的基础类型为uint32_t
。字段queueFamilyIndexCount
和pQueueFamilyIndices
也是如此。为什么flags
和queueFamilyIndexCount
占用8个字节,只有4个字节宽,而uint32_t
类型的每个其他字段只占用4个字节?那些偏移的存储器对齐要求有什么特别之处吗?
答案 0 :(得分:4)
VkSurfaceKHR
是一个不可分派的句柄。根据Vulkan的定义,这是一个64位整数。因此它必须具有8字节对齐。
当布局结构时,编译器将确保每个成员获得该类型所需的对齐。如果surface
在flags
之后立即出现,则不会有8字节对齐。因此,编译器在两者之间插入4个字节的填充。
答案 1 :(得分:1)
所有类型的大小均为sizeof(T)
,对齐要求为alignof(T)
。它的实例总是需要在alignof(T)
的多个地址的内存中布局。
在结构中,编译器会自动在元素之间插入 padding ,以便相对于结构的起始地址(即offsetof
满足其所有元素的此要求。值)。这是后续struct元素之间的空白区域。
它还设置整个结构的alignof
,以便其所有元素在内存中正确对齐。例如,在典型的64位平台上:
struct A {
char c; // sizeof(char) == 1; alignof(char) == 1
int* ptr; // sizeof(char) == 8; alignof(char) == 8
}
指针的大小为8字节(64位),并且对齐要求为8字节。在此结构中,c
和ptr
之间将有7个字节的填充,例如offsetof(A, c) == 0
和offsetof(A, ptr) == 8
。并alignof(A) == 8
。每当创建实例A a
时(在堆栈上或堆上),&a % 8 == 0
,以及&(a.ptr) % 8 == 0
。
这是因为一些CPU指令(例如SIMD向量指令)要求它们的操作数在字边界处对齐,即在存储器中的8的倍数(或32位的4)。如果没有正确的对齐方式,则无法直接使用这些指令,程序会变慢。
在此示例中,VkSurfaceKHR
和pQueueFamilyIndices
是alignof == 8
的指针。