gpt4 book ai didi

c++ - 比较来自外部 API 的相同类型的两个结构

转载 作者:行者123 更新时间:2023-12-01 14:48:04 26 4
gpt4 key购买 nike

所以基本上我想比较两个 VkPhysicalDeviceFeatures来自 Vulkan,来自 VkPhysicalDevice我正在查看,另一个对应于我实际需要的一组功能。 VkPhysicalDeviceFeatures结构只有包含 VkBool32成员(它们是 uint32_t 的类型定义),但是 vulkan 的每个次要版本都可以添加未知数量的这些功能。我想做的只是将每个结构的成员相互比较,但不是平等,更多的是逻辑比较。如果物理设备结构中的相应成员为假,但我的结构对该成员为真,则比较应返回假。

我能想到这样做的唯一方法是类似 this answer发布:

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;
}

这就是我想要的(尽管有一种方法可以通过名称查看哪个特定成员未通过比较会很好,但我想如果没有反射是不可能的)但我不认为 C++ 保证像这样的严格对齐?有没有一种跨平台的方式来实现这一目标?

最佳答案

你的方法有一个大问题,它与 C++ 的关系不大,而与 Vulkan 的关系更大。具体来说:

minor version of vulkan can add an unknown number of these structs



这告诉我您打算将此类技术应用于 VkPhysicalDeviceFeatures2 ,以及任何可以出现在其 pNext 中的特征结构体链。因此,“这些结构的数量未知”。

嗯,事情是这样的: VkPhysicalDeviceFeatures2不只是一堆 VkBool s。它是一个可扩展的 Vulkan 结构,这意味着它以 sType 开头。和 pNext此类结构共有的字段。所有 1.0 之后的 Vulkan 设备功能结构也是如此。

可以执行您在 1.0 后功能结构中所说的内容的代码必须能够占用整个 pNext特征结构链并测试它们。为了做到这一点,你必须知道它们是什么。无法仅从指向任意数据的指针查询该数据包含 X 个 VkBool s。

要完成这项工作,您需要能够映射 sType值到该结构的大小。因此,它不能自动扩展(不,C++ 反射不能解决这个问题;它不知道 void *pNext 指向什么结构);这将需要一定程度的手动维护。

幸运的是, Vulkan XML specification description files明确指定哪些结构可以存在于特定 pNext 中链。所以你可以写一个工具来加载XML,找到 VkPhysicalDeviceFeatures2 ,并处理出现在其 pNext 中的所有结构体链(这部分说起来容易做起来难,因为 XML 格式只是为了由 Khronos 自己的工具处理而构建的)来查找哪些结构可用,并生成您需要的 C++ 信息。我相信您可以用任何脚本语言相对轻松地编写这样的东西。

但是由于您已经在(准合理的)XML 中获得了结构定义,并且您已经获得了无论如何都会生成一些 C++ 代码的工具……您可以生成实际的比较逻辑。也就是说,不是手写成员对成员的比较,而是生成成员对成员的比较。您甚至可以获得不匹配的成员名称。

如果您要处理任意 pNext -chain 功能,那么您将需要某种生成器工具。如果您无论如何都需要一个生成器工具,只需使用它来解决整个问题。

现在,重要的是要意识到假设 hasRequiredFeatures 的生成代码。实现将不得不是半复杂的。如果你允许一个完整的 pNext结构链,那么您需要构建自己对应的等效结构链,以用于从 Vulkan 进行查询。这并非微不足道。

您将需要遍历 pNext链接并检查 sType每个结构的字段。但当然, pNextvoid* ,所以你将不得不撒谎/欺骗 C++ 的规则来阅读 sType field 。基本上,你必须 reinterpret_cast void*VkStructureType* ,读取值,将其与您正在使用的所有可能性进行比较,然后从那里继续。您应该跳过任何 sType你不知道的,这将需要做更多的 C++ 技巧。

但是您使用的是低级 API;打破 C++ 的规则只是你在这里必须习惯的事情。

对于每个这样的结构体,你需要分配一个匹配的结构体,填写它的 sType适本地,然后将其添加到 pNext您正在构建的链。

构建完所有这些之后,您就可以进行 Vulkan 调用、进行比较、收集数据,最后删除整个结构链。

如果您的目标真的只是坚持 VkPhysicalDeviceFeatures而不是可扩展的结构,而您只需要一种 C++ 可移植的方式来比较此类结构,那么只需 memcpy他们变成了 VkBool数组并比较两个数组是否不匹配。这两种类型都可以简单地复制,因此从表面上看,这样做并不是非法的。

此代码尚未编译或测试。
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;
}

关于c++ - 比较来自外部 API 的相同类型的两个结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61417998/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com