Skip to content

第二章 · Vulkan 初始化与生命周期

2.1 初始化流程总览 🔥

Application Start

    ├── 1. 创建 Instance ──── 与 Vulkan 驱动建立连接
    │       └── 指定应用信息 + 扩展

    ├── 2. 枚举 Physical Devices ── 获取 GPU 列表
    │       └── 选择最适合的 GPU

    ├── 3. 检查设备能力 ──── 是否支持所需特性
    │       └── 队列族、内存类型、Vulkan 版本

    ├── 4. 创建 Logical Device ── 创建虚拟连接
    │       └── 指定队列 + 扩展 + 特性

    ├── 5. 获取 Queue ───── 获取 Graphics Queue
    │       └── vkGetDeviceQueue()

    ├── 6. 创建 Surface ──── 绑定窗口系统
    │       └── GLFW/SDL/Wayland/Xlib/Win32

    └── Instance Init Complete!

2.2 Instance(实例)创建

2.2.1 完整创建流程

python
import vkbottle  # Vulkan Python 绑定
import ctypes

# --- 1. 创建 Application Info ---
app_info = vkbottle.ApplicationInfo(
    pApplicationName=b"Vulkan Tutorial",    # 应用名称
    applicationVersion=vkbottle.Version(1, 0, 0),
    pEngineName=b"None",                     # 引擎名称
    engineVersion=vkbottle.Version(1, 0, 0),
    apiVersion=vkbottle.Version(1, 3, 0),   # 目标 Vulkan 版本
)

# --- 2. 创建 Instance ---
instance_create_info = vkbottle.InstanceCreateInfo(
    pApplicationInfo=app_info,
    enabledExtensionNames=[
        # 平台相关扩展(必须)
        "VK_KHR_surface",                # Surface 支持
        "VK_KHR_win32_surface",          # Windows 平台
        # 或 "VK_KHR_xlib_surface" (Linux)
        # 或 "VK_KHR_wayland_surface" (Linux/Wayland)
    ],
    enabledLayerNames=[
        # 验证层(开发阶段必须)
        "VK_LAYER_KHRONOS_validation"    # Khronos 验证层
    ]
)

instance = vkbottle.Instance.create_instance(instance_create_info)

# --- 3. 验证 ---
assert instance.handle != 0, "Instance 创建失败!"
print(f"Instance 已创建, Vulkan version: {instance.api_version}")

# --- 4. 清理(应用退出时)---
instance.destroy()

2.2.2 常用实例扩展

扩展说明
VK_KHR_surface所有平台的 Surface 基础
VK_KHR_win32_surfaceWindows 窗口绑定
VK_KHR_xlib_surfaceLinux/X11 窗口绑定
VK_KHR_xcb_surfaceLinux/XCB 窗口绑定
VK_KHR_wayland_surfaceLinux/Wayland 窗口绑定
VK_KHR_android_surfaceAndroid 窗口绑定
VK_EXT_debug_utils调试支持

2.2.3 验证层(Validation Layers)

python
# 验证层 = 类似"运行时断言"的检查器
# 在开发阶段**必须**启用,发布时可移除

# 推荐的验证层
validation_layers = [
    "VK_LAYER_KHRONOS_validation",  # Khronos 官方层(推荐 ✅)
]

# 验证层的常用检查:
# - 资源泄漏检测
# - API 调用错误
# - 状态一致性
# - 内存管理
# - Shader 验证
# - 同步错误

# 获取可用的验证层
available_layers = vkbottle.Instance.get_available_layers(instance, validation_layers)
print(f"可用验证层: {available_layers}")

2.3 枚举物理设备(Physical Device)

2.3.1 获取 GPU 列表

python
# --- 获取所有 GPU ---
physical_devices = instance.get_physical_devices()
print(f"发现 {len(physical_devices)} 个 GPU")

for i, device in enumerate(physical_devices):
    properties = device.get_properties()
    print(f"GPU {i}: {properties.deviceName}")
    print(f"  Vulkan Version: {properties.driverVersion}")
    print(f"  API Version: {properties.apiVersion}")
    print(f"  Type: {properties.deviceType}")

