格式

Vulkan 格式用于描述内存的布局方式。本章旨在概述 Vulkan 中格式的各种变化以及如何使用它们的一些逻辑信息。所有详细信息都已在 Vulkan 规范格式章节Khronos 数据格式规范 中进行了详细说明。

VkFormat 最常见的用例是创建 VkImage 时。由于 VkFormat​s 已被明确定义,它们也用于描述 VkBufferView顶点输入属性映射 SPIR-V 图像格式、创建 底层加速结构中的三角形几何体等事物的内存布局。

特性支持

理解“格式支持”不是每个格式的单个二进制值非常重要,而是每个格式都有一组 VkFormatFeatureFlagBits,每个标志都描述了格式支持哪些特性。

支持的格式可能因实现而异,但保证了最少的一组格式特性。应用程序可以查询支持的格式属性。

VK_KHR_get_physical_device_properties2VK_KHR_format_feature_flags2 都提供了另一种查询格式特性的方法。

格式特性查询示例

在此示例中,代码将检查 VK_FORMAT_R8_UNORM 格式是否支持从使用 VK_IMAGE_TILING_LINEAR 作为 VkImageCreateInfo::tiling 创建的 VkImage 中采样。为此,代码将查询 VK_FORMAT_R8_UNORMlinearTilingFeatures 标志,以查看实现是否支持 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT

// Using core Vulkan 1.0
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(physicalDevice, VK_FORMAT_R8_UNORM, &formatProperties);
if ((formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0) {
    // supported
} else {
    // not supported
}
// Using core Vulkan 1.1 or VK_KHR_get_physical_device_properties2
VkFormatProperties2 formatProperties2;
formatProperties2.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
formatProperties2.pNext = nullptr; // used for possible extensions

vkGetPhysicalDeviceFormatProperties2(physicalDevice, VK_FORMAT_R8_UNORM, &formatProperties2);
if ((formatProperties2.formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0) {
    // supported
} else {
    // not supported
}
// Using VK_KHR_format_feature_flags2
VkFormatProperties3KHR formatProperties3;
formatProperties3.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR;
formatProperties3.pNext = nullptr;

VkFormatProperties2 formatProperties2;
formatProperties2.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
formatProperties2.pNext = &formatProperties3;

vkGetPhysicalDeviceFormatProperties2(physicalDevice, VK_FORMAT_R8_UNORM, &formatProperties2);
if ((formatProperties3.linearTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR) != 0) {
    // supported
} else {
    // not supported
}

格式的变体

格式有多种变体,大多数可以通过格式的名称进行分组。在处理图像时,使用 VkImageAspectFlagBits 值来表示在执行清除和复制等操作时访问的数据的哪一部分。

颜色

具有 RGBA 组件且使用 VK_IMAGE_ASPECT_COLOR_BIT 访问的格式

深度和模板

具有 DS 组件的格式。这些格式被视为不透明,并且在从深度/模板图像复制和复制到深度/模板图像时有特殊的规则。

某些格式同时具有深度和模板组件,可以使用 VK_IMAGE_ASPECT_DEPTH_BITVK_IMAGE_ASPECT_STENCIL_BIT 分别访问。

VK_KHR_separate_depth_stencil_layoutsVK_EXT_separate_stencil_usage(两者都已升级到 Vulkan 1.2)可以用于对深度和模板组件进行更精细的控制。

有关深度格式的更多信息也可以在深度章节中找到。

压缩

压缩图像格式表示在区域内以相互依赖的方式编码的多个像素。

表 1. Vulkan 压缩图像格式
格式 如何启用

BC(块压缩)

VkPhysicalDeviceFeatures::textureCompressionBC

ETC2 和 EAC

VkPhysicalDeviceFeatures::textureCompressionETC2

ASTC LDR

VkPhysicalDeviceFeatures::textureCompressionASTC_LDR

ASTC HDR

VK_EXT_texture_compression_astc_hdr

PVRTC

VK_IMG_format_pvrtc

平面

VK_KHR_sampler_ycbcr_conversionVK_EXT_ycbcr_2plane_444_formats 向 Vulkan 添加了多平面格式。可以使用 VK_IMAGE_ASPECT_PLANE_0_BITVK_IMAGE_ASPECT_PLANE_1_BITVK_IMAGE_ASPECT_PLANE_2_BIT 分别访问平面。

打包

打包格式用于地址对齐的目的。例如,VK_FORMAT_A8B8G8R8_UNORM_PACK32VK_FORMAT_R8G8B8A8_UNORM 可能看起来非常相似,但是当使用 规范的顶点输入提取部分中的公式时

attribAddress = bufferBindingAddress + vertexOffset + attribDesc.offset;

对于 VK_FORMAT_R8G8B8A8_UNORMattribAddress 必须是组件大小(8 位)的倍数,而 VK_FORMAT_A8B8G8R8_UNORM_PACK32 必须是打包大小(32 位)的倍数。

外部

目前仅支持 VK_ANDROID_external_memory_android_hardware_buffer 扩展。此扩展允许 Android 应用程序导入实现定义的外部格式,以便与 VkSamplerYcbcrConversion 一起使用。关于这些外部格式的许多限制在 规范文档中有所说明。