校验层是什么?
Vulkan API的设计是紧紧围绕最小化驱动程序开销进行的,所以,默认情况下,Vulkan API提供的错误检查功能非常有限。很多很基本的错误都没有被Vulkan显式地处理,遇到错误程序会直接崩溃或者发生未被明确定义的行为。Vukan需要我们显式地定义每一个操作,所以就很容易在使用过程中产生一些小错误,比如使用了一个新的GPU特性,却忘记在逻辑设备创建时请求这一特性。
然而,这并不意味着我们不能将错误检查加入API调用。Vulkan引入了校验层来优雅地解决这个问题。校验层是一个可选的可以用来在Vulkan API函数调用上进行附加操作的组件。校验层常被用来做下面的工作:
-
检测参数值是否合法
-
追踪对象的创建和清除操作,发现资源泄漏问题
-
追踪调用来自的线程,检测是否线程安全。
-
将API调用和调用的参数写入日志
-
追踪API调用进行分析和回放
下面的代码演示了Vulkan的校验层是如何工作的:
VkResult vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* instance) {
if (pCreateInfo == nullptr || instance == nullptr) {
log("Null pointer passed to required parameter!");
return VK_ERROR_INITIALIZATION_FAILED;
}
return real_vkCreateInstance(pCreateInfo, pAllocator, instance);
}
校验层可以被自由堆叠包含任何读者感兴趣的调试功能。我们可以在开发时使用校验层,然后在发布应用程序时,禁用校验层来提高程序的运行表现。
Vulkan库本身并没有提供任何内建的校验层,但LunarG的Vulkan SDK提供了一个非常不错的校验层实现。读者可以使用这个校验层实现来保证自己的应用程序在不同的驱动程序下能够尽可能得表现一致,而不是依赖于某个驱动程序的未定义行为。
校验层只能用于安装了它们的系统,比如,LunarG的校验层只可以在安装了Vulkan SDK的PC上使用。
Vulkan可以使用两种不同类型的校验层:实例校验层和设备校验层。实例校验层只检查和全局Vulkan对象相关的调用,比如Vulkan实例。设备校验层只检查和特定GPU相关的调用。设备校验层现在已经不推荐使用,也就是说,应该使用实例校验层来检测所有的Vulkan调用。Vulkan规范文档为了兼容性仍推荐启用设备校验层。在本教程,为了简便,我们为实例和设备指定相同的校验层。