2.3.2 选择最适合的 GPU

python
def is_suitable_gpu(device):
    """判断 GPU 是否适合渲染"""
    properties = device.get_properties()
    
    # 必须是独立 GPU(非集成)
    if properties.deviceType != vkbottle.PhysicalDeviceType.DISCRETE_GPU:
        return False
    
    # 查询队列族
    queue_families = device.get_queue_families()
    
    # 必须有 Graphics Queue
    has_graphics = any(q.queueFlags & vkbottle.QueueFlag.GRAPHICS)
    
    # 必须有 Present Queue
    has_present = any(
        q.queueFlags & vkbottle.QueueFlag.GRAPHICS and 
        device.get_surface_capabilitiesKHR(surface).supportedUsageFlags
    )
    
    return has_graphics and has_present

# 选择第一个适合的 GPU
for device in physical_devices:
    if is_suitable_gpu(device):
        chosen_device = device
        break

2.3.3 设备能力查询

python
# --- 查询设备能力 ---
properties = chosen_device.get_properties()
features = chosen_device.get_features()
mem_properties = chosen_device.get_memory_properties()
queue_families = chosen_device.get_queue_families()

# 查询 Surface 支持
surface_caps = chosen_device.get_surface_capabilitiesKHR(surface)
surface_formats = chosen_device.get_surface_formatsKHR(surface)
surface_present_modes = chosen_device.get_surface_present_modesKHR(surface)

print(f"最大纹理尺寸: {surface_caps.maxImageDimension2D}")
print(f"支持的像素格式: {surface_formats}")
print(f"内存类型数: {mem_properties.memoryTypeCount}")

for i, mem_type in enumerate(mem_properties.memoryTypes):
    print(f"  Memory Type {i}:")
    print(f"    属性: {hex(mem_type.propertyFlags)}")
    print(f"    堆索引: {mem_type.heapIndex}")

2.4 创建 Logical Device

2.4.1 完整创建流程

python
# --- 1. 创建 Queue Create Info ---
queue_priority = 1.0  # Queue 优先级 (0.0 - 1.0)

# 找到 Graphics Queue Family
graphics_queue_family = None
for i, qf in enumerate(queue_families):
    if qf.queueFlags & vkbottle.QueueFlag.GRAPHICS:
        graphics_queue_family = i
        break

# 找到 Present Queue Family
present_queue_family = None
for i, qf in enumerate(queue_families):
    if device.get_surface_supportKHR(i, surface):
        present_queue_family = i
        break

# 如果 Graphics 和 Present 在同一个 Queue Family
if graphics_queue_family == present_queue_family:
    queue_create_infos = [
        vkbottle.DeviceQueueCreateInfo(
            queueFamilyIndex=graphics_queue_family,
            pQueuePriorities=[queue_priority]
        )
    ]
else:
    queue_create_infos = [
        vkbottle.DeviceQueueCreateInfo(
            queueFamilyIndex=graphics_queue_family,
            pQueuePriorities=[queue_priority]
        ),
        vkbottle.DeviceQueueCreateInfo(
            queueFamilyIndex=present_queue_family,
            pQueuePriorities=[queue_priority]
        )
    ]

# --- 2. 创建 Logical Device ---
device_create_info = vkbottle.DeviceCreateInfo(
    pQueueCreateInfos=queue_create_infos,
    enabledExtensionNames=[
        "VK_KHR_swapchain",  # Swap Chain 扩展
    ],
    enabledLayerNames=[
        "VK_LAYER_KHRONOS_validation"  # 验证层
    ],
    enabledFeatures=vkbottle.DeviceFeatures(
        # 启用特性
        samplerAnisotropy=vkbottle.Bool(1),  # 各向异性过滤
        samplerCompression=vkbottle.Bool(0),
        robustBufferAccess=vkbottle.Bool(0),
    )
)

logical_device = chosen_device.create_device(device_create_info)

# --- 3. 获取 Queue ---
graphics_queue = logical_device.get_queue(queueFamilyIndex=graphics_queue_family, queueIndex=0)

