跳到主要内容

validation layer介绍

validation layer称为验证层。用于校验Vulkan API输入是否有效。

有效输入

有效输入(Valid Usage,简称为VU),在Vulkan Spec中定义为:

提示

为了使应用出现明确定义的行为而必须满足的前提条件。

作为一种显式调用的 API,Vulkan 的主要特点之一是驱动程序不会在检查有效输入上浪费时间。而在 OpenGL 中,驱动程序必须检查输入是否有效,这会增加很多额外开销。Vulkan 中没有等效的 glGetError实现。

vulkan spec在每个函数和结构之后列出了有效性输入。例如,如果检测出VkBindImageMemory中使用了无效的 vkImage,那么validation layer会识别出一个VUID,在VkBindImageMemory下有该VUID的说明。

未定义的行为

当应用程序有无效输入时,结果将是未定义行为。在这种状态下,Vulkan 不保证任何未定义行为的结果

有效输入 ID (VUID)

VUID是每个有效性输入的唯一 ID。根据VUID将很容易地在spec中找到有效性输入的说明。

举个例子,VUID-vkBindImageMemory-memoryOffset-01046)只需将 VUID 在spec html中添加锚点 (vkspec.html#VUID-vkBindImageMemory-memoryOffset-01046),就会直接跳转到该 VUID。

Khronos validation layer

由于 Vulkan 不执行任何错误检查,因此在开发调试时,启用验证层来辅助定位无效行为是非常重要的。

获取validation layer

验证层在不断的更新和改进,因此可以下载最新的源代码自己构建。也可以下载平台预编译好的版本:

分析验证错误消息

验证层会在发生错误时提供尽可能多的信息。以下示例说明了如何解读验证层信息

示例 1 - 隐式的有效输入校验

下面的信息表明触发了隐式有效输入,VUID 末尾没有数字。

Validation Error: [ VUID-vkBindBufferMemory-memory-parameter ] Object 0: handle =
0x20c8650, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0xe9199965 | Invalid
VkDeviceMemory Object 0x60000000006. The Vulkan spec states: memory must be a valid
VkDeviceMemory handle (https://registry.khronos.org/vulkan/specs/1.1-extensions/
html/vkspec.html#VUID-vkBindBufferMemory-memory-parameter)
  • VUID 在消息一开始处展现(VUID-vkBindBufferMemory-memory-parameter),在消息末尾还有VUID在spec中的链接
  • The Vulkan spec states:是从spec引用的VUID。
  • VK_OBJECT_TYPE_INSTANCE:指的是 VkObjectType
  • Invalid VkDeviceMemory Object 0x60000000006:是 Dispatchable Handle,用来定位哪个VkDeviceMemory句柄导致的错误。

示例 2 - 显式的有效输入校验

下面的错误信息表明VkImage对象尝试绑定到 2 个不同的对象VkDeviceMemory对象

Validation Error: [ VUID-vkBindImageMemory-image-01044 ] Object 0: handle =
0x90000000009, name = myTextureMemory, type = VK_OBJECT_TYPE_DEVICE_MEMORY; Object 1:
handle = 0x70000000007, type = VK_OBJECT_TYPE_IMAGE; Object 2: handle = 0x90000000006,
name = myIconMemory, type = VK_OBJECT_TYPE_DEVICE_MEMORY; | MessageID = 0x6f3eac96 |
In vkBindImageMemory(), attempting to bind VkDeviceMemory 0x90000000009[myTextureMemory]
to VkImage 0x70000000007[] which has already been bound to VkDeviceMemory
0x90000000006[myIconMemory]. The Vulkan spec states: image must not already be
backed by a memory object (https://registry.khronos.org/vulkan/specs/1.1-extensions/
html/vkspec.html#VUID-vkBindImageMemory-image-01044)
  • 示例 2 与示例 1 大致相同,不同之处在于附加对象名称(name = myTextureMemory)。这是通过 VK_EXT_debug_util 扩展(扩展使用示例)来实现的。
  • 此错误行为涉及 3 个对象
    • 对象0:名称为myTextureMemoryVkDeviceMemory
    • 对象1:没有名称的VkImage
    • 对象2:名称为myIconMemoryVkDeviceMemory
  • 通过显示的名称,很容易看到:在vkBindImageMemory()中,内存myTextureMemory尝试绑定到一个image,但是该image已绑定到内存myIconMemory

每条错误消息都包含一个固定的日志格式,格式如下:

  • 日志状态(如Error:Warning:等)
  • VUID
  • 涉及的对象数组
    • 索引数组
    • Dispatch Handle 值
    • 可选名称
    • 对象类型
  • 出现错误的函数或结构
  • Layer描述问题的消息
  • spec中完整的有效输入说明
  • 有效输入的链接