vulkan计算着色器

OpenTK 2026-09-11 10:27:59

#version 450

layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec4 inColor;

layout(location = 0) out vec3 fragColor;

void main() {

    gl_PointSize = 14.0;
    gl_Position = vec4(inPosition.xy, 1.0, 1.0);
    fragColor = inColor.rgb;
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#version 450

layout(location = 0) in vec3 fragColor;

layout(location = 0) out vec4 outColor;

void main() {

    vec2 coord = gl_PointCoord - vec2(0.5);
    outColor = vec4(fragColor, 0.5 - length(coord));
}
 

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

#version 450

struct Particle {
    vec2 position;
    vec2 velocity;
    vec4 color;
};

layout (binding = 0) uniform ParameterUBO {
    float deltaTime;
} ubo;

layout(std140, binding = 1) readonly buffer ParticleSSBOIn {
   Particle particlesIn[ ];
};

layout(std140, binding = 2) buffer ParticleSSBOOut {
   Particle particlesOut[ ];
};

layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;

void main() 
{
    uint index = gl_GlobalInvocationID.x;  

    Particle particleIn = particlesIn[index];

    particlesOut[index].position = particleIn.position + particleIn.velocity.xy * ubo.deltaTime;
    particlesOut[index].velocity = particleIn.velocity;

    // Flip movement at window border
    if ((particlesOut[index].position.x <= -1.0) || (particlesOut[index].position.x >= 1.0)) {
        particlesOut[index].velocity.x = -particlesOut[index].velocity.x;
    }
    if ((particlesOut[index].position.y <= -1.0) || (particlesOut[index].position.y >= 1.0)) {
        particlesOut[index].velocity.y = -particlesOut[index].velocity.y;
    }

}

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

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

#include <glm/glm.hpp>                       // GLM数学库核心
#include <glm/gtc/matrix_transform.hpp>      // GLM矩阵变换函数

#include <iostream>                          // 标准输入输出流
#include <fstream>                           // 文件读写
#include <stdexcept>                         // 标准异常类
#include <algorithm>                         // std::clamp等算法
#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 <random>                            // 随机数生成(粒子初始化)

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

const uint32_t PARTICLE_COUNT = 8192;        // 粒子数量(必须是256的整数倍,计算着色器本地工作组大小)

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> graphicsAndComputeFamily;  // 图形+计算队列族(同一族)
    std::optional<uint32_t> presentFamily;   // 呈现队列族

    bool isComplete() {                      // 是否都已找到
        return graphicsAndComputeFamily.has_value() && presentFamily.has_value();
    }
};

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

struct UniformBufferObject {                 // Uniform缓冲对象(传给计算着色器)
    float deltaTime = 1.0f;                  // 帧间隔时间(毫秒),用于帧率无关的动画
};

struct Particle {                            // 粒子结构体
    glm::vec2 position;                      // 位置
    glm::vec2 velocity;                      // 速度
    glm::vec4 color;                         // 颜色

    static VkVertexInputBindingDescription getBindingDescription() {  // 顶点绑定描述
        VkVertexInputBindingDescription bindingDescription{};         // 值初始化
        bindingDescription.binding = 0;                               // 绑定索引0
        bindingDescription.stride = sizeof(Particle);                 // 跨距(每个粒子字节数)
        bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;   // 逐顶点

        return bindingDescription;
    }

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

        attributeDescriptions[0].binding = 0;                         // 绑定0
        attributeDescriptions[0].location = 0;                        // location 0
        attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;    // vec2
        attributeDescriptions[0].offset = offsetof(Particle, position);  // position偏移

        attributeDescriptions[1].binding = 0;                         // 绑定0
        attributeDescriptions[1].location = 1;                        // location 1
        attributeDescriptions[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;  // vec4
        attributeDescriptions[1].offset = offsetof(Particle, color);  // color偏移

        return attributeDescriptions;
    }
};

