必须先创建VkInstance再枚举物理设备;extension/layer需匹配平台,macOS必加VK_KHR_portability_subset;验证层需动态开关;WSI扩展不可遗漏;apiVersion推荐1.3;调试函数须动态获取;vkEnumeratePhysicalDevices需两步调用;设备选择须验特性而非仅deviceType;实例生命周期须长于物理设备。

必须先创建 VkInstance,再枚举物理设备;跳过实例直接查设备会触发 VK_ERROR_INITIALIZATION_FAILED 或段错误。
创建 VkInstance 时 extension 和 layer 必须匹配平台能力
Windows/Linux 上启用 VK_KHR_get_physical_device_properties2 是安全的,但 macOS 必须加 VK_KHR_portability_subset,否则 vkEnumeratePhysicalDevices 返回 0 设备或崩溃。验证层(如 VK_LAYER_KHRONOS_validation)只在开发机存在,发布时要动态开关——硬编码启用会导致无层环境初始化失败。
-
vkCreateInstance前必须调用glfwGetRequiredInstanceExtensions(若用 GLFW)或手动拼接 WSI 扩展,漏掉VK_KHR_surface或平台专属扩展(如VK_KHR_win32_surface)会导致后续VkSurfaceKHR创建失败 -
appInfo.apiVersion推荐设为VK_API_VERSION_1_3:低于 1.2 可能无法启用VK_KHR_dynamic_rendering等现代特性;高于当前驱动支持版本会静默降级,但不报错 - 调试 messenger(
VkDebugUtilsMessengerCreateInfoEXT)必须通过vkGetInstanceProcAddr动态获取函数指针,不能直接链接——否则 macOS 或旧驱动上链接时报 undefined symbol
vkEnumeratePhysicalDevices 返回 VK_INCOMPLETE 不是错误
这是 Vulkan 的标准分页行为,不是失败信号。常见误操作是传入固定大小数组(如 std::array<vkphysicaldevice></vkphysicaldevice>)后忽略返回值,导致只拿到前几个设备甚至越界读写。
- 必须两步调用:第一次传
nullptr获取真实数量,第二次才分配数组并填入设备句柄 - 两次调用之间不要修改
deviceCount变量——尤其多线程环境下,它可能被其他 Vulkan 调用覆盖 - Mac M 系列芯片返回
VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,但实际性能远超某些低端独显;硬过滤DISCRETE_GPU会导致在 Apple 设备上找不到可用设备
选物理设备不能只看 deviceType,得验 capability
设备类型字段(properties.deviceType)只是提示,真正决定能否跑通的是特性支持。例如,一个标称“集成显卡”的设备可能不支持 geometryShader,但你的管线用了 tessellation,那就得换设备。
立即学习“C++免费学习笔记(深入)”;
- 调用
vkGetPhysicalDeviceFeatures检查必需特性是否available == VK_TRUE,特别是shaderStorageImageExtendedFormats(用于通用图像读写)和robustBufferAccess(防越界访问) - 用
vkGetPhysicalDeviceProperties拿apiVersion,过滤掉低于VK_API_VERSION_1_2的设备——1.1 及更早版本不支持VK_KHR_buffer_device_address,而现代着色器推导地址常依赖它 - 必须调用
vkGetPhysicalDeviceQueueFamilyProperties确认存在至少一个队列族同时满足:queueFlags & VK_QUEUE_GRAPHICS_BIT且& VK_QUEUE_COMPUTE_BIT,否则无法复用队列提交图形+计算任务
最易被忽略的一点:VkInstance 生命周期必须长于所有物理设备句柄。一旦 vkDestroyInstance 被调用,所有关联的 VkPhysicalDevice 句柄立即失效——即使你没显式销毁它们。很多初学者在 cleanup 阶段先毁 instance 再试图用 device 查询属性,结果触发未定义行为。


















