VK_KHR_maintenance7

此提案详细说明并解决了 VK_KHR_maintenance7 扩展所解决的问题。

1. 问题陈述

随着时间的推移,一些次要功能,没有一个值得单独创建一个完整的扩展,需要创建一个维护扩展。

以下是本提案中考虑的问题列表

  • 在渲染时,要求深度和模板方面之间没有访问重叠

  • 在通过分层实现提供 Vulkan 实现的环境中,添加一种查询有关底层设备信息的方法。

  • VK_RENDERING_CONTENTS_INLINE_BIT_EXTVK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT 提升为 KHR

  • 添加一个限制,以报告管道布局中可以包含的最大动态 uniform 缓冲区和动态存储缓冲区的总数。

  • 添加一种方法,用于确定实现是否在 32 位时间戳查询溢出时环绕或饱和

  • 要求 FSR 附件访问与其它图像访问保持一致以提高稳健性。或许还需要确保数组访问是稳健的 - 不仅仅是宽度/高度。

1.1. 分离深度/模板访问

一些实现将对混合深度/模板附件的单个方面的写入视为对两个方面的写入,而一些实现将这些写入视为单独的单方面写入。应用程序必须了解实现正在使用哪种行为。

1.2. 查询底层分层实现的属性

当 Vulkan 驱动程序由分层实现提供时,可能需要查询底层设备的详细信息。例如,在 Mesa/Venus 上运行时,驱动程序 ID 返回为 VK_DRIVER_ID_MESA_VENUS,但可能需要知道底层真正的驱动程序是什么。

1.3. 渲染通道中混合内联和二级命令缓冲区记录

Vulkan 1.0 要求渲染通道子通道的内容要么完全内联,要么在单个二级命令缓冲区中提供。在某些情况下,能够混合在同一渲染通道子通道内部的内联和二级命令缓冲区,或执行多个二级命令缓冲区可能是有益的。

1.4. 放宽动态 Uniform/存储缓冲区的计数

管线布局中可以包含的最大动态 uniform 缓冲区和动态存储缓冲区的数量是分别报告的。虽然一些实现以相同的方式处理 uniform 缓冲区和存储缓冲区的动态偏移,但报告总数以及最大动态 uniform 和存储缓冲区数量可以放宽限制,更准确地暴露设备功能。

1.5. 片元着色率附件大小不匹配

DirectX 12 可变着色率功能允许应用程序指定一个着色率图像,该图像比为所有渲染的纹素提供着色率所需的图像要小。当在着色率图像覆盖区域之外渲染片段时,将返回默认值,这与图像通常的超出边界值一致,并保证了这一点。

然而,在 Vulkan 中,目前这被完全禁止,使得依赖此功能的应用程序或模拟层难以保证可移植性。

2. 问题详情和解决方案空间

2.1. 分离的深度/模板访问

一个属性,指示对深度/模板附件的单方面写入是否会导致对两个方面都写入。

2.2. 查询底层分层实现的属性

包含一组新的结构体,可以通过链接到 VkPhysicalDeviceProperties2 时使用 VkPhysicalDeviceLayeredApiPropertiesListKHR 访问。

2.3. 渲染通道中混合内联和二级命令缓冲区记录

VK_EXT_nested_command_buffer 扩展中的标志提供了此功能,并被提升到此扩展中。

2.4. 放宽动态 Uniform/Storage 缓冲区的计数

添加了一个限制,指示可以在管线布局中包含的最大动态 uniform 缓冲区和存储缓冲区的总数。

2.5. 片元着色率附件大小不匹配

在基本层面上,第一个障碍是允许应用程序指定对于渲染区域来说太小的片元着色率附件,并赋予其某种明确的行为。第二个挑战是确保所有实现都返回预期值。

这可以通过使用新的语言来描述这些查找的具体细节来实现,但值得注意的是,具有鲁棒访问的图像读取已经具有所需的行为。因此,此提案将片元着色率附件读取重新定义为常规图像读取,并保证当启用 VkPhysicalDeviceRobustness2FeaturesEXT::robustImageAccess2 功能时,这些值与 DirectX 12 的保证相匹配。

2.6. 确定 32 位查询溢出行为

之前,当 32 位无符号整数查询结果溢出时,实现可能会环绕或饱和。然而,MESA Virtio-GPU Venus 分层实现需要确定的行为,才能基于 vkCmdCopyQueryPoolResults 以高效的方式实现 vkGetQueryPoolResults。这可以通过要求对于无符号整数查询,32 位结果值必须等于等效 64 位结果值的最低 32 位来解决。

3. 提案

3.1. 新功能

公开以下功能

typedef struct VkPhysicalDeviceMaintenance7FeaturesKHR {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           maintenance7;
} VkPhysicalDeviceMaintenance7FeaturesKHR;
  • maintenance7 功能指示对 VK_KHR_maintenance7 扩展的支持。