class ComputeShaderApplication {             // 应用主类(计算着色器粒子系统)
public:
    void run() {                             // 入口
        initWindow();                        // 创建窗口
        initVulkan();                        // 初始化Vulkan
        mainLoop();                          // 主循环
        cleanup();                           // 清理
    }

private:
    GLFWwindow* window;                      // GLFW窗口

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

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

    VkQueue graphicsQueue;                   // 图形队列
    VkQueue computeQueue;                    // 计算队列(与图形同族)
    VkQueue presentQueue;                    // 呈现队列

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

    VkRenderPass renderPass;                 // 渲染通道
    VkPipelineLayout pipelineLayout;         // 图形管线布局
    VkPipeline graphicsPipeline;             // 图形管线

    VkDescriptorSetLayout computeDescriptorSetLayout;  // 计算描述符集布局
    VkPipelineLayout computePipelineLayout;  // 计算管线布局
    VkPipeline computePipeline;              // 计算管线

    VkCommandPool commandPool;               // 命令池(图形+计算共用)

    std::vector<VkBuffer> shaderStorageBuffers;        // 计算着色器存储缓冲(粒子数据)
    std::vector<VkDeviceMemory> shaderStorageBuffersMemory;  // 存储缓冲内存

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

    VkDescriptorPool descriptorPool;         // 描述符池
    std::vector<VkDescriptorSet> computeDescriptorSets;  // 计算描述符集

    std::vector<VkCommandBuffer> commandBuffers;         // 图形命令缓冲
    std::vector<VkCommandBuffer> computeCommandBuffers;  // 计算命令缓冲

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

    float lastFrameTime = 0.0f;              // 上一帧耗时(毫秒)

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

