Vulkan深度缓冲

OpenTK 2026-09-11 09:43:43

#version 450

layout(binding = 0) uniform UniformBufferObject {
    mat4 model;
    mat4 view;
    mat4 proj;
} ubo;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord;

layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;

void main() {
    gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
    fragColor = inColor;
    fragTexCoord = inTexCoord;
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------

#version 450

layout(binding = 1) uniform sampler2D texSampler;

layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;

layout(location = 0) out vec4 outColor;

void main() {
    outColor = texture(texSampler, fragTexCoord);
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------

glslc 27_shader_depth.vert -o 27_shader_depth.vert.spv
glslc 27_shader_depth.frag -o 27_shader_depth.frag.spv

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------

#define GLFW_INCLUDE_VULKAN                  // 让GLFW自动包含Vulkan头文件
#include <GLFW/glfw3.h>                      // GLFW窗口库

#define GLM_FORCE_DEPTH_ZERO_TO_ONE          // 让GLM使用Vulkan的深度范围[0,1]而不是OpenGL的[-1,1]
#include <glm/glm.hpp>                       // GLM数学库核心
#include <glm/gtc/matrix_transform.hpp>      // GLM矩阵变换函数(perspective/lookAt/rotate等)

#define STB_IMAGE_IMPLEMENTATION             // 定义此宏以在当前位置生成stb_image的实现代码
#include <stb_image.h>                       // stb_image图像加载库(单头文件)

#include <iostream>                          // 标准输入输出流
#include <fstream>                           // 文件读写
#include <stdexcept>                         // 标准异常类
#include <algorithm>                         // std::clamp等算法
#include <chrono>                            // 时间库,用于计算旋转动画
#include <vector>                            // 动态数组
#include <cstring>                           // memcpy/strcmp等C字符串函数
#include <cstdlib>                           // EXIT_SUCCESS/EXIT_FAILURE
#include <cstdint>                           // uint32_t等固定宽度整型
#include <limits>                            // std::numeric_limits
#include <array>                             // std::array定长数组
#include <optional>                          // std::optional,用于可选队列族索引
#include <set>                               // std::set,用于去重队列族

const uint32_t WIDTH = 800;                  // 窗口宽度
const uint32_t HEIGHT = 600;                 // 窗口高度

const int MAX_FRAMES_IN_FLIGHT = 2;          // 允许同时在途的帧数(双缓冲)

const std::vector<const char*> validationLayers = {  // 启用的校验层列表
    "VK_LAYER_KHRONOS_validation"            // Khronos官方校验层,用于调试
};

const std::vector<const char*> deviceExtensions = {  // 需要的设备扩展
    VK_KHR_SWAPCHAIN_EXTENSION_NAME          // 交换链扩展,呈现图像必需
};

#ifdef NDEBUG
const bool enableValidationLayers = false;   // Release模式下关闭校验层
#else
const bool enableValidationLayers = true;    // Debug模式下开启校验层
#endif

VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {  // 动态加载vkCreateDebugUtilsMessengerEXT
    auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");  // 从实例获取函数指针
    if (func != nullptr) {                   // 若函数存在
        return func(instance, pCreateInfo, pAllocator, pDebugMessenger);  // 调用创建调试信使
    }
    else {
        return VK_ERROR_EXTENSION_NOT_PRESENT;  // 扩展不存在则返回错误
    }
}

void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) {  // 动态加载vkDestroyDebugUtilsMessengerEXT
    auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");  // 获取函数指针
    if (func != nullptr) {                   // 若函数存在
        func(instance, debugMessenger, pAllocator);  // 销毁调试信使
    }
}

struct QueueFamilyIndices {                  // 队列族索引结构体
    std::optional<uint32_t> graphicsFamily;  // 图形队列族索引(可选)
    std::optional<uint32_t> presentFamily;   // 呈现队列族索引(可选)

    bool isComplete() {                      // 判断两个队列族是否都已找到
        return graphicsFamily.has_value() && presentFamily.has_value();
    }
};

struct SwapChainSupportDetails {             // 交换链支持详情
    VkSurfaceCapabilitiesKHR capabilities;   // 表面能力
    std::vector<VkSurfaceFormatKHR> formats; // 支持的表面格式
    std::vector<VkPresentModeKHR> presentModes;  // 支持的呈现模式
};

struct Vertex {                              // 顶点结构体
    glm::vec3 pos;                           // 位置
    glm::vec3 color;                         // 颜色
    glm::vec2 texCoord;                      // 纹理坐标

    static VkVertexInputBindingDescription getBindingDescription() {  // 顶点绑定描述
        VkVertexInputBindingDescription bindingDescription{};         // 值初始化
        bindingDescription.binding = 0;                               // 绑定索引
        bindingDescription.stride = sizeof(Vertex);                   // 每个顶点跨距
        bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;   // 逐顶点输入

        return bindingDescription;
    }

    static std::array<VkVertexInputAttributeDescription, 3> getAttributeDescriptions() {  // 顶点属性描述(3个)
        std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{};

        attributeDescriptions[0].binding = 0;                         // 对应binding 0
        attributeDescriptions[0].location = 0;                        // 着色器location 0
        attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; // vec3
        attributeDescriptions[0].offset = offsetof(Vertex, pos);      // pos字段偏移

        attributeDescriptions[1].binding = 0;
        attributeDescriptions[1].location = 1;                        // 着色器location 1
        attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; // vec3
        attributeDescriptions[1].offset = offsetof(Vertex, color);    // color字段偏移

        attributeDescriptions[2].binding = 0;
        attributeDescriptions[2].location = 2;                        // 着色器location 2
        attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;    // vec2
        attributeDescriptions[2].offset = offsetof(Vertex, texCoord); // texCoord字段偏移

        return attributeDescriptions;
    }
};

struct UniformBufferObject {                 // Uniform缓冲对象(每帧传给顶点着色器)
    alignas(16) glm::mat4 model;             // 模型矩阵(16字节对齐)
    alignas(16) glm::mat4 view;              // 视图矩阵
    alignas(16) glm::mat4 proj;              // 投影矩阵
};

const std::vector<Vertex> vertices = {       // 顶点数据:两个四边形(前面+后面)
    {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f}},  // 前左下
    {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},   // 前右下
    {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},    // 前右上
    {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}},   // 前左上

    {{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f}}, // 后左下
    {{0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},  // 后右下
    {{0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},   // 后右上
    {{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}   // 后左上
};

const std::vector<uint16_t> indices = {      // 索引数据(两个四边形各2个三角形)
    0, 1, 2, 2, 3, 0,                        // 前面的两个三角形
    4, 5, 6, 6, 7, 4                         // 后面的两个三角形
};

class HelloTriangleApplication {             // 应用主类
public:
    void run() {                             // 入口:初始化 -> 主循环 -> 清理
        initWindow();                        // 创建窗口
        initVulkan();                        // 初始化Vulkan
        mainLoop();                          // 主循环
        cleanup();                           // 清理资源
    }

private:
    GLFWwindow* window;                      // GLFW窗口句柄

    VkInstance instance;                     // Vulkan实例
    VkDebugUtilsMessengerEXT debugMessenger; // 调试信使
    VkSurfaceKHR surface;                    // 窗口表面

    VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;  // 物理设备(GPU)
    VkDevice device;                         // 逻辑设备

    VkQueue graphicsQueue;                   // 图形队列
    VkQueue presentQueue;                    // 呈现队列

    VkSwapchainKHR swapChain;                // 交换链
    std::vector<VkImage> swapChainImages;    // 交换链图像
    VkFormat swapChainImageFormat;           // 交换链图像格式
    VkExtent2D swapChainExtent;              // 交换链图像尺寸
    std::vector<VkImageView> swapChainImageViews;  // 交换链图像视图
    std::vector<VkFramebuffer> swapChainFramebuffers;  // 帧缓冲

    VkRenderPass renderPass;                 // 渲染通道
    VkDescriptorSetLayout descriptorSetLayout;  // 描述符集布局
    VkPipelineLayout pipelineLayout;         // 管线布局
    VkPipeline graphicsPipeline;             // 图形管线

    VkCommandPool commandPool;               // 命令池

    VkImage depthImage;                      // 深度图像
    VkDeviceMemory depthImageMemory;         // 深度图像内存
    VkImageView depthImageView;              // 深度图像视图

    VkImage textureImage;                    // 纹理图像
    VkDeviceMemory textureImageMemory;       // 纹理图像内存
    VkImageView textureImageView;            // 纹理图像视图
    VkSampler textureSampler;                // 纹理采样器

    VkBuffer vertexBuffer;                   // 顶点缓冲
    VkDeviceMemory vertexBufferMemory;       // 顶点缓冲内存
    VkBuffer indexBuffer;                    // 索引缓冲
    VkDeviceMemory indexBufferMemory;        // 索引缓冲内存

    std::vector<VkBuffer> uniformBuffers;    // Uniform缓冲(每帧一个)
    std::vector<VkDeviceMemory> uniformBuffersMemory;  // Uniform缓冲内存
    std::vector<void*> uniformBuffersMapped; // 映射后的Uniform缓冲指针

    VkDescriptorPool descriptorPool;         // 描述符池
    std::vector<VkDescriptorSet> descriptorSets;  // 描述符集

    std::vector<VkCommandBuffer> commandBuffers;  // 命令缓冲

    std::vector<VkSemaphore> imageAvailableSemaphores;  // 图像可用信号量
    std::vector<VkSemaphore> renderFinishedSemaphores;  // 渲染完成信号量
    std::vector<VkFence> inFlightFences;     // 在途帧围栏
    uint32_t currentFrame = 0;               // 当前帧索引

    bool framebufferResized = false;         // 帧缓冲是否被改变大小

    void initWindow() {                      // 初始化GLFW窗口
        glfwInit();                          // 初始化GLFW

        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);  // 告诉GLFW不要创建OpenGL上下文

        window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);  // 创建窗口
        glfwSetWindowUserPointer(window, this);  // 保存this指针,便于回调访问
        glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);  // 注册窗口大小变化回调
    }

    static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {  // 窗口大小变化回调
        auto app = reinterpret_cast<HelloTriangleApplication*>(glfwGetWindowUserPointer(window));  // 取回应用实例
        app->framebufferResized = true;      // 标记需要重建交换链
    }

    void initVulkan() {                      // 初始化Vulkan的各步骤
        createInstance();                    // 创建实例
        setupDebugMessenger();               // 设置调试信使
        createSurface();                     // 创建窗口表面
        pickPhysicalDevice();                // 选择物理设备
        createLogicalDevice();               // 创建逻辑设备
        createSwapChain();                   // 创建交换链
        createImageViews();                  // 创建图像视图
        createRenderPass();                  // 创建渲染通道
        createDescriptorSetLayout();         // 创建描述符集布局
        createGraphicsPipeline();            // 创建图形管线
        createCommandPool();                 // 创建命令池
        createDepthResources();              // 创建深度资源
        createFramebuffers();                // 创建帧缓冲
        createTextureImage();                // 创建纹理图像
        createTextureImageView();            // 创建纹理图像视图
        createTextureSampler();              // 创建纹理采样器
        createVertexBuffer();                // 创建顶点缓冲
        createIndexBuffer();                 // 创建索引缓冲
        createUniformBuffers();              // 创建Uniform缓冲
        createDescriptorPool();              // 创建描述符池
        createDescriptorSets();              // 分配描述符集
        createCommandBuffers();              // 创建命令缓冲
        createSyncObjects();                 // 创建同步对象
    }

    void mainLoop() {                        // 主循环
        while (!glfwWindowShouldClose(window)) {  // 窗口未关闭时循环
            glfwPollEvents();                // 处理窗口事件
            drawFrame();                     // 绘制一帧
        }

        vkDeviceWaitIdle(device);            // 等待设备空闲
    }

    void cleanupSwapChain() {                // 清理交换链相关资源
        vkDestroyImageView(device, depthImageView, nullptr);      // 销毁深度图像视图
        vkDestroyImage(device, depthImage, nullptr);              // 销毁深度图像
        vkFreeMemory(device, depthImageMemory, nullptr);          // 释放深度图像内存

        for (auto framebuffer : swapChainFramebuffers) {          // 遍历帧缓冲
            vkDestroyFramebuffer(device, framebuffer, nullptr);   // 销毁帧缓冲
        }

        for (auto imageView : swapChainImageViews) {              // 遍历图像视图
            vkDestroyImageView(device, imageView, nullptr);       // 销毁图像视图
        }

        vkDestroySwapchainKHR(device, swapChain, nullptr);        // 销毁交换链
    }

    void cleanup() {                         // 清理所有资源
        cleanupSwapChain();                  // 先清理交换链相关

        vkDestroyPipeline(device, graphicsPipeline, nullptr);     // 销毁图形管线
        vkDestroyPipelineLayout(device, pipelineLayout, nullptr); // 销毁管线布局
        vkDestroyRenderPass(device, renderPass, nullptr);         // 销毁渲染通道

        for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {       // 遍历每帧资源
            vkDestroyBuffer(device, uniformBuffers[i], nullptr);  // 销毁Uniform缓冲
            vkFreeMemory(device, uniformBuffersMemory[i], nullptr);  // 释放Uniform缓冲内存
        }

        vkDestroyDescriptorPool(device, descriptorPool, nullptr); // 销毁描述符池

        vkDestroySampler(device, textureSampler, nullptr);        // 销毁纹理采样器
        vkDestroyImageView(device, textureImageView, nullptr);    // 销毁纹理图像视图

        vkDestroyImage(device, textureImage, nullptr);            // 销毁纹理图像
        vkFreeMemory(device, textureImageMemory, nullptr);        // 释放纹理图像内存

        vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);  // 销毁描述符集布局

        vkDestroyBuffer(device, indexBuffer, nullptr);            // 销毁索引缓冲
        vkFreeMemory(device, indexBufferMemory, nullptr);         // 释放索引缓冲内存

        vkDestroyBuffer(device, vertexBuffer, nullptr);           // 销毁顶点缓冲
        vkFreeMemory(device, vertexBufferMemory, nullptr);        // 释放顶点缓冲内存

        for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {       // 遍历每帧同步对象
            vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);  // 销毁渲染完成信号量
            vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);  // 销毁图像可用信号量
            vkDestroyFence(device, inFlightFences[i], nullptr);   // 销毁围栏
        }

        vkDestroyCommandPool(device, commandPool, nullptr);       // 销毁命令池

        vkDestroyDevice(device, nullptr);                         // 销毁逻辑设备

        if (enableValidationLayers) {                             // 若启用了校验层
            DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);  // 销毁调试信使
        }

        vkDestroySurfaceKHR(instance, surface, nullptr);          // 销毁表面
        vkDestroyInstance(instance, nullptr);                     // 销毁实例

        glfwDestroyWindow(window);                                // 销毁窗口

        glfwTerminate();                                          // 终止GLFW
    }

    void recreateSwapChain() {               // 重建交换链
        int width = 0, height = 0;           // 当前帧缓冲尺寸
        glfwGetFramebufferSize(window, &width, &height);  // 获取窗口尺寸
        while (width == 0 || height == 0) {  // 最小化时等待
            glfwGetFramebufferSize(window, &width, &height);
            glfwWaitEvents();
        }

        vkDeviceWaitIdle(device);            // 等待设备空闲

        cleanupSwapChain();                  // 清理旧的交换链资源

        createSwapChain();                   // 重建交换链
        createImageViews();                  // 重建图像视图
        createDepthResources();              // 重建深度资源
        createFramebuffers();                // 重建帧缓冲
    }

    void createInstance() {                  // 创建Vulkan实例
        if (enableValidationLayers && !checkValidationLayerSupport()) {  // 校验层不可用则报错
            throw std::runtime_error("validation layers requested, but not available!");
        }

        VkApplicationInfo appInfo{};         // 应用信息
        appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
        appInfo.pApplicationName = "Hello Triangle";  // 应用名
        appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);  // 应用版本
        appInfo.pEngineName = "No Engine";   // 引擎名
        appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);  // 引擎版本
        appInfo.apiVersion = VK_API_VERSION_1_0;  // Vulkan API版本

        VkInstanceCreateInfo createInfo{};   // 实例创建信息
        createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
        createInfo.pApplicationInfo = &appInfo;

        auto extensions = getRequiredExtensions();  // 获取所需扩展
        createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());  // 扩展数量
        createInfo.ppEnabledExtensionNames = extensions.data();  // 扩展名称数组

        VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};  // 调试信使创建信息
        if (enableValidationLayers) {        // 若启用校验层
            createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());  // 层数量
            createInfo.ppEnabledLayerNames = validationLayers.data();  // 层名称

            populateDebugMessengerCreateInfo(debugCreateInfo);  // 填充调试信使信息
            createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo;  // 挂到pNext
        }
        else {
            createInfo.enabledLayerCount = 0;  // 不启用层

            createInfo.pNext = nullptr;
        }

        if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {  // 创建实例
            throw std::runtime_error("failed to create instance!");
        }
    }

    void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {  // 填充调试信使创建信息
        createInfo = {};
        createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
        createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;  // 关注Verbose/Warning/Error
        createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;  // 关注通用/校验/性能
        createInfo.pfnUserCallback = debugCallback;  // 回调函数
    }

    void setupDebugMessenger() {             // 设置调试信使
        if (!enableValidationLayers) return; // 未启用校验层则直接返回

        VkDebugUtilsMessengerCreateInfoEXT createInfo;
        populateDebugMessengerCreateInfo(createInfo);  // 填充信息

        if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {  // 创建
            throw std::runtime_error("failed to set up debug messenger!");
        }
    }

    void createSurface() {                   // 创建窗口表面
        if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {  // 由GLFW创建表面
            throw std::runtime_error("failed to create window surface!");
        }
    }

    void pickPhysicalDevice() {              // 选择物理设备
        uint32_t deviceCount = 0;            // 设备数量
        vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);  // 查询数量

        if (deviceCount == 0) {              // 没有支持Vulkan的GPU
            throw std::runtime_error("failed to find GPUs with Vulkan support!");
        }

        std::vector<VkPhysicalDevice> devices(deviceCount);  // 设备列表
        vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());  // 获取设备

        for (const auto& device : devices) { // 遍历设备
            if (isDeviceSuitable(device)) {  // 若满足需求
                physicalDevice = device;     // 选中
                break;
            }
        }

        if (physicalDevice == VK_NULL_HANDLE) {  // 没有合适的GPU
            throw std::runtime_error("failed to find a suitable GPU!");
        }
    }

    void createLogicalDevice() {             // 创建逻辑设备
        QueueFamilyIndices indices = findQueueFamilies(physicalDevice);  // 查找队列族

        std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;  // 队列创建信息
        std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };  // 去重

        float queuePriority = 1.0f;          // 队列优先级
        for (uint32_t queueFamily : uniqueQueueFamilies) {  // 遍历队列族
            VkDeviceQueueCreateInfo queueCreateInfo{};
            queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
            queueCreateInfo.queueFamilyIndex = queueFamily;  // 队列族索引
            queueCreateInfo.queueCount = 1;  // 队列数量
            queueCreateInfo.pQueuePriorities = &queuePriority;  // 优先级
            queueCreateInfos.push_back(queueCreateInfo);
        }

        VkPhysicalDeviceFeatures deviceFeatures{};  // 设备特性
        deviceFeatures.samplerAnisotropy = VK_TRUE; // 启用各向异性采样

        VkDeviceCreateInfo createInfo{};     // 设备创建信息
        createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

        createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());  // 队列信息数量
        createInfo.pQueueCreateInfos = queueCreateInfos.data();  // 队列信息数组

        createInfo.pEnabledFeatures = &deviceFeatures;  // 启用特性

        createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());  // 扩展数量
        createInfo.ppEnabledExtensionNames = deviceExtensions.data();  // 扩展名称

        if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {  // 创建逻辑设备
            throw std::runtime_error("failed to create logical device!");
        }

        vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);  // 获取图形队列
        vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);    // 获取呈现队列
    }

    void createSwapChain() {                 // 创建交换链
        SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);  // 查询支持详情

        VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);  // 选择表面格式
        VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);   // 选择呈现模式
        VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);                   // 选择尺寸

        uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;  // 至少比最小多1
        if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {  // 不超过最大值
            imageCount = swapChainSupport.capabilities.maxImageCount;
        }

        VkSwapchainCreateInfoKHR createInfo{};  // 交换链创建信息
        createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
        createInfo.surface = surface;           // 表面

        createInfo.minImageCount = imageCount;  // 图像数量
        createInfo.imageFormat = surfaceFormat.format;      // 图像格式
        createInfo.imageColorSpace = surfaceFormat.colorSpace;  // 颜色空间
        createInfo.imageExtent = extent;        // 图像尺寸
        createInfo.imageArrayLayers = 1;        // 数组层数
        createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;  // 用作颜色附件

        QueueFamilyIndices indices = findQueueFamilies(physicalDevice);  // 队列族
        uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };  // 两个队列族

        if (indices.graphicsFamily != indices.presentFamily) {  // 不同队列族
            createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;  // 并发共享
            createInfo.queueFamilyIndexCount = 2;
            createInfo.pQueueFamilyIndices = queueFamilyIndices;
        }
        else {
            createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;  // 独占
        }

        createInfo.preTransform = swapChainSupport.capabilities.currentTransform;  // 当前变换
        createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;  // 不透明
        createInfo.presentMode = presentMode;   // 呈现模式
        createInfo.clipped = VK_TRUE;           // 允许裁剪

        if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) {  // 创建交换链
            throw std::runtime_error("failed to create swap chain!");
        }

        vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);  // 查询图像数量
        swapChainImages.resize(imageCount);     // 调整大小
        vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());  // 获取图像

        swapChainImageFormat = surfaceFormat.format;  // 保存格式
        swapChainExtent = extent;                     // 保存尺寸
    }

    void createImageViews() {                // 创建图像视图
        swapChainImageViews.resize(swapChainImages.size());  // 调整大小

        for (uint32_t i = 0; i < swapChainImages.size(); i++) {  // 遍历交换链图像
            swapChainImageViews[i] = createImageView(swapChainImages[i], swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT);  // 创建视图
        }
    }

    void createRenderPass() {                // 创建渲染通道
        VkAttachmentDescription colorAttachment{};  // 颜色附件
        colorAttachment.format = swapChainImageFormat;  // 格式
        colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;  // 不多重采样
        colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;  // 清空
        colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;  // 存储
        colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;  // 模板不关心
        colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
        colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;  // 初始布局
        colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;  // 最终布局用于呈现

        VkAttachmentDescription depthAttachment{};  // 深度附件
        depthAttachment.format = findDepthFormat();  // 深度格式
        depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
        depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;  // 清空
        depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;  // 不存储
        depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
        depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
        depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
        depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;  // 最终布局

        VkAttachmentReference colorAttachmentRef{};  // 颜色附件引用
        colorAttachmentRef.attachment = 0;           // 附件索引0
        colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;  // 颜色附件布局

        VkAttachmentReference depthAttachmentRef{};  // 深度附件引用
        depthAttachmentRef.attachment = 1;           // 附件索引1
        depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;  // 深度布局

        VkSubpassDescription subpass{};              // 子通道描述
        subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;  // 图形绑定点
        subpass.colorAttachmentCount = 1;            // 颜色附件数
        subpass.pColorAttachments = &colorAttachmentRef;  // 颜色附件引用
        subpass.pDepthStencilAttachment = &depthAttachmentRef;  // 深度附件引用

        VkSubpassDependency dependency{};            // 子通道依赖
        dependency.srcSubpass = VK_SUBPASS_EXTERNAL; // 外部
        dependency.dstSubpass = 0;                   // 目标子通道0
        dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;  // 源阶段
        dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;  // 源访问
        dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;  // 目标阶段
        dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;  // 目标访问

        std::array<VkAttachmentDescription, 2> attachments = { colorAttachment, depthAttachment };  // 附件数组
        VkRenderPassCreateInfo renderPassInfo{};     // 渲染通道创建信息
        renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
        renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());  // 附件数量
        renderPassInfo.pAttachments = attachments.data();  // 附件数组
        renderPassInfo.subpassCount = 1;             // 子通道数量
        renderPassInfo.pSubpasses = &subpass;        // 子通道
        renderPassInfo.dependencyCount = 1;          // 依赖数量
        renderPassInfo.pDependencies = &dependency;  // 依赖

        if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {  // 创建渲染通道
            throw std::runtime_error("failed to create render pass!");
        }
    }

    void createDescriptorSetLayout() {        // 创建描述符集布局
        VkDescriptorSetLayoutBinding uboLayoutBinding{};  // UBO绑定
        uboLayoutBinding.binding = 0;            // 绑定索引0
        uboLayoutBinding.descriptorCount = 1;    // 描述符数量
        uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;  // Uniform缓冲类型
        uboLayoutBinding.pImmutableSamplers = nullptr;  // 无不可变采样器
        uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;  // 顶点着色器使用

        VkDescriptorSetLayoutBinding samplerLayoutBinding{};  // 采样器绑定
        samplerLayoutBinding.binding = 1;        // 绑定索引1
        samplerLayoutBinding.descriptorCount = 1;
        samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;  // 组合图像采样器
        samplerLayoutBinding.pImmutableSamplers = nullptr;
        samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;  // 片段着色器使用

        std::array<VkDescriptorSetLayoutBinding, 2> bindings = { uboLayoutBinding, samplerLayoutBinding };  // 两个绑定
        VkDescriptorSetLayoutCreateInfo layoutInfo{};  // 布局创建信息
        layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
        layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());  // 绑定数量
        layoutInfo.pBindings = bindings.data();  // 绑定数组

        if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {  // 创建布局
            throw std::runtime_error("failed to create descriptor set layout!");
        }
    }

    void createGraphicsPipeline() {           // 创建图形管线
        auto vertShaderCode = readFile("shaders/27_shader_depth.vert.spv");  // 读取顶点着色器SPIR-V
        auto fragShaderCode = readFile("shaders/27_shader_depth.frag.spv");  // 读取片段着色器SPIR-V

        VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);  // 创建顶点着色器模块
        VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);  // 创建片段着色器模块

        VkPipelineShaderStageCreateInfo vertShaderStageInfo{};  // 顶点着色阶段
        vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
        vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;  // 顶点阶段
        vertShaderStageInfo.module = vertShaderModule;           // 模块
        vertShaderStageInfo.pName = "main";                      // 入口函数名

        VkPipelineShaderStageCreateInfo fragShaderStageInfo{};  // 片段着色阶段
        fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
        fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;  // 片段阶段
        fragShaderStageInfo.module = fragShaderModule;
        fragShaderStageInfo.pName = "main";

        VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };  // 阶段数组

        VkPipelineVertexInputStateCreateInfo vertexInputInfo{};  // 顶点输入状态
        vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;

        auto bindingDescription = Vertex::getBindingDescription();       // 绑定描述
        auto attributeDescriptions = Vertex::getAttributeDescriptions(); // 属性描述

        vertexInputInfo.vertexBindingDescriptionCount = 1;               // 绑定数量
        vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());  // 属性数量
        vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;      // 绑定描述指针
        vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();  // 属性描述指针

        VkPipelineInputAssemblyStateCreateInfo inputAssembly{};  // 输入装配状态
        inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
        inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;  // 三角形列表
        inputAssembly.primitiveRestartEnable = VK_FALSE;  // 不启用图元重启

        VkPipelineViewportStateCreateInfo viewportState{};  // 视口状态
        viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
        viewportState.viewportCount = 1;         // 视口数量
        viewportState.scissorCount = 1;          // 剪裁数量

        VkPipelineRasterizationStateCreateInfo rasterizer{};  // 光栅化状态
        rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
        rasterizer.depthClampEnable = VK_FALSE;  // 不启用深度钳制
        rasterizer.rasterizerDiscardEnable = VK_FALSE;  // 不丢弃
        rasterizer.polygonMode = VK_POLYGON_MODE_FILL;  // 填充模式
        rasterizer.lineWidth = 1.0f;             // 线宽
        rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;  // 背面剔除
        rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;  // 逆时针为正面
        rasterizer.depthBiasEnable = VK_FALSE;   // 不启用深度偏移

        VkPipelineMultisampleStateCreateInfo multisampling{};  // 多重采样状态
        multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
        multisampling.sampleShadingEnable = VK_FALSE;  // 不启用采样着色
        multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;  // 1个采样

        VkPipelineDepthStencilStateCreateInfo depthStencil{};  // 深度模板状态
        depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
        depthStencil.depthTestEnable = VK_TRUE;  // 启用深度测试
        depthStencil.depthWriteEnable = VK_TRUE; // 启用深度写入
        depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;  // 深度比较:更小通过
        depthStencil.depthBoundsTestEnable = VK_FALSE;     // 不启用深度边界测试
        depthStencil.stencilTestEnable = VK_FALSE;         // 不启用模板测试

        VkPipelineColorBlendAttachmentState colorBlendAttachment{};  // 颜色混合附件
        colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;  // 写RGBA
        colorBlendAttachment.blendEnable = VK_FALSE;  // 不启用混合

        VkPipelineColorBlendStateCreateInfo colorBlending{};  // 颜色混合状态
        colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
        colorBlending.logicOpEnable = VK_FALSE;  // 不启用逻辑操作
        colorBlending.logicOp = VK_LOGIC_OP_COPY;  // 逻辑操作
        colorBlending.attachmentCount = 1;       // 附件数量
        colorBlending.pAttachments = &colorBlendAttachment;  // 附件
        colorBlending.blendConstants[0] = 0.0f;  // 混合常量
        colorBlending.blendConstants[1] = 0.0f;
        colorBlending.blendConstants[2] = 0.0f;
        colorBlending.blendConstants[3] = 0.0f;

        std::vector<VkDynamicState> dynamicStates = {  // 动态状态
            VK_DYNAMIC_STATE_VIEWPORT,           // 视口动态
            VK_DYNAMIC_STATE_SCISSOR             // 剪裁动态
        };
        VkPipelineDynamicStateCreateInfo dynamicState{};  // 动态状态创建信息
        dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
        dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());  // 数量
        dynamicState.pDynamicStates = dynamicStates.data();  // 数组

        VkPipelineLayoutCreateInfo pipelineLayoutInfo{};  // 管线布局创建信息
        pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
        pipelineLayoutInfo.setLayoutCount = 1;   // 描述符集布局数量
        pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;  // 描述符集布局

        if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {  // 创建管线布局
            throw std::runtime_error("failed to create pipeline layout!");
        }

        VkGraphicsPipelineCreateInfo pipelineInfo{};  // 图形管线创建信息
        pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
        pipelineInfo.stageCount = 2;             // 着色阶段数量
        pipelineInfo.pStages = shaderStages;     // 着色阶段
        pipelineInfo.pVertexInputState = &vertexInputInfo;   // 顶点输入状态
        pipelineInfo.pInputAssemblyState = &inputAssembly;   // 输入装配状态
        pipelineInfo.pViewportState = &viewportState;        // 视口状态
        pipelineInfo.pRasterizationState = &rasterizer;      // 光栅化状态
        pipelineInfo.pMultisampleState = &multisampling;     // 多重采样状态
        pipelineInfo.pDepthStencilState = &depthStencil;     // 深度模板状态
        pipelineInfo.pColorBlendState = &colorBlending;      // 颜色混合状态
        pipelineInfo.pDynamicState = &dynamicState;          // 动态状态
        pipelineInfo.layout = pipelineLayout;                // 管线布局
        pipelineInfo.renderPass = renderPass;                // 渲染通道
        pipelineInfo.subpass = 0;                            // 子通道索引
        pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;    // 无基础管线

        if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {  // 创建图形管线
            throw std::runtime_error("failed to create graphics pipeline!");
        }

        vkDestroyShaderModule(device, fragShaderModule, nullptr);  // 销毁片段着色器模块
        vkDestroyShaderModule(device, vertShaderModule, nullptr);  // 销毁顶点着色器模块
    }

    void createFramebuffers() {              // 创建帧缓冲
        swapChainFramebuffers.resize(swapChainImageViews.size());  // 调整大小

        for (size_t i = 0; i < swapChainImageViews.size(); i++) {  // 遍历图像视图
            std::array<VkImageView, 2> attachments = {  // 附件:颜色+深度
                swapChainImageViews[i],           // 颜色图像视图
                depthImageView                    // 深度图像视图
            };

            VkFramebufferCreateInfo framebufferInfo{};  // 帧缓冲创建信息
            framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
            framebufferInfo.renderPass = renderPass;    // 渲染通道
            framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());  // 附件数量
            framebufferInfo.pAttachments = attachments.data();  // 附件数组
            framebufferInfo.width = swapChainExtent.width;      // 宽度
            framebufferInfo.height = swapChainExtent.height;    // 高度
            framebufferInfo.layers = 1;              // 层数

            if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {  // 创建帧缓冲
                throw std::runtime_error("failed to create framebuffer!");
            }
        }
    }

    void createCommandPool() {               // 创建命令池
        QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);  // 队列族

        VkCommandPoolCreateInfo poolInfo{};  // 命令池创建信息
        poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
        poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;  // 允许重置命令缓冲
        poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();  // 图形队列族

        if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {  // 创建命令池
            throw std::runtime_error("failed to create graphics command pool!");
        }
    }

    void createDepthResources() {            // 创建深度资源
        VkFormat depthFormat = findDepthFormat();  // 查找深度格式

        createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);  // 创建深度图像
        depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);  // 创建深度图像视图
    }

    VkFormat findSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) {  // 查找支持的格式
        for (VkFormat format : candidates) { // 遍历候选格式
            VkFormatProperties props;        // 格式属性
            vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props);  // 查询属性

            if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) {  // 线性平铺支持
                return format;
            }
            else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) {  // 最优平铺支持
                return format;
            }
        }

        throw std::runtime_error("failed to find supported format!");
    }

    VkFormat findDepthFormat() {             // 查找深度格式
        return findSupportedFormat(
            { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },  // 候选格式
            VK_IMAGE_TILING_OPTIMAL,             // 最优平铺
            VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT  // 用作深度模板附件
        );
    }

    bool hasStencilComponent(VkFormat format) {  // 是否含模板分量
        return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
    }

    void createTextureImage() {              // 创建纹理图像
        int texWidth, texHeight, texChannels;  // 纹理宽高通道
        stbi_uc* pixels = stbi_load("textures/1.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);  // 加载图像
        VkDeviceSize imageSize = texWidth * texHeight * 4;  // 图像字节数(RGBA)

        if (!pixels) {                       // 加载失败
            throw std::runtime_error("failed to load texture image!");
        }

        VkBuffer stagingBuffer;              // 暂存缓冲
        VkDeviceMemory stagingBufferMemory;  // 暂存缓冲内存
        createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);  // 创建暂存缓冲

        void* data;                          // 映射指针
        vkMapMemory(device, stagingBufferMemory, 0, imageSize, 0, &data);  // 映射
        memcpy(data, pixels, static_cast<size_t>(imageSize));  // 拷贝像素
        vkUnmapMemory(device, stagingBufferMemory);  // 取消映射

        stbi_image_free(pixels);             // 释放图像数据

        createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory);  // 创建纹理图像

        transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);  // 转换布局为传输目标
        copyBufferToImage(stagingBuffer, textureImage, static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight));  // 拷贝缓冲到图像
        transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);  // 转换为着色器只读

        vkDestroyBuffer(device, stagingBuffer, nullptr);       // 销毁暂存缓冲
        vkFreeMemory(device, stagingBufferMemory, nullptr);    // 释放暂存缓冲内存
    }

    void createTextureImageView() {          // 创建纹理图像视图
        textureImageView = createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);  // 创建视图
    }

    void createTextureSampler() {            // 创建纹理采样器
        VkPhysicalDeviceProperties properties{};  // 物理设备属性
        vkGetPhysicalDeviceProperties(physicalDevice, &properties);  // 查询属性

        VkSamplerCreateInfo samplerInfo{};   // 采样器创建信息
        samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
        samplerInfo.magFilter = VK_FILTER_LINEAR;  // 放大过滤:线性
        samplerInfo.minFilter = VK_FILTER_LINEAR;  // 缩小过滤:线性
        samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;  // U方向重复
        samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;  // V方向重复
        samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;  // W方向重复
        samplerInfo.anisotropyEnable = VK_TRUE;  // 启用各向异性
        samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;  // 最大各向异性
        samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;  // 边界颜色
        samplerInfo.unnormalizedCoordinates = VK_FALSE;  // 使用归一化坐标
        samplerInfo.compareEnable = VK_FALSE;  // 不启用比较
        samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;  // 比较操作
        samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;  // mipmap线性

        if (vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) {  // 创建采样器
            throw std::runtime_error("failed to create texture sampler!");
        }
    }

    VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags) {  // 创建图像视图
        VkImageViewCreateInfo viewInfo{};    // 视图创建信息
        viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        viewInfo.image = image;              // 图像
        viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;  // 2D视图
        viewInfo.format = format;            // 格式
        viewInfo.subresourceRange.aspectMask = aspectFlags;  // 方面掩码
        viewInfo.subresourceRange.baseMipLevel = 0;  // 基础mip
        viewInfo.subresourceRange.levelCount = 1;    // mip层数
        viewInfo.subresourceRange.baseArrayLayer = 0;  // 基础数组层
        viewInfo.subresourceRange.layerCount = 1;    // 数组层数

        VkImageView imageView;               // 图像视图句柄
        if (vkCreateImageView(device, &viewInfo, nullptr, &imageView) != VK_SUCCESS) {  // 创建视图
            throw std::runtime_error("failed to create image view!");
        }

        return imageView;
    }

    void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {  // 创建图像
        VkImageCreateInfo imageInfo{};       // 图像创建信息
        imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
        imageInfo.imageType = VK_IMAGE_TYPE_2D;  // 2D图像
        imageInfo.extent.width = width;      // 宽度
        imageInfo.extent.height = height;    // 高度
        imageInfo.extent.depth = 1;          // 深度1
        imageInfo.mipLevels = 1;             // mip层数
        imageInfo.arrayLayers = 1;           // 数组层数
        imageInfo.format = format;           // 格式
        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!");
        }

        VkMemoryRequirements memRequirements;  // 内存需求
        vkGetImageMemoryRequirements(device, image, &memRequirements);  // 查询需求

        VkMemoryAllocateInfo allocInfo{};    // 内存分配信息
        allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
        allocInfo.allocationSize = memRequirements.size;  // 分配大小
        allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);  // 内存类型

        if (vkAllocateMemory(device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) {  // 分配内存
            throw std::runtime_error("failed to allocate image memory!");
        }

        vkBindImageMemory(device, image, imageMemory, 0);  // 绑定内存
    }

    void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) {  // 转换图像布局
        VkCommandBuffer commandBuffer = beginSingleTimeCommands();  // 开始一次性命令

        VkImageMemoryBarrier barrier{};      // 图像内存屏障
        barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
        barrier.oldLayout = oldLayout;       // 旧布局
        barrier.newLayout = newLayout;       // 新布局
        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;  // 忽略源队列族
        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;  // 忽略目标队列族
        barrier.image = image;               // 图像
        barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;  // 颜色方面
        barrier.subresourceRange.baseMipLevel = 0;
        barrier.subresourceRange.levelCount = 1;
        barrier.subresourceRange.baseArrayLayer = 0;
        barrier.subresourceRange.layerCount = 1;

        VkPipelineStageFlags sourceStage;    // 源阶段
        VkPipelineStageFlags destinationStage;  // 目标阶段

        if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {  // 未定义->传输目标
            barrier.srcAccessMask = 0;       // 无需等待
            barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;  // 传输写

            sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;  // 顶部
            destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;  // 传输阶段
        }
        else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {  // 传输目标->着色器只读
            barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;  // 传输写
            barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;     // 着色器读

            sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;          // 传输阶段
            destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;  // 片段着色器
        }
        else {
            throw std::invalid_argument("unsupported layout transition!");  // 不支持的转换
        }

        vkCmdPipelineBarrier(                // 记录管线屏障
            commandBuffer,
            sourceStage, destinationStage,
            0,
            0, nullptr,
            0, nullptr,
            1, &barrier
        );

        endSingleTimeCommands(commandBuffer);  // 结束一次性命令
    }

    void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height) {  // 拷贝缓冲到图像
        VkCommandBuffer commandBuffer = beginSingleTimeCommands();  // 开始一次性命令

        VkBufferImageCopy region{};          // 拷贝区域
        region.bufferOffset = 0;             // 缓冲偏移
        region.bufferRowLength = 0;          // 行长度
        region.bufferImageHeight = 0;        // 图像高度
        region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;  // 颜色方面
        region.imageSubresource.mipLevel = 0;
        region.imageSubresource.baseArrayLayer = 0;
        region.imageSubresource.layerCount = 1;
        region.imageOffset = { 0, 0, 0 };    // 图像偏移
        region.imageExtent = {
            width,
            height,
            1
        };

        vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);  // 记录拷贝

        endSingleTimeCommands(commandBuffer);  // 结束一次性命令
    }

    void createVertexBuffer() {              // 创建顶点缓冲
        VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();  // 缓冲大小

        VkBuffer stagingBuffer;              // 暂存缓冲
        VkDeviceMemory stagingBufferMemory;
        createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);  // 创建暂存缓冲

        void* data;
        vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);  // 映射
        memcpy(data, vertices.data(), (size_t)bufferSize);  // 拷贝顶点
        vkUnmapMemory(device, stagingBufferMemory);  // 取消映射

        createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);  // 创建顶点缓冲

        copyBuffer(stagingBuffer, vertexBuffer, bufferSize);  // 拷贝到设备本地

        vkDestroyBuffer(device, stagingBuffer, nullptr);     // 销毁暂存缓冲
        vkFreeMemory(device, stagingBufferMemory, nullptr);  // 释放内存
    }

    void createIndexBuffer() {               // 创建索引缓冲
        VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size();  // 缓冲大小

        VkBuffer stagingBuffer;              // 暂存缓冲
        VkDeviceMemory stagingBufferMemory;
        createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);

        void* data;
        vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
        memcpy(data, indices.data(), (size_t)bufferSize);  // 拷贝索引
        vkUnmapMemory(device, stagingBufferMemory);

        createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);  // 创建索引缓冲

        copyBuffer(stagingBuffer, indexBuffer, bufferSize);  // 拷贝到设备本地

        vkDestroyBuffer(device, stagingBuffer, nullptr);
        vkFreeMemory(device, stagingBufferMemory, nullptr);
    }

    void createUniformBuffers() {            // 创建Uniform缓冲
        VkDeviceSize bufferSize = sizeof(UniformBufferObject);  // 缓冲大小

        uniformBuffers.resize(MAX_FRAMES_IN_FLIGHT);        // 每帧一个
        uniformBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);
        uniformBuffersMapped.resize(MAX_FRAMES_IN_FLIGHT);

        for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {  // 遍历每帧
            createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers[i], uniformBuffersMemory[i]);  // 创建Uniform缓冲

            vkMapMemory(device, uniformBuffersMemory[i], 0, bufferSize, 0, &uniformBuffersMapped[i]);  // 持久映射
        }
    }

    void createDescriptorPool() {            // 创建描述符池
        std::array<VkDescriptorPoolSize, 2> poolSizes{};  // 池大小
        poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;  // UBO类型
        poolSizes[0].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);  // 每帧一个
        poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;  // 采样器类型
        poolSizes[1].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);

        VkDescriptorPoolCreateInfo poolInfo{};  // 池创建信息
        poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
        poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());  // 池大小数量
        poolInfo.pPoolSizes = poolSizes.data();  // 池大小
        poolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);  // 最大集合数

        if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {  // 创建池
            throw std::runtime_error("failed to create descriptor pool!");
        }
    }

    void createDescriptorSets() {            // 创建描述符集
        std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout);  // 布局数组
        VkDescriptorSetAllocateInfo allocInfo{};  // 分配信息
        allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
        allocInfo.descriptorPool = descriptorPool;  // 池
        allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);  // 数量
        allocInfo.pSetLayouts = layouts.data();  // 布局

        descriptorSets.resize(MAX_FRAMES_IN_FLIGHT);  // 调整大小
        if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {  // 分配
            throw std::runtime_error("failed to allocate descriptor sets!");
        }

        for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {  // 遍历每帧
            VkDescriptorBufferInfo bufferInfo{};  // 缓冲信息
            bufferInfo.buffer = uniformBuffers[i];  // Uniform缓冲
            bufferInfo.offset = 0;               // 偏移
            bufferInfo.range = sizeof(UniformBufferObject);  // 范围

            VkDescriptorImageInfo imageInfo{};   // 图像信息
            imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;  // 布局
            imageInfo.imageView = textureImageView;  // 图像视图
            imageInfo.sampler = textureSampler;  // 采样器

            std::array<VkWriteDescriptorSet, 2> descriptorWrites{};  // 描述符写入

            descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
            descriptorWrites[0].dstSet = descriptorSets[i];  // 目标集合
            descriptorWrites[0].dstBinding = 0;  // 绑定0
            descriptorWrites[0].dstArrayElement = 0;
            descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
            descriptorWrites[0].descriptorCount = 1;
            descriptorWrites[0].pBufferInfo = &bufferInfo;  // 缓冲信息

            descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
            descriptorWrites[1].dstSet = descriptorSets[i];
            descriptorWrites[1].dstBinding = 1;  // 绑定1
            descriptorWrites[1].dstArrayElement = 0;
            descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
            descriptorWrites[1].descriptorCount = 1;
            descriptorWrites[1].pImageInfo = &imageInfo;  // 图像信息

            vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);  // 更新描述符集
        }
    }

    void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {  // 创建缓冲
        VkBufferCreateInfo bufferInfo{};     // 缓冲创建信息
        bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
        bufferInfo.size = size;              // 大小
        bufferInfo.usage = usage;            // 用途
        bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;  // 独占

        if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {  // 创建缓冲
            throw std::runtime_error("failed to create buffer!");
        }

        VkMemoryRequirements memRequirements;  // 内存需求
        vkGetBufferMemoryRequirements(device, buffer, &memRequirements);  // 查询

        VkMemoryAllocateInfo allocInfo{};    // 分配信息
        allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
        allocInfo.allocationSize = memRequirements.size;  // 大小
        allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);  // 类型

        if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {  // 分配
            throw std::runtime_error("failed to allocate buffer memory!");
        }

        vkBindBufferMemory(device, buffer, bufferMemory, 0);  // 绑定
    }

    VkCommandBuffer beginSingleTimeCommands() {  // 开始一次性命令
        VkCommandBufferAllocateInfo allocInfo{};  // 分配信息
        allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
        allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;  // 主命令缓冲
        allocInfo.commandPool = commandPool;  // 命令池
        allocInfo.commandBufferCount = 1;     // 数量

        VkCommandBuffer commandBuffer;        // 命令缓冲
        vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);  // 分配

        VkCommandBufferBeginInfo beginInfo{};  // 开始信息
        beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
        beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;  // 一次提交

        vkBeginCommandBuffer(commandBuffer, &beginInfo);  // 开始记录

        return commandBuffer;
    }

    void endSingleTimeCommands(VkCommandBuffer commandBuffer) {  // 结束一次性命令
        vkEndCommandBuffer(commandBuffer);   // 结束记录

        VkSubmitInfo submitInfo{};           // 提交信息
        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
        submitInfo.commandBufferCount = 1;
        submitInfo.pCommandBuffers = &commandBuffer;

        vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);  // 提交
        vkQueueWaitIdle(graphicsQueue);      // 等待完成

        vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);  // 释放命令缓冲
    }

    void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {  // 拷贝缓冲
        VkCommandBuffer commandBuffer = beginSingleTimeCommands();  // 开始一次性命令

        VkBufferCopy copyRegion{};           // 拷贝区域
        copyRegion.size = size;              // 大小
        vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);  // 记录拷贝

        endSingleTimeCommands(commandBuffer);  // 结束
    }

    uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {  // 查找内存类型
        VkPhysicalDeviceMemoryProperties memProperties;  // 内存属性
        vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);  // 查询

        for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {  // 遍历内存类型
            if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {  // 匹配
                return i;
            }
        }

        throw std::runtime_error("failed to find suitable memory type!");
    }

    void createCommandBuffers() {            // 创建命令缓冲
        commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);  // 每帧一个

        VkCommandBufferAllocateInfo allocInfo{};  // 分配信息
        allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
        allocInfo.commandPool = commandPool;  // 命令池
        allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;  // 主命令缓冲
        allocInfo.commandBufferCount = (uint32_t)commandBuffers.size();  // 数量

        if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {  // 分配
            throw std::runtime_error("failed to allocate command buffers!");
        }
    }

    void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {  // 记录命令缓冲
        VkCommandBufferBeginInfo beginInfo{};  // 开始信息
        beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;

        if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {  // 开始记录
            throw std::runtime_error("failed to begin recording command buffer!");
        }

        VkRenderPassBeginInfo renderPassInfo{};  // 渲染通道开始信息
        renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
        renderPassInfo.renderPass = renderPass;  // 渲染通道
        renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex];  // 帧缓冲
        renderPassInfo.renderArea.offset = { 0, 0 };  // 渲染区域偏移
        renderPassInfo.renderArea.extent = swapChainExtent;  // 渲染区域尺寸

        std::array<VkClearValue, 2> clearValues{};  // 清空值
        clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} };  // 黑色
        clearValues[1].depthStencil = { 1.0f, 0 };  // 深度1.0

        renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());  // 数量
        renderPassInfo.pClearValues = clearValues.data();  // 清空值

        vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);  // 开始渲染通道

        vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);  // 绑定图形管线

        VkViewport viewport{};               // 视口
        viewport.x = 0.0f;                   // x
        viewport.y = 0.0f;                   // y
        viewport.width = (float)swapChainExtent.width;   // 宽
        viewport.height = (float)swapChainExtent.height; // 高
        viewport.minDepth = 0.0f;            // 最小深度
        viewport.maxDepth = 1.0f;            // 最大深度
        vkCmdSetViewport(commandBuffer, 0, 1, &viewport);  // 设置视口

        VkRect2D scissor{};                  // 剪裁矩形
        scissor.offset = { 0, 0 };           // 偏移
        scissor.extent = swapChainExtent;    // 尺寸
        vkCmdSetScissor(commandBuffer, 0, 1, &scissor);  // 设置剪裁

        VkBuffer vertexBuffers[] = { vertexBuffer };  // 顶点缓冲
        VkDeviceSize offsets[] = { 0 };      // 偏移
        vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);  // 绑定顶点缓冲

        vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT16);  // 绑定索引缓冲

        vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[currentFrame], 0, nullptr);  // 绑定描述符集

        vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);  // 绘制索引

        vkCmdEndRenderPass(commandBuffer);   // 结束渲染通道

        if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {  // 结束记录
            throw std::runtime_error("failed to record command buffer!");
        }
    }

    void createSyncObjects() {               // 创建同步对象
        imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);  // 图像可用信号量
        renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);  // 渲染完成信号量
        inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);            // 在途围栏

        VkSemaphoreCreateInfo semaphoreInfo{};  // 信号量创建信息
        semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;

        VkFenceCreateInfo fenceInfo{};       // 围栏创建信息
        fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
        fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;  // 初始为已触发

        for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {  // 遍历每帧
            if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS ||  // 创建图像可用信号量
                vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS ||  // 创建渲染完成信号量
                vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) {  // 创建围栏
                throw std::runtime_error("failed to create synchronization objects for a frame!");
            }
        }
    }

    void updateUniformBuffer(uint32_t currentImage) {  // 更新Uniform缓冲
        static auto startTime = std::chrono::high_resolution_clock::now();  // 起始时间

        auto currentTime = std::chrono::high_resolution_clock::now();  // 当前时间
        float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();  // 经过秒数

        UniformBufferObject ubo{};           // Uniform数据
        ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));  // 绕Z轴旋转
        ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));  // 视图矩阵
        ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float)swapChainExtent.height, 0.1f, 10.0f);  // 投影矩阵
        ubo.proj[1][1] *= -1;               // 翻转Y,因为Vulkan的Y轴向下

        memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo));  // 拷贝到映射内存
    }

    void drawFrame() {                       // 绘制一帧
        vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);  // 等待当前帧围栏

        uint32_t imageIndex;                 // 图像索引
        VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);  // 获取下一张图像

        if (result == VK_ERROR_OUT_OF_DATE_KHR) {  // 交换链过期
            recreateSwapChain();             // 重建
            return;
        }
        else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {  // 其他错误
            throw std::runtime_error("failed to acquire swap chain image!");
        }

        updateUniformBuffer(currentFrame);   // 更新Uniform

        vkResetFences(device, 1, &inFlightFences[currentFrame]);  // 重置围栏

        vkResetCommandBuffer(commandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);  // 重置命令缓冲
        recordCommandBuffer(commandBuffers[currentFrame], imageIndex);  // 记录命令

        VkSubmitInfo submitInfo{};           // 提交信息
        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

        VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };  // 等待信号量
        VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };  // 等待阶段
        submitInfo.waitSemaphoreCount = 1;   // 等待数量
        submitInfo.pWaitSemaphores = waitSemaphores;  // 等待信号量
        submitInfo.pWaitDstStageMask = waitStages;    // 等待阶段

        submitInfo.commandBufferCount = 1;   // 命令缓冲数量
        submitInfo.pCommandBuffers = &commandBuffers[currentFrame];  // 命令缓冲

        VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };  // 信号信号量
        submitInfo.signalSemaphoreCount = 1;  // 信号数量
        submitInfo.pSignalSemaphores = signalSemaphores;  // 信号信号量

        if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {  // 提交
            throw std::runtime_error("failed to submit draw command buffer!");
        }

        VkPresentInfoKHR presentInfo{};      // 呈现信息
        presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;

        presentInfo.waitSemaphoreCount = 1;  // 等待数量
        presentInfo.pWaitSemaphores = signalSemaphores;  // 等待信号量

        VkSwapchainKHR swapChains[] = { swapChain };  // 交换链
        presentInfo.swapchainCount = 1;      // 交换链数量
        presentInfo.pSwapchains = swapChains;  // 交换链

        presentInfo.pImageIndices = &imageIndex;  // 图像索引

        result = vkQueuePresentKHR(presentQueue, &presentInfo);  // 呈现

        if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {  // 需要重建
            framebufferResized = false;
            recreateSwapChain();
        }
        else if (result != VK_SUCCESS) {     // 其他错误
            throw std::runtime_error("failed to present swap chain image!");
        }

        currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;  // 下一帧
    }

    VkShaderModule createShaderModule(const std::vector<char>& code) {  // 创建着色器模块
        VkShaderModuleCreateInfo createInfo{};  // 创建信息
        createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
        createInfo.codeSize = code.size();   // 代码大小
        createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());  // 代码指针

        VkShaderModule shaderModule;         // 着色器模块
        if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {  // 创建
            throw std::runtime_error("failed to create shader module!");
        }

        return shaderModule;
    }

    VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {  // 选择表面格式
        for (const auto& availableFormat : availableFormats) {  // 遍历
            if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {  // 优选SRGB
                return availableFormat;
            }
        }

        return availableFormats[0];          // 否则取第一个
    }

    VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes) {  // 选择呈现模式
        for (const auto& availablePresentMode : availablePresentModes) {  // 遍历
            if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {  // 优选Mailbox(低延迟)
                return availablePresentMode;
            }
        }

        return VK_PRESENT_MODE_FIFO_KHR;     // 否则用FIFO(垂直同步)
    }

    VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) {  // 选择交换范围
        if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {  // 已指定
            return capabilities.currentExtent;
        }
        else {
            int width, height;
            glfwGetFramebufferSize(window, &width, &height);  // 获取窗口尺寸

            VkExtent2D actualExtent = {
                static_cast<uint32_t>(width),
                static_cast<uint32_t>(height)
            };

            actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);  // 钳制
            actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);

            return actualExtent;
        }
    }

    SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) {  // 查询交换链支持
        SwapChainSupportDetails details;     // 详情

        vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);  // 表面能力

        uint32_t formatCount;
        vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);  // 格式数量

        if (formatCount != 0) {
            details.formats.resize(formatCount);
            vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());  // 获取格式
        }

        uint32_t presentModeCount;
        vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);  // 呈现模式数量

        if (presentModeCount != 0) {
            details.presentModes.resize(presentModeCount);
            vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());  // 获取呈现模式
        }

        return details;
    }

    bool isDeviceSuitable(VkPhysicalDevice device) {  // 判断设备是否合适
        QueueFamilyIndices indices = findQueueFamilies(device);  // 队列族

        bool extensionsSupported = checkDeviceExtensionSupport(device);  // 扩展支持

        bool swapChainAdequate = false;
        if (extensionsSupported) {
            SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device);  // 查询交换链支持
            swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();  // 非空
        }

        VkPhysicalDeviceFeatures supportedFeatures;
        vkGetPhysicalDeviceFeatures(device, &supportedFeatures);  // 查询特性

        return indices.isComplete() && extensionsSupported && swapChainAdequate && supportedFeatures.samplerAnisotropy;  // 全部满足
    }

    bool checkDeviceExtensionSupport(VkPhysicalDevice device) {  // 检查设备扩展支持
        uint32_t extensionCount;
        vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);  // 扩展数量

        std::vector<VkExtensionProperties> availableExtensions(extensionCount);
        vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());  // 获取扩展

        std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());  // 需要的扩展

        for (const auto& extension : availableExtensions) {  // 遍历可用扩展
            requiredExtensions.erase(extension.extensionName);  // 移除已满足的
        }

        return requiredExtensions.empty();   // 全部满足则返回true
    }

    QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {  // 查找队列族
        QueueFamilyIndices indices;          // 索引

        uint32_t queueFamilyCount = 0;
        vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);  // 队列族数量

        std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
        vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());  // 获取队列族

        int i = 0;
        for (const auto& queueFamily : queueFamilies) {  // 遍历
            if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {  // 支持图形
                indices.graphicsFamily = i;
            }

            VkBool32 presentSupport = false;
            vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);  // 查询呈现支持

            if (presentSupport) {            // 支持呈现
                indices.presentFamily = i;
            }

            if (indices.isComplete()) {      // 都找到则退出
                break;
            }

            i++;
        }

        return indices;
    }

    std::vector<const char*> getRequiredExtensions() {  // 获取所需实例扩展
        uint32_t glfwExtensionCount = 0;
        const char** glfwExtensions;
        glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);  // GLFW需要的扩展

        std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);  // 拷贝

        if (enableValidationLayers) {        // 启用校验层时
            extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);  // 添加调试工具扩展
        }

        return extensions;
    }

    bool checkValidationLayerSupport() {     // 检查校验层支持
        uint32_t layerCount;
        vkEnumerateInstanceLayerProperties(&layerCount, nullptr);  // 层数量

        std::vector<VkLayerProperties> availableLayers(layerCount);
        vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());  // 获取层

        for (const char* layerName : validationLayers) {  // 遍历需要的层
            bool layerFound = false;

            for (const auto& layerProperties : availableLayers) {  // 遍历可用层
                if (strcmp(layerName, layerProperties.layerName) == 0) {  // 匹配
                    layerFound = true;
                    break;
                }
            }

            if (!layerFound) {               // 未找到
                return false;
            }
        }

        return true;
    }

    static std::vector<char> readFile(const std::string& filename) {  // 读取文件
        std::ifstream file(filename, std::ios::ate | std::ios::binary);  // 以二进制打开,定位到末尾

        if (!file.is_open()) {               // 打开失败
            throw std::runtime_error("failed to open file!");
        }

        size_t fileSize = (size_t)file.tellg();  // 文件大小
        std::vector<char> buffer(fileSize);  // 缓冲

        file.seekg(0);                       // 回到开头
        file.read(buffer.data(), fileSize);  // 读取

        file.close();                        // 关闭

        return buffer;
    }

    static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {  // 调试回调
        std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;  // 打印校验层消息

        return VK_FALSE;                     // 不中止调用
    }
};

int main() {                                 // 程序入口
    HelloTriangleApplication app;            // 创建应用

    try {
        app.run();                           // 运行
    }
    catch (const std::exception& e) {        // 捕获异常
        std::cerr << e.what() << std::endl;  // 打印错误
        return EXIT_FAILURE;                 // 返回失败
    }

    return EXIT_SUCCESS;                     // 返回成功
}

...全文
15 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

4

社区成员

发帖
与我相关
我的任务
社区描述
openTK、OpenGL、WebGL技术学习交流
图形渲染c#程序人生 技术论坛(原bbs) 广东省·深圳市
社区管理员
  • 亿只小灿灿
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