3.2. 新属性

此扩展添加以下属性

typedef struct VkPhysicalDeviceMaintenance7PropertiesKHR {
    VkStructureType                     sType;
    void*                               pNext;
    VkBool32                            robustFragmentShadingRateAttachmentAccess;
    VkBool32                            separateDepthStencilAttachmentAccess;
    uint32_t                            maxDescriptorSetTotalUniformBuffersDynamic;
    uint32_t                            maxDescriptorSetTotalStorageBuffersDynamic;
    uint32_t                            maxDescriptorSetTotalBuffersDynamic;
    uint32_t                            maxDescriptorSetUpdateAfterBindTotalUniformBuffersDynamic;
    uint32_t                            maxDescriptorSetUpdateAfterBindTotalStorageBuffersDynamic;
    uint32_t                            maxDescriptorSetUpdateAfterBindTotalBuffersDynamic;
} VkPhysicalDeviceMaintenance7PropertiesKHR;
  • robustFragmentShadingRateAttachmentAccess 指示使用 VkImageSubresourceRange::`baseMipLevel` 等于 0 创建的片元着色率附件是否可以具有太小而无法覆盖指定渲染区域的大小。

  • separateDepthStencilAttachmentAccess 指示对深度/模板附件的读取-修改-写入操作是否被视为对包含深度和模板方面的图像中同级模板或深度附件的写入。

  • maxDescriptorSetTotalUniformBuffersDynamic 指示可以在管线布局中包含的最大动态 uniform 缓冲区的总数。

  • maxDescriptorSetTotalStorageBuffersDynamic 指示可以在管线布局中包含的最大动态存储缓冲区的总数。

  • maxDescriptorSetTotalBuffersDynamic 指示可以在管线布局中包含的最大动态 uniform 缓冲区和存储缓冲区的总数。

  • maxDescriptorSetUpdateAfterBindTotalUniformBuffersDynamic 类似于 maxDescriptorSetUniformBuffersDynamic,但计算使用或不使用设置了 VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT 位的描述符集创建的描述符。

  • maxDescriptorSetUpdateAfterBindTotalStorageBuffersDynamic 类似于 maxDescriptorSetStorageBuffersDynamic,但计算使用或不使用设置了 VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT 位的描述符集创建的描述符。

  • maxDescriptorSetUpdateAfterBindTotalBuffersDynamic 类似于 maxDescriptorSetBuffersDynamic,但计算使用或不使用设置了 VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT 位的描述符集创建的描述符。

3.3. 新标志

VK_EXT_nested_command_buffer 扩展提升的 VK_RENDERING_CONTENTS_INLINE_BIT_KHR 标志允许在当前命令缓冲区内内联记录渲染通道实例。与 VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT 位结合使用,可以在内联和使用 vkCmdExecuteCommands 执行的二级命令缓冲区中记录渲染通道实例的内容。

VK_EXT_nested_command_buffer 扩展提升的 VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR 标志允许在内联和使用 vkCmdExecuteCommands 执行的二级命令缓冲区中记录渲染通道子通道的内容。

3.4. 新结构体

要查询有关分层实现的信息,请将以下内容链接到 vkGetPhysicalDeviceProperties2

typedef struct VkPhysicalDeviceLayeredApiPropertiesListKHR {
    VkStructureType                            sType;
    void*                                      pNext;
    uint32_t                                   layeredApiCount;
    VkPhysicalDeviceLayeredApiPropertiesKHR*   pLayeredApis;
} VkPhysicalDeviceLayeredApiPropertiesListKHR;

其中

typedef struct VkPhysicalDeviceLayeredApiPropertiesKHR {
    VkStructureType                       sType;
    void*                                 pNext;
    uint32_t                              vendorID;
    uint32_t                              deviceID;
    VkPhysicalDeviceLayeredApiKHR         layeredAPI;
    char                                  deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
} VkPhysicalDeviceLayeredApiPropertiesKHR;

在上面的内容中,vendorIDdeviceIDdeviceNameVkPhysicalDeviceProperties 中同名的成员类似。layeredAPI 是一个枚举,用于标识分层实现的底层 API,例如,如果该层实现 D3D12 API,则为 VK_PHYSICAL_DEVICE_LAYERED_API_D3D12_KHR

在存在多个层的情况下,pLayeredApis[0] 的内容对应于最底层的层,其后的索引(如果有)按层顺序排列。这允许纯粹对执行命令的最终供应商 ID 或 API 感兴趣的应用程序避免查询层计数,始终提供 layeredApiCount 为 1,并且仅检查 pLayeredApis[0]

