Vulkan——Mipmap

OpenTK 2026-09-11 10:13:46

#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]
#define GLM_ENABLE_EXPERIMENTAL              // 启用GLM实验性功能(gtx/hash.hpp需要)
#include <glm/glm.hpp>                       // GLM数学库核心
#include <glm/gtc/matrix_transform.hpp>      // GLM矩阵变换函数(perspective/lookAt/rotate)
#include <glm/gtx/hash.hpp>                  // GLM的hash支持(用于给vec3/vec2计算哈希)

#define STB_IMAGE_IMPLEMENTATION             // 定义此宏以生成stb_image实现代码
#include <stb_image.h>                       // stb_image图像加载库

#define TINYOBJLOADER_IMPLEMENTATION         // 定义此宏以生成tinyobjloader实现代码
#include <tiny_obj_loader.h>                 // tinyobjloader模型加载库

#include <iostream>                          // 标准输入输出流
#include <fstream>                           // 文件读写
#include <stdexcept>                         // 标准异常类
#include <algorithm>                         // std::clamp/std::max/std::min等算法
#include <chrono>                            // 时间库,用于动画
#include <vector>                            // 动态数组
#include <cstring>                           // memcpy/strcmp
#include <cstdlib>                           // EXIT_SUCCESS/EXIT_FAILURE
#include <cstdint>                           // 固定宽度整型
#include <limits>                            // std::numeric_limits
#include <array>                             // std::array
#include <optional>                          // std::optional
#include <set>                               // std::set
#include <unordered_map>                     // 哈希表,用于顶点去重
#include <cmath>                             // std::floor/std::log2(mipmap层数计算用)

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

const std::string MODEL_PATH = "models/viking_room.obj";   // 模型文件路径
const std::string TEXTURE_PATH = "textures/viking_room.png";  // 纹理文件路径

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;                               // 绑定索引(对应shader里的binding)
        bindingDescription.stride = sizeof(Vertex);                   // 每个顶点占用的字节数(跨距)
        bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;   // 逐顶点前进(而不是逐实例)

        return bindingDescription;
    }

    static std::array<VkVertexInputAttributeDescription, 3> getAttributeDescriptions() {  // 顶点属性描述:告诉管线每个属性的位置/格式/偏移
        std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{};

        attributeDescriptions[0].binding = 0;                         // 属于绑定0
        attributeDescriptions[0].location = 0;                        // 着色器中的location=0
        attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; // 3个32位浮点(vec3)
        attributeDescriptions[0].offset = offsetof(Vertex, pos);      // pos字段在结构体中的字节偏移

        attributeDescriptions[1].binding = 0;                         // 属于绑定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;                         // 属于绑定0
        attributeDescriptions[2].location = 2;                        // 着色器中的location=2
        attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;    // 2个32位浮点(vec2)
        attributeDescriptions[2].offset = offsetof(Vertex, texCoord); // texCoord字段偏移

        return attributeDescriptions;
    }

    bool operator==(const Vertex& other) const {  // 相等运算符,供unordered_map去重使用
        return pos == other.pos && color == other.color && texCoord == other.texCoord;  // 三个字段都相等才算相等
    }
};

