You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Vulkan API查询GPU支持的所有纹理格式?

正确查询Vulkan GPU支持的所有纹理格式

问题场景

我在用Vulkan API查询GPU支持的纹理格式时,使用vkGetPhysicalDeviceSurfaceFormatsKHR得到的结果仅4种格式,但我的AMD Radeon高性能GPU实际支持VK_FORMAT_BC1_RGBA_UNORM_BLOCK这类压缩格式(已成功用该格式创建图像)。怀疑这段代码只枚举了KHR Surface的支持格式,而非GPU的全部纹理格式,请问如何正确查询?

附原查询代码:

uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
if (formatCount != 0) {
    details.formats.resize(formatCount);
    vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
    int counter = 0;
    int numFormats = details.formats.size();
    for (const auto& format : details.formats) {
        VkFormat vkFormat = format.format;
        VkColorSpaceKHR colorSpace = format.colorSpace;
        std::cout << "[" << counter << "] Format: " <<
            vkFormatToString(vkFormat) <<
            ", Color Space: " << colorSpace << std::endl;
        counter++;
    }
}

附成功创建BC1格式图像的代码:

imageInfo.format = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
imageInfo.tiling = tiling;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = usage;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
    throw std::runtime_error("failed to create image!");
}

问题原因

你判断的完全正确:vkGetPhysicalDeviceSurfaceFormatsKHR仅返回与指定窗口表面兼容的交换链图像格式——这些是GPU能直接输出到显示器的格式,和GPU本身支持的所有纹理格式不是一个概念。BC1这类压缩格式属于GPU内部处理的纹理格式,不属于交换链输出兼容格式,因此不会被该API返回。


正确查询方法

要获取GPU支持的所有纹理格式,需根据纹理的使用场景,调用以下两个核心API:

1. 查询格式的基础支持属性

使用vkGetPhysicalDeviceFormatProperties可以获取指定格式的通用支持能力,比如能否作为采样图像、存储图像、颜色附件等:

VkPhysicalDevice physicalDevice = ...; // 你的物理设备实例
VkFormat targetFormat = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
VkFormatProperties formatProps;
vkGetPhysicalDeviceFormatProperties(physicalDevice, targetFormat, &formatProps);

// 检查是否支持作为采样图像(最常见的纹理用途)
if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
    std::cout << "BC1格式支持作为采样图像" << std::endl;
}
// 检查是否支持作为存储图像
if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) {
    std::cout << "BC1格式支持作为存储图像" << std::endl;
}

2. 查询特定图像参数下的格式兼容性

如果要确认某格式能否配合你创建图像时的具体参数(如tiling、usage、样本数)使用,vkGetPhysicalDeviceImageFormatProperties更准确,它直接对应vkCreateImage的参数校验逻辑:

VkPhysicalDevice physicalDevice = ...;
VkFormat format = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
VkImageType imageType = VK_IMAGE_TYPE_2D;
VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; // 压缩格式通常仅支持OPTIMAL tiling
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT;
VkImageCreateFlags flags = 0;

VkImageFormatProperties imageFormatProps;
VkResult result = vkGetPhysicalDeviceImageFormatProperties(
    physicalDevice,
    format,
    imageType,
    tiling,
    usage,
    flags,
    &imageFormatProps
);

if (result == VK_SUCCESS) {
    std::cout << "BC1格式支持指定参数创建图像,最大分辨率:" 
              << imageFormatProps.maxExtent.width << "x" 
              << imageFormatProps.maxExtent.height << std::endl;
} else {
    std::cout << "BC1格式不支持当前指定的图像参数" << std::endl;
}

3. 枚举GPU支持的所有纹理格式

如果要遍历GPU支持的所有可用纹理格式,可以循环所有VkFormat枚举值,逐个检查是否满足纹理相关的用途:

VkPhysicalDevice physicalDevice = ...;
// 遍历所有VkFormat(跳过VK_FORMAT_UNDEFINED)
for (uint32_t formatEnum = 1; formatEnum < VK_FORMAT_MAX_ENUM; ++formatEnum) {
    VkFormat format = static_cast<VkFormat>(formatEnum);
    VkFormatProperties props;
    vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props);
    
    // 判断是否为可用的纹理格式(支持采样、存储或颜色附件)
    bool isValidTextureFormat = false;
    // 检查最优平铺下的支持能力
    if (props.optimalTilingFeatures & (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | 
                                       VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | 
                                       VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
        isValidTextureFormat = true;
    }
    // 检查线性平铺下的支持能力
    if (props.linearTilingFeatures & (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | 
                                      VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | 
                                      VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
        isValidTextureFormat = true;
    }
    
    if (isValidTextureFormat) {
        std::cout << "支持的纹理格式:" << vkFormatToString(format) << std::endl;
    }
}

注意事项

  • 压缩格式(BC、ASTC、ETC等)几乎都只支持VK_IMAGE_TILING_OPTIMAL,不支持线性平铺,查询时要对应正确的tiling参数。
  • 不同GPU厂商对格式的支持差异较大,务必通过API动态查询,不要硬编码格式列表。

内容的提问来源于stack exchange,提问作者gmmo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:30:33