要查询分层实现的 API 特定细节,可以将 API 特定的结构体链接到 VkPhysicalDeviceLayeredApiPropertiesKHR。对于分层 Vulkan 实现(即 VK_PHYSICAL_DEVICE_LAYERED_API_VULKAN_KHR),此扩展引入了 VkPhysicalDeviceLayeredApiVulkanPropertiesKHR 进行链接,未来可能会在其他扩展中添加其他 API 的结构体。实现将填充与分层 API 对应的链接结构体,并保持其他 API 的结构体不变。这允许应用程序链接多个 API 的结构体,并在单个查询中检索所有必要的信息。

typedef struct VkPhysicalDeviceLayeredApiVulkanPropertiesKHR {
    VkStructureType                       sType;
    void*                                 pNext;
    VkPhysicalDeviceProperties2           properties;
} VkPhysicalDeviceLayeredApiVulkanPropertiesKHR;

在上述结构体中,应用程序还可以将 VkPhysicalDeviceDriverPropertiesVkPhysicalDeviceIDProperties 链接到 properties,以从底层 Vulkan 设备提取更多信息。但是,properties.properties.limitsproperties.properties.sparseProperties 将被初始化为 0,并且不包含有意义的值。

例如,一个通过 Mesa 的 Venus,在 Mesa 的 Dozen 之上,并在 Nvidia 的专有 D3D12 实现之上运行的应用程序会收到以下信息:

layers->pLayeredApis[0].layeredAPI = VK_PHYSICAL_DEVICE_LAYERED_API_D3D12_KHR;
// other fields

layers->pLayeredApis[1].layeredAPI = VK_PHYSICAL_DEVICE_LAYERED_API_VULKAN_KHR;
// other fields

// If driverProperties is a VkPhysicalDeviceDriverProperties chained to
// VkPhysicalDeviceLayeredApiVulkanPropertiesKHR::properties that is in turn
// chained to layers->pLayeredApis[1].pNext:
driverProperties->driverID = VK_DRIVER_ID_MESA_DOZEN;
// other fields

在上面的例子中,顶层(Mesa 的 Venus)的属性将像往常一样在 VkPhysicalDeviceProperties2 中返回。注意:如果非 Vulkan 实现下方存在层,则可能在此查询中不可见。例如,如果应用程序通过 Mesa 的 Dozen 运行,并在 VKD3D-proton 等之上运行,则查询可能仅返回分层实现,直到 Mesa 的 Dozen,因为其他 API 可能缺少这样的查询。

VkPhysicalDeviceLayeredApiKHR 枚举定义为:

typedef enum VkPhysicalDeviceLayeredApiKHR {
    VK_PHYSICAL_DEVICE_LAYERED_API_VULKAN_KHR = 1,
    VK_PHYSICAL_DEVICE_LAYERED_API_D3D12_KHR = 2,
    VK_PHYSICAL_DEVICE_LAYERED_API_METAL_KHR = 3,
    VK_PHYSICAL_DEVICE_LAYERED_API_OPENGL_KHR = 4,
    VK_PHYSICAL_DEVICE_LAYERED_API_OPENGLES_KHR = 5,
} VkPhysicalDeviceLayeredApiKHR;

4. 问题

4.1. 已解决:当在分层实现上运行时,应如何查询底层分层 Vulkan 设备的属性?

应使用专用结构体 VkPhysicalDeviceLayeredApiVulkanPropertiesKHR,其中包含 VkPhysicalDeviceProperties2 成员。可以通过将 VkPhysicalDeviceDriverPropertiesVkPhysicalDeviceIDProperties 结构体链接到该成员来查询其他信息。

VkPhysicalDeviceProperties2VkPhysicalDeviceDriverPropertiesVkPhysicalDeviceIDProperties 直接链接到 VkPhysicalDeviceLayeredApiPropertiesKHR 可能会因多种原因而令人困惑。特别是,VkPhysicalDeviceProperties2 是一个“根”结构,可以接受其链中的 VkPhysicalDeviceDriverPropertiesVkPhysicalDeviceIDProperties;允许将这些结构体链接到 VkPhysicalDeviceLayeredApiPropertiesKHR 意味着应用程序可以创建一个诸如 VkPhysicalDeviceLayeredApiPropertiesKHRVkPhysicalDeviceDriverPropertiesVkPhysicalDeviceProperties2 的链,这可能会令人困惑。

未来的扩展还可以提供查询其他分层 API(例如 D3D)属性的功能。此扩展允许将 API 特定的结构体链接到 VkPhysicalDeviceLayeredApiPropertiesKHR,以便于一次查询所有信息,这意味着 VkPhysicalDeviceLayeredApiPropertiesKHRpNext 链可以包括 Vulkan 和 D3D 的属性结构体。允许每个 API 存在多个结构体,并且可能交错,只会增加混乱。

通过将 VkPhysicalDeviceProperties2 包装在 VkPhysicalDeviceLayeredApiVulkanPropertiesKHR 结构体中,VkPhysicalDeviceLayeredApiPropertiesKHRpNext 链每个 API 将仅包含一个结构体,从而避免驱动程序、应用程序和验证层出现混淆。

5. 进一步的功能

无。