示例代码

VkFormat get_suitable_depth_format(VkPhysicalDevice physical_device, bool depth_only, const std::vector<VkFormat> &depth_format_priority_list)
{
    VkFormat depth_format{VK_FORMAT_UNDEFINED};
    for (auto &format : depth_format_priority_list)
    {
        if (depth_only && !is_depth_only_format(format))
        {
            continue;
        }
        VkFormatProperties properties;
        vkGetPhysicalDeviceFormatProperties(physical_device, format, &properties);
        // Format must support depth stencil attachment for optimal tiling
        if (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
        {
            depth_format = format;
            break;
        }
    }
    if (depth_format != VK_FORMAT_UNDEFINED)
    {
        LOGI("Depth format selected: {}", to_string(depth_format));
        return depth_format;
    }
    throw std::runtime_error("No suitable depth format could be determined");
}  

详细解释

这个函数用于选择合适的深度缓冲区格式,其中核心判断条件 Format must support depth stencil attachment for optimal tiling 涉及到 Vulkan 中的内存布局优化。让我详细解释:

Optimal Tiling

  • 它是 Vulkan 中的一种内存布局方式
  • 与 linear tiling 相对
  • 由 GPU 厂商优化的内存布局,具体布局对应用程序不可见
  • 通常性能更好,因为是为特定 GPU 架构优化的

Depth Stencil Attachment

  • 深度模板附件,用于深度测试和模板测试
  • 是渲染管线中重要的组成部分
  • 用于确定像素的可见性和特殊效果

代码分析

if (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)

这行代码在检查:

  • 该格式是否支持作为深度模板附件
  • 是否支持以 optimal tiling 方式使用
  • 两个条件必须同时满足

为什么需要这个检查

  • 不是所有格式都支持 optimal tiling
  • 不是所有格式都能用作深度模板附件
  • 使用最优的内存布局可以获得更好的性能

这个检查确保选择的深度格式能够:

  1. 高效地存储在显存中(optimal tiling)
  2. 正确用作深度缓冲区(depth stencil attachment)
  3. 得到硬件的良好支持

如果没有找到满足条件的格式,函数会抛出异常,因为深度缓冲区对于 3D 渲染来说通常是必需的。