格式
Vulkan 格式用于描述内存的布局方式。本章旨在简要概述 Vulkan 中各种各样的格式变体,以及如何使用它们。更详细的信息请阅读 Vulkan Spec格式章节和 Khronos 数据格式规范。
使用VkFormat
最常见的场景是创建VkImage
。由于VkFormat
定义明确,因此它也用于描述诸如VkBufferView
、顶点输入属性、SPIR-V 图像格式映射、创建三角形几何图形的底层加速结构等内容的内存布局。
查询功能是否支持
这里所说的“格式支持”不是指每种格式的单个二进制值,而是每种格式都有一组 VkFormatFeatureFlagBits,用来描述格式支持哪些功能。
每个硬件厂商支持的格式可能会有差异,但必须保证支持最小的格式功能集。应用在使用前可以查询支持的格式属性。
怎么查询格式特性
下面的代码展示了检查一个VkImageCreateInfo::tiling
设置为VK_IMAGE_TILING_LINEAR
的VkImage
是否支持采样为VK_FORMAT_R8_UNORM
格式。
代码将查询VK_FORMAT_R8_UNORM
的linearTilingFeatures
的标志,以查看设备是否支持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 值用于表示数据的哪一部分用来执行清除和复制等操作。
颜色
一个格式具备 R
、G
、B
、A
分量,可以通过VK_IMAGE_ASPECT_COLOR_BIT
访问分量。
深度和模板
格式有D
或S
分量。这些格式被视为不透明格式,并且在与深度/模板图像进行复制时有特殊规则。
某些格式同时具有深度和模板分量,可以使用VK_IMAGE_ASPECT_DEPTH_BIT
和VK_IMAGE_ASPECT_STENCIL_BIT
单独访问。
VK_KHR_separate_depth_stencil_layouts 和 VK_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_conversion 和 VK_EXT_ycbcr_2plane_444_formats 向 Vulkan 添加了多平面格式功能。可以使用VK_IMAGE_ASPECT_PLANE_0_BIT
、VK_IMAGE_ASPECT_PLANE_1_BIT
和VK_IMAGE_ASPECT_PLANE_2_BIT
单独访问这些平面。
打包格式
打包格式用于地址对齐。例如,VK_FORMAT_A8B8G8R8_UNORM_PACK32
和VK_FORMAT_R8G8B8A8_UNORM
可能看起来非常相似,但是当使用规范的 Vertex Input Extraction 章节的公式:
attribAddress = bufferBindingAddress + vertexOffset + attribDesc.offset;
对于VK_FORMAT_R8G8B8A8_UNORM
,attribAddress
必须是分量大小(8 比特位)的倍数,而VK_FORMAT_A8B8G8R8_UNORM_PACK32
必须是打包 大小(32 比特位)的倍数。
外部扩展
目前仅支持VK_ANDROID_external_memory_android_hardware_buffer
扩展,此扩展允许 Android 应用导入自定义的外部格式,以便与 VkSamplerYcbcrConversion 一起使用,这些外部格式在规范文档中有许多限制。