    double lastTime = 0.0f;                  // 上一帧的时间戳(秒)

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

        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);  // 不创建OpenGL上下文

        window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);  // 创建窗口
        glfwSetWindowUserPointer(window, this);  // 保存this
        glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);  // 注册回调

        lastTime = glfwGetTime();            // 记录初始时间
    }

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

    void initVulkan() {                      // 初始化Vulkan
        createInstance();                    // 创建实例
        setupDebugMessenger();               // 设置调试信使
        createSurface();                     // 创建表面
        pickPhysicalDevice();                // 选择物理设备
        createLogicalDevice();               // 创建逻辑设备
        createSwapChain();                   // 创建交换链
        createImageViews();                  // 创建图像视图
        createRenderPass();                  // 创建渲染通道
        createComputeDescriptorSetLayout();  // 创建计算描述符集布局
        createGraphicsPipeline();            // 创建图形管线
        createComputePipeline();             // 创建计算管线(新增)
        createFramebuffers();                // 创建帧缓冲
        createCommandPool();                 // 创建命令池
        createShaderStorageBuffers();        // 创建存储缓冲(粒子数据,新增)
        createUniformBuffers();              // 创建Uniform缓冲
        createDescriptorPool();              // 创建描述符池
        createComputeDescriptorSets();       // 分配计算描述符集
        createCommandBuffers();              // 创建图形命令缓冲
        createComputeCommandBuffers();       // 创建计算命令缓冲(新增)
        createSyncObjects();                 // 创建同步对象
    }

    void mainLoop() {                        // 主循环
        while (!glfwWindowShouldClose(window)) {  // 窗口未关闭
            glfwPollEvents();                // 处理事件
            drawFrame();                     // 绘制一帧
            // 使用上一帧的时间来计算 deltaTime,实现帧率无关的平滑动画
            double currentTime = glfwGetTime();  // 当前时间
            lastFrameTime = (currentTime - lastTime) * 1000.0;  // 毫秒
            lastTime = currentTime;          // 更新上次时间
        }

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

    void cleanupSwapChain() {                // 清理交换链资源
        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); // 销毁图形管线布局

        vkDestroyPipeline(device, computePipeline, nullptr);      // 销毁计算管线
        vkDestroyPipelineLayout(device, computePipelineLayout, 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);  // 释放内存
        }

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

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

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

        for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {       // 遍历每帧
            vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);   // 销毁渲染完成信号量
            vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);   // 销毁图像可用信号量
            vkDestroySemaphore(device, computeFinishedSemaphores[i], nullptr);  // 销毁计算完成信号量
            vkDestroyFence(device, inFlightFences[i], nullptr);                 // 销毁图形围栏
            vkDestroyFence(device, computeInFlightFences[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();                  // 重建图像视图
        createFramebuffers();                // 重建帧缓冲
    }

    void createInstance() {                  // 创建实例
        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;  // 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;  // 严重性
        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) {              // 无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) {  // 未找到
            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.graphicsAndComputeFamily.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{};  // 设备特性(本示例无需特殊特性)

        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.graphicsAndComputeFamily.value(), 0, &graphicsQueue);  // 获取图形队列
        vkGetDeviceQueue(device, indices.graphicsAndComputeFamily.value(), 0, &computeQueue);   // 获取计算队列(同族)
        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.graphicsAndComputeFamily.value(), indices.presentFamily.value() };  // 两族

        if (indices.graphicsAndComputeFamily != 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 (size_t i = 0; i < swapChainImages.size(); i++) {  // 遍历
            VkImageViewCreateInfo createInfo{};  // 视图创建信息
            createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
            createInfo.image = swapChainImages[i];  // 图像
            createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;  // 2D
            createInfo.format = swapChainImageFormat;  // 格式
            createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;  // R通道
            createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;  // G通道
            createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;  // B通道
            createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;  // A通道
            createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;  // 颜色
            createInfo.subresourceRange.baseMipLevel = 0;  // 基础mip
            createInfo.subresourceRange.levelCount = 1;    // mip数
            createInfo.subresourceRange.baseArrayLayer = 0;  // 基础层
            createInfo.subresourceRange.layerCount = 1;      // 层数

            if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {  // 创建
                throw std::runtime_error("failed to create image views!");
            }
        }
    }

    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;  // 最终布局

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

        VkSubpassDescription subpass{};              // 子通道
        subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;  // 图形
        subpass.colorAttachmentCount = 1;            // 颜色附件数
        subpass.pColorAttachments = &colorAttachmentRef;  // 颜色附件

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

        VkRenderPassCreateInfo renderPassInfo{};     // 创建信息
        renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
        renderPassInfo.attachmentCount = 1;          // 附件数
        renderPassInfo.pAttachments = &colorAttachment;  // 附件
        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 createComputeDescriptorSetLayout() {  // 创建计算描述符集布局
        std::array<VkDescriptorSetLayoutBinding, 3> layoutBindings{};  // 3个绑定
        layoutBindings[0].binding = 0;           // 绑定0
        layoutBindings[0].descriptorCount = 1;   // 数量
        layoutBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;  // Uniform缓冲(deltaTime)
        layoutBindings[0].pImmutableSamplers = nullptr;  // 无
        layoutBindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;  // 计算阶段

        layoutBindings[1].binding = 1;           // 绑定1
        layoutBindings[1].descriptorCount = 1;
        layoutBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;  // 存储缓冲(上一帧粒子)
        layoutBindings[1].pImmutableSamplers = nullptr;
        layoutBindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;

        layoutBindings[2].binding = 2;           // 绑定2
        layoutBindings[2].descriptorCount = 1;
        layoutBindings[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;  // 存储缓冲(当前帧粒子)
        layoutBindings[2].pImmutableSamplers = nullptr;
        layoutBindings[2].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;

        VkDescriptorSetLayoutCreateInfo layoutInfo{};  // 布局创建信息
        layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
        layoutInfo.bindingCount = 3;             // 数量
        layoutInfo.pBindings = layoutBindings.data();  // 绑定

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

    void createGraphicsPipeline() {           // 创建图形管线
        auto vertShaderCode = readFile("shaders/31_shader_compute.vert.spv");  // 读顶点SPIR-V
        auto fragShaderCode = readFile("shaders/31_shader_compute.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 = Particle::getBindingDescription();       // 绑定描述
        auto attributeDescriptions = Particle::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_POINT_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采样

        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_TRUE;  // 启用混合(粒子需要alpha混合)
        colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;  // 颜色混合操作:相加
        colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;  // 源因子:源alpha
        colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;  // 目标因子:1-源alpha
        colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;  // alpha混合操作:相加
        colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;  // 源alpha因子
        colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;  // 目标alpha因子

        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 = 0;   // 无描述符集
        pipelineLayoutInfo.pSetLayouts = nullptr;  // 无

        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.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 createComputePipeline() {           // 创建计算管线(新增)
        auto computeShaderCode = readFile("shaders/31_shader_compute.comp.spv");  // 读计算SPIR-V

        VkShaderModule computeShaderModule = createShaderModule(computeShaderCode);  // 计算模块

        VkPipelineShaderStageCreateInfo computeShaderStageInfo{};  // 计算阶段
        computeShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
        computeShaderStageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;  // 计算阶段
        computeShaderStageInfo.module = computeShaderModule;         // 模块
        computeShaderStageInfo.pName = "main";                       // 入口

        VkPipelineLayoutCreateInfo pipelineLayoutInfo{};  // 计算管线布局
        pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
        pipelineLayoutInfo.setLayoutCount = 1;   // 1个描述符集布局
        pipelineLayoutInfo.pSetLayouts = &computeDescriptorSetLayout;  // 计算描述符集布局

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

        VkComputePipelineCreateInfo pipelineInfo{};  // 计算管线创建信息
        pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
        pipelineInfo.layout = computePipelineLayout;  // 布局
        pipelineInfo.stage = computeShaderStageInfo;  // 计算阶段

        if (vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &computePipeline) != VK_SUCCESS) {  // 创建
            throw std::runtime_error("failed to create compute pipeline!");
        }

        vkDestroyShaderModule(device, computeShaderModule, nullptr);  // 销毁计算模块
    }

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

        for (size_t i = 0; i < swapChainImageViews.size(); i++) {  // 遍历
            VkImageView attachments[] = {
                swapChainImageViews[i]          // 颜色附件
            };

            VkFramebufferCreateInfo framebufferInfo{};  // 创建信息
            framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
            framebufferInfo.renderPass = renderPass;    // 渲染通道
            framebufferInfo.attachmentCount = 1;        // 附件数
            framebufferInfo.pAttachments = attachments; // 附件
            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.graphicsAndComputeFamily.value();  // 图形+计算队列族

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

    void createShaderStorageBuffers() {      // 创建存储缓冲(粒子数据,新增)

        // 初始化粒子
        std::default_random_engine rndEngine((unsigned)time(nullptr));  // 随机数引擎(以时间为种子)
        std::uniform_real_distribution<float> rndDist(0.0f, 1.0f);      // 均匀分布[0,1]

        // 粒子初始位置分布在一个圆内
        std::vector<Particle> particles(PARTICLE_COUNT);  // 粒子数组
        for (auto& particle : particles) {   // 遍历粒子
            float r = 0.25f * sqrt(rndDist(rndEngine));  // 半径(sqrt使其面积均匀)
            float theta = rndDist(rndEngine) * 2.0f * 3.14159265358979323846f;  // 角度
            float x = r * cos(theta) * HEIGHT / WIDTH;  // x(按宽高比缩放)
            float y = r * sin(theta);            // y
            particle.position = glm::vec2(x, y); // 位置
            particle.velocity = glm::normalize(glm::vec2(x, y)) * 0.00025f;  // 速度(沿径向)
            particle.color = glm::vec4(rndDist(rndEngine), rndDist(rndEngine), rndDist(rndEngine), 1.0f);  // 随机颜色
        }

        VkDeviceSize bufferSize = sizeof(Particle) * PARTICLE_COUNT;  // 缓冲大小

        // 创建暂存缓冲用于上传数据到GPU
        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, particles.data(), (size_t)bufferSize);  // 拷贝粒子数据
        vkUnmapMemory(device, stagingBufferMemory);  // 取消映射

        shaderStorageBuffers.resize(MAX_FRAMES_IN_FLIGHT);        // 每帧一个
        shaderStorageBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);  // 每帧一个

        // 把初始粒子数据拷贝到所有存储缓冲
        for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {  // 遍历每帧
            createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, shaderStorageBuffers[i], shaderStorageBuffersMemory[i]);  // 创建(存储+顶点+传输目标)
            copyBuffer(stagingBuffer, shaderStorageBuffers[i], 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]);  // 创建

            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_STORAGE_BUFFER;  // 存储缓冲
        poolSizes[1].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT) * 2;  // 每帧两个(上一帧+当前帧)

        VkDescriptorPoolCreateInfo poolInfo{};  // 创建信息
        poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
        poolInfo.poolSizeCount = 2;              // 数量
        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 createComputeDescriptorSets() {     // 创建计算描述符集
        std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, computeDescriptorSetLayout);  // 布局
        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();  // 布局

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

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

            std::array<VkWriteDescriptorSet, 3> descriptorWrites{};  // 3个写入
            descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
            descriptorWrites[0].dstSet = computeDescriptorSets[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 = &uniformBufferInfo;  // 缓冲

            VkDescriptorBufferInfo storageBufferInfoLastFrame{};  // 上一帧存储缓冲信息
            storageBufferInfoLastFrame.buffer = shaderStorageBuffers[(i - 1) % MAX_FRAMES_IN_FLIGHT];  // 上一帧缓冲
            storageBufferInfoLastFrame.offset = 0;  // 偏移
            storageBufferInfoLastFrame.range = sizeof(Particle) * PARTICLE_COUNT;  // 范围

            descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
            descriptorWrites[1].dstSet = computeDescriptorSets[i];  // 目标集合
            descriptorWrites[1].dstBinding = 1;  // 绑定1(上一帧)
            descriptorWrites[1].dstArrayElement = 0;
            descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
            descriptorWrites[1].descriptorCount = 1;
            descriptorWrites[1].pBufferInfo = &storageBufferInfoLastFrame;  // 缓冲

            VkDescriptorBufferInfo storageBufferInfoCurrentFrame{};  // 当前帧存储缓冲信息
            storageBufferInfoCurrentFrame.buffer = shaderStorageBuffers[i];  // 当前帧缓冲
            storageBufferInfoCurrentFrame.offset = 0;  // 偏移
            storageBufferInfoCurrentFrame.range = sizeof(Particle) * PARTICLE_COUNT;  // 范围

            descriptorWrites[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
            descriptorWrites[2].dstSet = computeDescriptorSets[i];  // 目标集合
            descriptorWrites[2].dstBinding = 2;  // 绑定2(当前帧)
            descriptorWrites[2].dstArrayElement = 0;
            descriptorWrites[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
            descriptorWrites[2].descriptorCount = 1;
            descriptorWrites[2].pBufferInfo = &storageBufferInfoCurrentFrame;  // 缓冲

            vkUpdateDescriptorSets(device, 3, 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);  // 绑定
    }

    void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {  // 拷贝缓冲(一次性命令)
        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);  // 开始

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

        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);  // 释放
    }

    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 createComputeCommandBuffers() {     // 创建计算命令缓冲(新增)
        computeCommandBuffers.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)computeCommandBuffers.size();  // 数量

        if (vkAllocateCommandBuffers(device, &allocInfo, computeCommandBuffers.data()) != VK_SUCCESS) {  // 分配
            throw std::runtime_error("failed to allocate compute 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;  // 尺寸

        VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} };  // 清空颜色:黑色
        renderPassInfo.clearValueCount = 1;  // 数量
        renderPassInfo.pClearValues = &clearColor;  // 值

        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);  // 设置

        VkDeviceSize offsets[] = { 0 };      // 偏移
        vkCmdBindVertexBuffers(commandBuffer, 0, 1, &shaderStorageBuffers[currentFrame], offsets);  // 绑定存储缓冲作为顶点缓冲

        vkCmdDraw(commandBuffer, PARTICLE_COUNT, 1, 0, 0);  // 绘制所有粒子(点)

        vkCmdEndRenderPass(commandBuffer);   // 结束

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

    void recordComputeCommandBuffer(VkCommandBuffer commandBuffer) {  // 记录计算命令(新增)
        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 compute command buffer!");
        }

        vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);  // 绑定计算管线

        vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout, 0, 1, &computeDescriptorSets[currentFrame], 0, nullptr);  // 绑定计算描述符集

        vkCmdDispatch(commandBuffer, PARTICLE_COUNT / 256, 1, 1);  // 分派计算:每256个一组

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

    void createSyncObjects() {               // 创建同步对象
        imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);   // 图像可用信号量
        renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);   // 渲染完成信号量
        computeFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);  // 计算完成信号量
        inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);             // 图形在途围栏
        computeInFlightFences.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 graphics synchronization objects for a frame!");
            }
            if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &computeFinishedSemaphores[i]) != VK_SUCCESS ||  // 计算完成信号量
                vkCreateFence(device, &fenceInfo, nullptr, &computeInFlightFences[i]) != VK_SUCCESS) {  // 计算围栏
                throw std::runtime_error("failed to create compute synchronization objects for a frame!");
            }
        }
    }

    void updateUniformBuffer(uint32_t currentImage) {  // 更新Uniform(deltaTime)
        UniformBufferObject ubo{};           // UBO
        ubo.deltaTime = lastFrameTime * 2.0f;  // 帧间隔时间(乘2放大运动幅度)

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

    void drawFrame() {                       // 绘制一帧
        VkSubmitInfo submitInfo{};           // 提交信息
        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

        // ===== 计算提交 =====
        vkWaitForFences(device, 1, &computeInFlightFences[currentFrame], VK_TRUE, UINT64_MAX);  // 等待计算围栏

        updateUniformBuffer(currentFrame);   // 更新UBO(deltaTime)

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

        vkResetCommandBuffer(computeCommandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);  // 重置计算命令
        recordComputeCommandBuffer(computeCommandBuffers[currentFrame]);  // 记录计算命令

        submitInfo.commandBufferCount = 1;   // 命令数量
        submitInfo.pCommandBuffers = &computeCommandBuffers[currentFrame];  // 计算命令
        submitInfo.signalSemaphoreCount = 1;  // 信号数量
        submitInfo.pSignalSemaphores = &computeFinishedSemaphores[currentFrame];  // 计算完成信号量

        if (vkQueueSubmit(computeQueue, 1, &submitInfo, computeInFlightFences[currentFrame]) != VK_SUCCESS) {  // 提交到计算队列
            throw std::runtime_error("failed to submit compute command buffer!");
        };

        // ===== 图形提交 =====
        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!");
        }

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

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

        VkSemaphore waitSemaphores[] = { computeFinishedSemaphores[currentFrame], imageAvailableSemaphores[currentFrame] };  // 等待两个信号量:计算完成+图像可用
        VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };  // 等待阶段:顶点输入+颜色输出
        submitInfo = {};                     // 清空提交信息
        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

        submitInfo.waitSemaphoreCount = 2;   // 等待数量
        submitInfo.pWaitSemaphores = waitSemaphores;  // 等待
        submitInfo.pWaitDstStageMask = waitStages;    // 阶段
        submitInfo.commandBufferCount = 1;   // 命令数量
        submitInfo.pCommandBuffers = &commandBuffers[currentFrame];  // 图形命令
        submitInfo.signalSemaphoreCount = 1;  // 信号数量
        submitInfo.pSignalSemaphores = &renderFinishedSemaphores[currentFrame];  // 渲染完成信号量

        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 = &renderFinishedSemaphores[currentFrame];  // 等待

        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) {  // 优选
                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();  // 非空
        }

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

    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();   // 全部满足
    }

    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) && (queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT)) {  // 同时支持图形+计算
                indices.graphicsAndComputeFamily = 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() {                                 // 入口
    ComputeShaderApplication 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创作助手写篇文章吧