C++ 比较外部API中相同类型的两个结构
所以基本上,我试图比较Vulkan的两个C++ 比较外部API中相同类型的两个结构,c++,struct,c++17,vulkan,struct-member-alignment,C++,Struct,C++17,Vulkan,Struct Member Alignment,所以基本上,我试图比较Vulkan的两个VkPhysicalDeviceFeatures,一个来自我正在查看的VkPhysicalDevice,另一个对应于我实际需要的一组功能。VkPhysicalDeviceFeaturesstruct仅包含VkBool32成员(属于uint32的typedef),但vulkan的每个次要版本都可以添加未知数量的这些功能。我想做的只是将每个结构的成员相互比较,但不是为了相等,更像是逻辑比较。如果物理设备结构中的对应成员为false,但my struct对该成员
VkPhysicalDeviceFeatures
,一个来自我正在查看的VkPhysicalDevice
,另一个对应于我实际需要的一组功能。VkPhysicalDeviceFeatures
struct仅包含VkBool32
成员(属于uint32的typedef
),但vulkan的每个次要版本都可以添加未知数量的这些功能。我想做的只是将每个结构的成员相互比较,但不是为了相等,更像是逻辑比较。如果物理设备结构中的对应成员为false,但my struct对该成员为true,则比较应返回false
我能想到的唯一方法是发布以下内容:
bool具有所需的功能(VkPhysicalDevice物理设备、,
VKP物理设备(所需功能(U功能){
VkPhysicalDeviceFeatures physical_device_features=getSupportedFeatures(物理_device);
std::size\u t struct\u length=sizeof(VkPhysicalDeviceFeatures)/sizeof(VkBool32);
自动物理设备功能\u bool\u ptr=重新解释播放(&P)物理设备功能;
自动所需的\u功能\u bool\u ptr=重新解释\u强制转换(&所需的\u功能);
对于(std::size\u t i=0;i
这是我想要的(虽然有一种方法可以看出哪个特定成员的名字没有通过比较,但是我认为在反射之外是不可能的)但是我不认为C++能保证这样的严格对齐吗?我有没有跨平台的方法来实现这一点
>你的方法有很大的问题,与C++无关,而且更多的与Vulkan有关。具体而言: vulkan的次要版本可以添加未知数量的这些结构 这说明您打算将此类技术应用于VkPhysicalDeviceFeatures2
,以及可能出现在其pNext
链中的任何功能结构。因此,“这些结构的数量未知”
好吧,事情是这样的:VkPhysicalDeviceFeatures2
不仅仅是一堆VkBool
s。它是一个可扩展的Vulkan结构,这意味着它以此类结构常见的sType
和pNext
字段开头。所有1.0版本后的Vulkan设备功能结构也是如此
能够实现您在1.0版后功能结构中所述功能的代码必须能够获取功能结构的整个pNext
链并对其进行测试。为了做到这一点,你必须知道它们是什么。无法通过指向任意数据的指针来查询此数据是否包含X个VkBool
s
要实现这一点,您需要能够将sType
值映射到该结构的大小。因此,它不能自动扩展(并且,不,C++反射不能修复它;它不能知道什么结构:代码>空隙*Pbx< /Coo>指向);这需要一定程度的手动维护
幸运的是,代码可以清楚地指定特定的pNext
链中可以存在哪些结构。因此,您可以编写一个工具来加载XML,查找VkPhysicalDeviceFeatures2
,并处理其pNext
链中出现的所有结构(这部分说起来容易做起来难,因为XML格式只由Khronos自己的工具处理),以找到可用的结构,并生成你需要的C++信息。我相信,用任何脚本语言编写这样的东西都相对容易
但是由于你已经在(准合理)XML中得到了结构定义,而且你得到了这个工具,它将生成一些C++代码…您只需生成实际的比较逻辑即可。也就是说,不必手工编写成员到成员的比较,只需生成成员到成员的比较。您甚至可以获得不匹配的成员名称
如果要处理任意的pNext
-链特性,那么需要某种生成器工具。如果你需要一个生成器工具,就用它来解决整个问题
现在,认识到假设的hasRequiredFeatures
实现的生成代码必须是半复杂的,这一点很重要。如果您允许一个完整的pNext
结构链,那么您需要构建自己相应的等效结构链,用于从Vulkan进行查询。这可不是什么小事
您需要遍历pNext
链,并检查每个结构的sType
字段。但是,当然,pNext
是一个void*
,因此您必须稍微撒谎/欺骗C++的规则才能读取sType
字段。基本上,您必须将void*
重新解释为VkStructureType*
,读取值,将其与您正在使用的所有可能性进行比较,然后从那里开始。你应该跳过任何你不知道的代码>样式> <代码>,这将需要做更多的C++欺骗。
但您使用的是低级API;打破C++的规则只是你在这里必须习惯的事情
对于每个这样的结构,您需要分配一个匹配的结构,适当地填写其sType
,然后将其添加到正在构建的pNext
链中
构建完所有这些之后,就可以进行Vulkan调用、比较、收集数据,最后删除整个结构链
如果您的目标真的是坚持使用VkPhysicalDeviceFeatures而不是可扩展的
bool hasRequiredFeatures(VkPhysicalDevice physical_device,
VkPhysicalDeviceFeatures required_features) {
VkPhysicalDeviceFeatures physical_device_features = getSupportedFeatures(physical_device);
std::size_t struct_length = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
auto physical_device_features_bool_ptr = reinterpret_cast<VkBool32*>(&physical_device_features);
auto required_features_bool_ptr = reinterpret_cast<VkBool32*>(&required_features);
for(std::size_t i = 0; i < struct_length; ++i){
if(physical_device_features_bool_ptr[i] == VK_FALSE && required_features_bool_ptr[i] == VK_TRUE){
return false;
}
}
return true;
}
bool hasRequiredFeatures(VkPhysicalDevice physical_device,
VkPhysicalDeviceFeatures required_features)
{
constexpr auto feature_count = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
using FeatureArray = std::array<VkBool, feature_count>;
auto physical_device_features = getSupportedFeatures(physical_device);
FeatureArray required;
memcpy(&required, &required_features, sizeof(FeatureArray));
FeatureArray retrieved;
memcpy(&retrieved, &physical_device_features, sizeof(FeatureArray));
bool did_mismatch = false;
for(auto it_pair = std::mismatch(required.begin(), required.end(), retrieved.begin());
it_pair.first != required.end();
it_pair = std::mismatch(it_pair.first, required.end(), it_pair.second))
{
did_mismatch = true
auto mismatch_index = it_pair.first - required.begin();
//Do something with mismatch_index
}
return did_mismatch;
}