我应该什么时候使用 VULKAN_HPP_NO_EXCEPTIONS?

When should I use VULKAN_HPP_NO_EXCEPTIONS?

此问题与 Vulkan-Hpp(官方 Vulkan C++ 绑定)中的异常处理有关。

我使用 Vulkan-Hpp 编写了一个小型应用程序,但没有 VULKAN_HPP_NO_EXCEPTIONS 定义(并且带有异常处理程序)。但是在遇到这个 Whosebug 问题 (Are Exceptions in C++ really slow) 之后,我开始担心在那里使用异常的惩罚。然后我发现了定义 VULKAN_HPP_NO_EXCEPTIONS,但它完全改变了所有可能引发异常的调用的语法(因为不同的 return 值):这意味着,必须在开始实施之前决定使用或不使用 VULKAN_HPP_NO_EXCEPTIONS(即它们无法针对 "Debug" 配置启用,也无法针对 "Release" 配置轻松禁用)。

If exception handling is disabled by defining VULKAN_HPP_NO_EXCEPTIONS ResultValue<SomeType>::type is a struct which contains the return value and the error code in the fields result and value.

Source

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 以及在什么情况下我应该使用 VULKAN_HPP_NO_EXCEPTIONS不应该?

我认为它背后一定有一些技术原理,而不仅仅是个人 taste/opinion。

可以禁用异常的主要原因是,许多针对各种平台的游戏开发人员在编译器级别关闭了异常处理。在某些平台上,不支持异常处理。这些平台仍然需要一种合理的方式来处理错误,而这需要不同的 API.

异常一直是 C++ 中争论不休的话题,而且可能永远如此。虽然 C++ 程序员同意异常只应在特殊情况下使用,但 "exceptional circumstances" 和 "expected behavior" 之间的界线最终在旁观者的眼中。

就我个人而言,我认为 Vulkan 错误是 "exceptional circumstances"。设备丢失和 OOM 错误不是您经常期望发生的事情。另外,您对他们的回应很可能是非本地的;调用堆栈中更高层的代码将是实际处理它的代码。

此外,许多出错的函数 不是 在性能关键 Vulkan 代码(vkCmd* 等)中经常遇到的函数。毕竟,使用错误应该由验证层处理,并且在运行时应该是不可能的。通常会为对象 creation/destruction 和分配提供错误,这不是您在构建命令缓冲区期间所做的事情。

最有可能在性能关键代码中发现的错误函数是 vkAllocateDescriptorSets。虽然它可能会出错,但只能出于内存碎片的原因这样做。标准实际上需要这个:

Any returned error other than VK_ERROR_OUT_OF_POOL_MEMORY_KHR or VK_ERROR_FRAGMENTED_POOL does not imply its usual meaning: applications should assume that the allocation failed due to fragmentation, and create a new descriptor pool.

如果您对输入数据有严格的控制,碎片化通常是可以避免的。有了这样的控制,您就可以确保从描述符池中分配时永远不会出错。

vkBegin/EndCommandBuffer 可能会出错,但仅限于 OOM 原因。这通常意味着您几乎无法恢复,因此性能无关紧要。

给您带来需要操作的严重运行时错误的命令通常是设备命令。而且您不会在渲染过程中发出此类命令; vkQueueSubmit 是一个例外,它在渲染的 结束 处(或开始;无论你想看到它)。

这可能就是为什么 VK_HPP 是默认设置的原因。