Vulkan在其函数中广泛使用结构以传递大量参数,并通过将结构类型和“ next”指针用作每个结构的前两个成员,通过将这些结构菊花链在一起来实现扩展。例如,使用以下功能:
VkResult vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance);
说明VkInstanceCreateInfo
:
typedef struct VkInstanceCreateInfo {
VkStructureType sType;
const void* pNext;
VkInstanceCreateFlags flags;
const VkApplicationInfo* pApplicationInfo;
uint32_t enabledLayerCount;
const char* const* ppEnabledLayerNames;
uint32_t enabledExtensionCount;
const char* const* ppEnabledExtensionNames;
令我着迷的是,据我所知,结构成员的包装是由编译器决定的(顺序除外)。据我所知,这与基于COM的API形成对比,后者不存在依赖于编译器的问题。我一直在浏览Vulkan标头,期望找到特定于编译器的对齐方式编译指示/语句,但是没有什么引人注目的。
查看诸如Wikipedia数据结构对齐之类的页面,这将表明常见的知名编译器在x86上遵循某些规则:
该结构的每个成员的类型通常具有默认对齐方式,这意味着除非程序员另有要求,否则它将在预定边界上对齐。对于32位x86的编译器,以下典型对齐方式适用于Microsoft(Visual C ++),Borland / CodeGear(C ++ Builder),Digital Mars(DMC)和GNU(GCC)的编译器。
但是使用像“通常”和“典型”这样的狡猾的单词对我来说并不可靠。这样的答案中的一段更引人注目:
重要说明:C和C ++标准均声明结构对齐方式是实现定义的。因此,每个编译器可能选择不同地对齐数据,从而导致不同且不兼容的数据布局。因此,在处理将由不同编译器使用的库时,了解编译器如何对齐数据非常重要。一些编译器具有命令行设置和/或特殊的#pragma语句以更改结构对齐设置。
如果我使用的是由一个编译器使用一组规则编译的Vulkan SDK,并且正在使用另一个编译器编写客户端应用程序,那么是否存在对齐问题的可能性?我在这里想念什么?
如果我使用的是由一个编译器使用一组规则编译的Vulkan SDK,并且正在使用另一个编译器编写客户端应用程序,那么是否存在对齐问题的可能性?
我可以编写由GCC编译的程序,该程序可以(动态或其他方式)链接到Clang编译的程序。或Visual Studio在其支持的平台上。或任何其他编译器。从我的编译器中,我可以调用将各种结构传递给目标编译器下编译的代码的函数。
而且有效。为什么?
因为在这些库/ SO / DLL /可执行文件的边界上发生的事情的行为不是由编译器定义的;它由平台定义。库间通信受该平台上所有编译器都同意的通信协议的约束。这是使OS系统调用甚至可能尚未编译的代码的方式。这是因为源和目标已就调用约定和应用程序二进制接口(ABI)达成共识。
系统的ABI定义了结构布局的外观。如果编译器正在编译试图跨ABI边界传递结构的代码,则编译器必须确保其生成的代码的结构布局符合ABI。对于编译器确定不会跨ABI边界过渡的类型,它可以执行任何所需的操作,但是一般而言,它仍将使用ABI的约定。
Linux系统使用Itanium ABI。Windows有其自己的ABI。每个平台都有一个ABI,这就是编译到该平台的编译器所遵循的。
因此,出现布局问题的唯一可能性是,如果要将这些结构发送到另一个操作系统。考虑到Vulkan是低级API,这可能不是一个好主意。当然,这不是Vulkan的预期用例。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句