namespace std {
    template<> struct hash<Vertex> {         // 为Vertex特化std::hash,使其可作为unordered_map的键
        size_t operator()(Vertex const& vertex) const {  // 哈希函数
            return ((hash<glm::vec3>()(vertex.pos) ^ (hash<glm::vec3>()(vertex.color) << 1)) >> 1) ^ (hash<glm::vec2>()(vertex.texCoord) << 1);  // 组合各字段的哈希
        }
    };
}

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

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;                         // 逻辑设备(应用程序与GPU交互的接口)

    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;         // 管线布局(描述符集布局 + push常量)
    VkPipeline graphicsPipeline;             // 图形管线(固定的渲染状态集合)

    VkCommandPool commandPool;               // 命令池(分配命令缓冲)

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

    uint32_t mipLevels;                      // 纹理的mipmap层数(新增)
    VkImage textureImage;                    // 纹理图像
    VkDeviceMemory textureImageMemory;       // 纹理图像内存
    VkImageView textureImageView;            // 纹理图像视图
    VkSampler textureSampler;                // 纹理采样器

    std::vector<Vertex> vertices;            // 顶点数据(从模型加载)
    std::vector<uint32_t> indices;           // 索引数据(从模型加载)
    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();                // 创建纹理图像(含mipmap生成)
        createTextureImageView();            // 创建纹理图像视图
        createTextureSampler();              // 创建纹理采样器
        loadModel();                         // 加载模型
        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) {  // 最小化时尺寸为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;          // 队列优先级(0.0~1.0)
        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) {  // 不超过最大值(0表示无上限)
            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;        // 数组层数(非立体则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;  // 合成alpha:不透明
        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, 1);  // 创建视图(mipLevels=1)
        }
    }

    void createRenderPass() {                // 创建渲染通道
        VkAttachmentDescription colorAttachment{};  // 颜色附件描述
        colorAttachment.format = swapChainImageFormat;  // 格式:与交换链一致
        colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;  // 采样数:1(非MSAA)
        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;  // 采样数:1
        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;           // 对应attachments[0]
        colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;  // 用作颜色附件时的布局

        VkAttachmentReference depthAttachmentRef{};  // 深度附件引用
        depthAttachmentRef.attachment = 1;           // 对应attachments[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(非MSAA)

        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;  // 混合常量R
        colorBlending.blendConstants[1] = 0.0f;  // 混合常量G
        colorBlending.blendConstants[2] = 0.0f;  // 混合常量B
        colorBlending.blendConstants[3] = 0.0f;  // 混合常量A

        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, 1, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);  // 创建深度图像(mipLevels=1)
        depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);  // 创建深度图像视图
    }

    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() {              // 创建纹理图像(含mipmap)
        int texWidth, texHeight, texChannels;  // 纹理宽高通道
        stbi_uc* pixels = stbi_load(TEXTURE_PATH.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);  // 加载图像(强制RGBA)
        VkDeviceSize imageSize = texWidth * texHeight * 4;  // 图像字节数
        mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1;  // 计算mipmap层数:log2(最大边)+1

        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, mipLevels, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory);  // 创建纹理图像(含mip层,用途含传输源/目标/采样)

        transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, mipLevels);  // 转为传输目标布局(所有mip层)
        copyBufferToImage(stagingBuffer, textureImage, static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight));  // 拷贝缓冲到图像(第0层)
        // 之后会在generateMipmaps中转为SHADER_READ_ONLY_OPTIMAL

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

        generateMipmaps(textureImage, VK_FORMAT_R8G8B8A8_SRGB, texWidth, texHeight, mipLevels);  // 生成mipmap
    }

    void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) {  // 生成mipmap(新增)
        // 检查图像格式是否支持线性blit
        VkFormatProperties formatProperties;  // 格式属性
        vkGetPhysicalDeviceFormatProperties(physicalDevice, imageFormat, &formatProperties);  // 查询

        if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {  // 不支持线性过滤
            throw std::runtime_error("texture image format does not support linear blitting!");
        }

        VkCommandBuffer commandBuffer = beginSingleTimeCommands();  // 开始一次性命令

        VkImageMemoryBarrier barrier{};      // 图像内存屏障
        barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;  // 结构体类型
        barrier.image = image;               // 图像
        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;  // 忽略源队列族
        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;  // 忽略目标队列族
        barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;  // 颜色方面
        barrier.subresourceRange.baseArrayLayer = 0;  // 基础数组层
        barrier.subresourceRange.layerCount = 1;      // 数组层数
        barrier.subresourceRange.levelCount = 1;      // mip层数(逐个处理)

        int32_t mipWidth = texWidth;         // 当前mip宽度
        int32_t mipHeight = texHeight;       // 当前mip高度

        for (uint32_t i = 1; i < mipLevels; i++) {  // 从第1层开始逐层生成
            barrier.subresourceRange.baseMipLevel = i - 1;  // 上一层作为源
            barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;  // 旧布局:传输目标
            barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;  // 新布局:传输源
            barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;  // 源访问:传输写
            barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;   // 目标访问:传输读

            vkCmdPipelineBarrier(commandBuffer,
                VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,  // 源/目标阶段:传输
                0, nullptr,
                0, nullptr,
                1, &barrier);

            VkImageBlit blit{};              // 图像blit区域
            blit.srcOffsets[0] = { 0, 0, 0 };  // 源起点
            blit.srcOffsets[1] = { mipWidth, mipHeight, 1 };  // 源终点
            blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;  // 源方面
            blit.srcSubresource.mipLevel = i - 1;  // 源mip层
            blit.srcSubresource.baseArrayLayer = 0;  // 源基础层
            blit.srcSubresource.layerCount = 1;      // 源层数
            blit.dstOffsets[0] = { 0, 0, 0 };  // 目标起点
            blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 };  // 目标终点(尺寸减半)
            blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;  // 目标方面
            blit.dstSubresource.mipLevel = i;  // 目标mip层
            blit.dstSubresource.baseArrayLayer = 0;  // 目标基础层
            blit.dstSubresource.layerCount = 1;      // 目标层数

            vkCmdBlitImage(commandBuffer,
                image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,  // 源图像+布局
                image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,  // 目标图像+布局
                1, &blit,                                     // blit区域
                VK_FILTER_LINEAR);                            // 线性过滤

            barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;  // 旧布局:传输源
            barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;  // 新布局:着色器只读
            barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;  // 源访问:传输读
            barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;    // 目标访问:着色器读

            vkCmdPipelineBarrier(commandBuffer,
                VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,  // 源:传输;目标:片段着色器
                0, nullptr,
                0, nullptr,
                1, &barrier);

            if (mipWidth > 1) mipWidth /= 2;  // 下一层宽度减半
            if (mipHeight > 1) mipHeight /= 2;  // 下一层高度减半
        }

        barrier.subresourceRange.baseMipLevel = mipLevels - 1;  // 最后一层
        barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;  // 旧布局:传输目标
        barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;  // 新布局:着色器只读
        barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;  // 源访问:传输写
        barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;     // 目标访问:着色器读

        vkCmdPipelineBarrier(commandBuffer,
            VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,  // 源:传输;目标:片段着色器
            0, nullptr,
            0, nullptr,
            1, &barrier);

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

    void createTextureImageView() {          // 创建纹理图像视图
        textureImageView = createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, mipLevels);  // 视图包含所有mip层
    }

    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;  // 使用归一化坐标[0,1]
        samplerInfo.compareEnable = VK_FALSE;  // 不启用比较(非阴影采样器)
        samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;  // 比较操作(未启用时无意义)
        samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;  // mipmap过滤:线性
        samplerInfo.minLod = 0.0f;           // 最小LOD(mip层级)
        samplerInfo.maxLod = VK_LOD_CLAMP_NONE;  // 最大LOD:不限制(使用全部mip层)
        samplerInfo.mipLodBias = 0.0f;       // LOD偏置

        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, uint32_t mipLevels) {  // 创建图像视图
        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 = mipLevels;  // 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, uint32_t mipLevels, 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 = mipLevels;     // 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;  // 采样数:1
        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, uint32_t mipLevels) {  // 转换图像布局
        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;  // 基础mip层
        barrier.subresourceRange.levelCount = mipLevels;  // 所有mip层
        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;          // 缓冲行长度(0表示紧密排列)
        region.bufferImageHeight = 0;        // 缓冲图像高度(0表示紧密排列)
        region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;  // 颜色方面
        region.imageSubresource.mipLevel = 0;  // mip层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 loadModel() {                       // 加载模型
        tinyobj::attrib_t attrib;            // 模型属性(顶点/法线/纹理坐标)
        std::vector<tinyobj::shape_t> shapes;      // 形状列表
        std::vector<tinyobj::material_t> materials;  // 材质列表
        std::string warn, err;               // 警告/错误信息

        if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, MODEL_PATH.c_str())) {  // 加载OBJ文件
            throw std::runtime_error(warn + err);  // 失败抛错
        }

        std::unordered_map<Vertex, uint32_t> uniqueVertices{};  // 顶点去重表

        for (const auto& shape : shapes) {   // 遍历形状
            for (const auto& index : shape.mesh.indices) {  // 遍历索引
                Vertex vertex{};             // 顶点

                vertex.pos = {               // 位置
                    attrib.vertices[3 * index.vertex_index + 0],
                    attrib.vertices[3 * index.vertex_index + 1],
                    attrib.vertices[3 * index.vertex_index + 2]
                };

                vertex.texCoord = {          // 纹理坐标(V翻转,OBJ原点在左下,Vulkan在左上)
                    attrib.texcoords[2 * index.texcoord_index + 0],
                    1.0f - attrib.texcoords[2 * index.texcoord_index + 1]
                };

                vertex.color = { 1.0f, 1.0f, 1.0f };  // 颜色默认白色

                if (uniqueVertices.count(vertex) == 0) {  // 新顶点
                    uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size());  // 记录索引
                    vertices.push_back(vertex);  // 添加顶点
                }

                indices.push_back(uniqueVertices[vertex]);  // 添加索引
            }
        }
    }

    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;  // 类型:Uniform缓冲
        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;  // 数组元素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;  // 数组元素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,模板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_UINT32);  // 绑定索引缓冲(UINT32)

        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());  // 代码指针(SPIR-V为32位字)

        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;                     // 返回成功
}

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

4

社区成员

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

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