什么时候应该使用VULKAN_HPP_NO_EXCEPTIONS?

4
这个问题涉及到在Vulkan-Hpp(官方的Vulkan C++绑定)中的异常处理。
我使用了带有异常处理程序的Vulkan-Hpp编写了一个小应用程序,但在遇到这个stackoverflow问题之后(C++中的异常真的很慢吗?),我开始担心在那里使用异常的惩罚。然后我发现了定义VULKAN_HPP_NO_EXCEPTIONS,但它会完全改变所有可能引发异常的调用的语法(因为返回值不同):这意味着,在开始实现之前必须决定是否使用VULKAN_HPP_NO_EXCEPTIONS(即它们不能轻松地在“Debug”配置中启用,在“Release”配置中禁用)。

如果通过定义VULKAN_HPP_NO_EXCEPTIONS来禁用异常处理,ResultValue<SomeType>::type是一个包含返回值和错误代码的结构体,分别存储在result和value字段中。

来源

surface = instance.createWin32SurfaceKHR(surfaceCreateInfo);

变成

vk::ResultValue<vk::SurfaceKHR> surfaceResult = instance.createWin32SurfaceKHR(surfaceCreateInfo);
if (surfaceResult.result == vk::Result::eSuccess) {
  surface = surfaceResult.value;
}

鉴于在开发的后期更改关于VULKAN_HPP_NO_EXCEPTIONS策略并不容易,我想知道在哪些情况下应该为我的项目使用VULKAN_HPP_NO_EXCEPTIONS,在哪些情况下不应该使用?

我认为除了个人品味/意见之外,必须有一些技术理由。


2
“我认为这背后肯定存在一些技术方面的理由,而不仅仅是个人口味或看法。”你为什么认为会有“除了个人口味或看法之外的其他原因”呢? - Nicol Bolas
@NicolBolas 我只是这样假设的,因为为了这个目的支持两个不同的API对我来说似乎很奇怪。非常感谢您详细的回答! - Constantin
1个回答

7
异常处理可以被禁用的主要原因是许多游戏开发者在编译器级别关闭异常处理。在某些平台上,异常处理根本不被支持。这些平台仍然需要合理的方法来处理错误,这就需要不同的API。
异常处理一直是C++中备受争议的话题,而且可能会一直如此。虽然C++程序员会同意只有在特殊情况下才应该使用异常,但“特殊情况”和“预期行为”的界限最终取决于观察者的眼中钉。
个人而言,我认为Vulkan错误属于“特殊情况”。设备丢失和OOM错误不是经常发生的事情。此外,你对它们的响应很可能是非局部的;调用堆栈中更高层的代码将实际处理它。
此外,许多出现错误的函数并不是在性能关键的Vulkan代码(vkCmd*等)中经常遇到的函数。毕竟,使用错误应该由验证层处理,并且在运行时应该是不可能的。通常会在对象创建/销毁和分配方面给出错误,这些都不是在构建命令缓冲区时做的事情。
最有可能在性能关键代码中发现错误的函数是vkAllocateDescriptorSets。虽然它可能会出错,但只有在内存碎片化的情况下才能这样做。标准实际上要求这样做:

任何返回的错误除了VK_ERROR_OUT_OF_POOL_MEMORY_KHRVK_ERROR_FRAGMENTED_POOL之外都不意味着其通常的含义:应用程序应该假定由于碎片而分配失败,并创建新的描述符池。

如果你对输入数据有牢固的控制,那么碎片化通常是可以避免的。在这种情况下,你可以确保从描述符池中分配时永远不会出现错误。 vkBegin/EndCommandBuffer可能会出错,但只有在OOM的情况下才会如此。这通常意味着你几乎无法恢复,因此性能并不重要。
给你严重的需要采取行动的运行时错误的命令通常是设备命令。而你不会在渲染过程中发出这样的命令;vkQueueSubmit是唯一的例外,而且是在渲染结束时(或开始时)。
这可能是为什么VK_HPP中默认抛出异常的原因。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接