print(f"Logical Device 已创建!")
print(f"Graphics Queue: {graphics_queue}")

2.4.2 常用设备特性

特性说明
samplerAnisotropy各向异性过滤
sampleRateShading采样率着色
depthBiasClamp深度偏置
fillModeNonSolid非实心多边形模式
wideLines宽线
largePoints大点
fullDrawIndexedUint3232 位索引
imageCubeArray立方体数组
independentBlend独立混合
geometryShader几何着色器

2.5 创建 Surface

2.5.1 GLFW 绑定

python
import glfw

# --- 1. 初始化 GLFW ---
glfw.init()
window = glfw.create_window(800, 600, "Vulkan Window", None, None)
glfw.make_context_current(window)

# --- 2. 创建 Vulkan Surface ---
surface = vkbottle.Instance.create_surface(instance, glfw_window=window)

# --- 3. 查询 Surface 信息 ---
surface_caps = chosen_device.get_surface_capabilitiesKHR(surface)
surface_formats = chosen_device.get_surface_formatsKHR(surface)
surface_present_modes = chosen_device.get_surface_present_modesKHR(surface)

print(f"Surface 尺寸范围: {surface_caps.minImageExtent} x {surface_caps.maxImageExtent}")
print(f"支持的格式: {surface_formats}")
print(f"呈现模式: {surface_present_modes}")

# --- 4. 选择 Present Mode ---
preferred_present_mode = vkbottle.PresentModeKHR.FIFO  # VSync
for mode in surface_present_modes:
    if mode == vkbottle.PresentModeKHR.IMMEDIATE:
        preferred_present_mode = mode
        break

# --- 5. 清理 ---
glfw.destroy_window(window)
surface.destroy()
glfw.terminate()

2.5.2 不同平台 Surface 创建

平台方式说明
Windowsglfw_create_window() + glfw_create_window_surface()Win32
Linux/X11glfw_create_window() + glfw_create_window_surface()Xlib
Linux/Waylandwl_display_connect() + wl_egl_window_create()Wayland
AndroidANativeWindow_fromJava() + android_create_window_surface()NDK
macOSMoltenVK (VK_KHR_vulkan_win32)Metal 转换层

2.6 清理资源

python
# --- 正确的清理顺序(与创建顺序相反)---
# 1. 销毁 Swap Chain
swap_chain.destroy()

# 2. 销毁 Framebuffers
for framebuffer in framebuffers:
    framebuffer.destroy()

# 3. 销毁 Render Pass
render_pass.destroy()

# 4. 销毁 Pipelines
for pipeline in pipelines:
    pipeline.destroy()

# 5. 销毁 Descriptors
descriptor_layout.destroy()
descriptor_set_layout.destroy()

# 6. 销毁 Shader Modules
for shader_module in shader_modules:
    shader_module.destroy()

# 7. 销毁 Images
for image in images:
    image.destroy()

# 8. 销毁 Buffers
for buffer in buffers:
    buffer.destroy()

# 9. 销毁 Memory
for memory in memory_allocations:
    memory.destroy()

# 10. 销毁 Device
logical_device.destroy()

# 11. 销毁 Surface
surface.destroy()

# 12. 销毁 Instance
instance.destroy()

2.7 初始化速查表

步骤关键 API说明
1. 创建 InstancevkCreateInstance()与驱动建立连接
2. 枚举 DevicesvkEnumeratePhysicalDevices()获取 GPU 列表
3. 选择 GPUvkGetPhysicalDeviceProperties()查询能力
4. 创建 DevicevkCreateDevice()创建虚拟连接
5. 获取 QueuevkGetDeviceQueue()获取执行队列
6. 创建 Surfaceglfw_create_window_surface()绑定窗口
7. 创建 Swap ChainvkCreateSwapchainKHR()帧缓冲管理
8. 创建 Render PassvkCreateRenderPass()定义渲染结构
9. 创建 PipelinevkCreateGraphicsPipelines()定义渲染状态
10. 创建 ResourcesvkCreateBuffer/ Image资源创建