Files
face_sdk/vulkan/Application.cpp
T

900 lines
33 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "Application.h"
#include <iostream>
#include <string>
using namespace std;
#ifdef _WIN32
#else
#include <game-activity/native_app_glue/android_native_app_glue.h>
#include <game-activity/GameActivity.h>
#include <vulkan/vulkan_android.h>
#include "../app/src/main/cpp/AndroidOut.h"
#endif
void Application::initWindow()
{
#ifdef _WIN32
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(480, 480, "Vulkan", nullptr, nullptr);
#else
#endif
}
void Application::run()
{
initVulkan();
cout << "initVulkan finished" << endl;
mainLoop();
cleanup();
}
#ifdef _WIN32
#else
extern android_app* g_android_app;
#endif
void Application::createSurface() {
#ifdef _WIN32
if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {
throw std::runtime_error("failed to create window surface!");
}
#else
//VkSurfaceKHR surface{};
VkAndroidSurfaceCreateInfoKHR info{VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR};
info.window = g_android_app->window;
VK_CHECK(vkCreateAndroidSurfaceKHR(instance, &info, nullptr, &surface));
#endif
}
void Application::initVulkan()
{
initWindow();
createInstance(); // 创建 Vulkan 实例
setupDebugMessenger(); // 在这里调用
createSurface(); // 创建窗口表面
pickPhysicalDevice(physicalDevice, surface); // 选择物理设备
createLogicalDevice(); // 创建逻辑设备
createSwapChain(); // 创建交换链
createImages();
createImageViews(); // 创建交换链图像视图
createColorResources();
createRenderPass(); // 创建渲染流程
createPipelineLayout(); // 在这里调用
createGraphicsPipeline(); // 创建图形管线
createFramebuffers(); // 创建帧缓冲区
createCommandPool(); // 创建命令池
createCommandBuffer(); // 创建命令缓冲区
createSyncObjects(); // 创建同步对象
inited = true;
}
void Application::createImages()
{
uint32_t imageCount = 0;
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
swapChainImages.resize(imageCount);
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());
}
void Application::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;
createInfo.format = swapChainImageFormat;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
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 Application::createFramebuffers()
{
swapChainFramebuffers.resize(swapChainImageViews.size());
for (size_t i = 0; i < swapChainImageViews.size(); i++)
{
std::vector<VkImageView> attachments =
{
colorImageView, // 0: MSAA color attachment
swapChainImageViews[i] // 1: resolve target (swapchain)
};
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 Application::mainLoop()
{
#ifdef _WIN32
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
drawFrame(); // 在这里调用
}
#else
#endif
vkDeviceWaitIdle(device); // 等待设备空闲
}
void Application::createLogicalDevice() {
QueueFamilyIndices indices = findQueueFamilies(physicalDevice, surface);
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
float queuePriority = 1.0f;
for (uint32_t queueFamily : uniqueQueueFamilies) {
VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
queueCreateInfos.push_back(queueCreateInfo);
}
VkPhysicalDeviceFeatures deviceFeatures{};
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;
// 启用交换链扩展
const std::vector<const char*> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
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 Application::createSwapChain() {
// 选择交换链格式、颜色空间和分辨率
VkSurfaceFormatKHR surfaceFormat = { VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
VkSurfaceCapabilitiesKHR surface_capabilities{};
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(this->physicalDevice, this->surface, &surface_capabilities);
VkExtent2D extent = surface_capabilities.currentExtent;
uint32_t imageCount = 2;
// 创建交换链
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, surface);
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.queueFamilyIndexCount = 0; // Optional
createInfo.pQueueFamilyIndices = nullptr; // Optional
}
createInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = presentMode;
createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) {
throw std::runtime_error("failed to create swap chain!");
}
swapChainImageFormat = surfaceFormat.format;
swapChainExtent = extent;
}
void Application::createPipelineLayout() {
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 0; // 可选:描述符集布局
pipelineLayoutInfo.pSetLayouts = nullptr; // 可选:描述符集布局
pipelineLayoutInfo.pushConstantRangeCount = 0; // 可选:推送常量范围
pipelineLayoutInfo.pPushConstantRanges = nullptr; // 可选:推送常量范围
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
throw std::runtime_error("failed to create pipeline layout!");
}
}
void Application::createGraphicsPipeline() {
// 顶点着色器和片段着色器
auto vertShaderCode = readFile("shaders/simple_shader.vert.spv");
auto fragShaderCode = readFile("shaders/simple_shader.frag.spv");
// 创建着色器模块
VkShaderModule vertShaderModule = createShaderModule(this->device, vertShaderCode);
VkShaderModule fragShaderModule = createShaderModule(this->device, 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;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.pVertexBindingDescriptions = nullptr;
vertexInputInfo.vertexAttributeDescriptionCount = 0;
vertexInputInfo.pVertexAttributeDescriptions = nullptr;
// 输入组装状态
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
// 视口状态
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)swapChainExtent.width;
viewport.height = (float)swapChainExtent.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VkRect2D scissor{};
scissor.offset = { 0, 0 };
scissor.extent = swapChainExtent;
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;
// 光栅化状态
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_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_8_BIT;
// 颜色混合状态
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
// 创建图形管线
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.layout = pipelineLayout;
pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0;
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 Application::createRenderPass() {
// 1. 多重采样颜色附件(8x
VkAttachmentDescription colorAttachment{};
colorAttachment.format = swapChainImageFormat;
colorAttachment.samples = VK_SAMPLE_COUNT_8_BIT; // ←←← 8x
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // 不需要存储,因为会 resolve
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_COLOR_ATTACHMENT_OPTIMAL;
// 2. Resolve 附件(普通 swapchain image
VkAttachmentDescription resolveAttachment{};
resolveAttachment.format = swapChainImageFormat;
resolveAttachment.samples = VK_SAMPLE_COUNT_1_BIT; // ←←← resolve 到单采样
resolveAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
resolveAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
resolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
resolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
resolveAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
resolveAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
// 引用
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference resolveAttachmentRef{};
resolveAttachmentRef.attachment = 1;
resolveAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
// Subpass:指定 color 和 resolve
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
subpass.pResolveAttachments = &resolveAttachmentRef; // ←←← 关键!
// Subpass 依赖(可选但推荐)
VkSubpassDependency dependency{};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 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;
std::vector<VkAttachmentDescription> attachments = { colorAttachment, resolveAttachment };
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 Application::createCommandPool() {
QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice, surface);
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // 添加标志
if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
throw std::runtime_error("failed to create command pool!");
}
}
void Application::createCommandBuffer()
{
//std::vector<VkCommandBuffer> commandBuffers = { commandBuffers_Left, commandBuffers_Right };
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = commandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;
if (vkAllocateCommandBuffers(device, &allocInfo, &commandBuffers_Left) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate command buffers!");
}
if (vkAllocateCommandBuffers(device, &allocInfo, &commandBuffers_Right) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate command buffers!");
}
}
void Application::createSyncObjects()
{
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;
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores_Left);
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores_Right);
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores_Left);
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores_Right);
vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences_Left);
vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences_Right);
}
void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex)
{
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0; // 可选标志
beginInfo.pInheritanceInfo = nullptr; // 仅用于次级命令缓冲区
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]; // 使用正确的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);
// 绘制三角形
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
// 结束渲染流程
vkCmdEndRenderPass(commandBuffer);
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to record command buffer!");
}
}
void Application::drawLeft()
{
if(showDrawDebug)
cout << "call drawLeft curFrame:" << to_string(currentFrame) << endl;
// 1. 等待前一帧完成
vkWaitForFences(device, 1, &inFlightFences_Left, VK_TRUE, UINT64_MAX);
if (showDrawDebug) cout << "vkWaitForFences inFlightFences_Left" << endl;
// 2. 获取交换链图像 - 使用当前帧的信号量
uint32_t imageIndex;
VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores_Left, VK_NULL_HANDLE, &imageIndex);
if (showDrawDebug) cout << "vkAcquireNextImageKHR set imageAvailableSemaphores_Left ImageIndex:" << to_string(imageIndex) << endl;
if (result != VK_SUCCESS) {
throw std::runtime_error("failed to acquire swap chain image!");
}
if (imageIndex == 0)
{
// 3. 检查该图像是否正在被之前的帧使用
if (imagesInFlight_Left != VK_NULL_HANDLE) {
if (showDrawDebug) cout << "vkWaitForFences imagesInFlight_Left ImageIndex:" << to_string(imageIndex) << endl;
vkWaitForFences(device, 1, &imagesInFlight_Left, VK_TRUE, UINT64_MAX);
}
else
{
if (showDrawDebug) cout << "imagesInFlight_Left is NULL" << endl;
}
if (showDrawDebug) cout << "imagesInFlight_Left = inFlightFences_Left ImageIndex:" << to_string(imageIndex) << endl;
// 标记该图像正在被当前帧使用
imagesInFlight_Left = inFlightFences_Left;
}
else
{
// 3. 检查该图像是否正在被之前的帧使用
if (imagesInFlight_Right != VK_NULL_HANDLE) {
if (showDrawDebug) cout << "vkWaitForFences imagesInFlight_Right ImageIndex:" << to_string(imageIndex) << endl;
vkWaitForFences(device, 1, &imagesInFlight_Right, VK_TRUE, UINT64_MAX);
}
if (showDrawDebug) cout << "imagesInFlight_Right = inFlightFences_Left ImageIndex:" << to_string(imageIndex) << endl;
imagesInFlight_Right = inFlightFences_Left;
}
if (showDrawDebug) cout << "vkResetFences inFlightFences_Left" << endl;
// 4. 重置栅栏
vkResetFences(device, 1, &inFlightFences_Left);
if (showDrawDebug) cout << "Process commandBuffers_Left" << endl;
// 5. 记录命令缓冲区
vkResetCommandBuffer(commandBuffers_Left, 0);
recordCommandBuffer(commandBuffers_Left, imageIndex);
// 6. 提交命令缓冲区
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
// 等待图像获取完成
VkSemaphore waitSemaphores[] = { imageAvailableSemaphores_Left };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffers_Left;
VkSemaphore signalSemaphores[1];
if (imageIndex == 0)
{
if (showDrawDebug) cout << "renderFinishedSemaphores_Left ImageIndex:" << to_string(imageIndex) << endl;
// 使用对应图像的渲染完成信号量
signalSemaphores[0] = { renderFinishedSemaphores_Left };
}
else
{
if (showDrawDebug) cout << "renderFinishedSemaphores_Right ImageIndex:" << to_string(imageIndex) << endl;
// 使用对应图像的渲染完成信号量
signalSemaphores[0] = { renderFinishedSemaphores_Right };
}
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
if (showDrawDebug) cout << "vkQueueSubmit inFlightFences_Left" << endl;
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences_Left) != VK_SUCCESS) {
throw std::runtime_error("failed to submit draw command buffer!");
}
// 7. 呈现图像
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;
if (showDrawDebug) cout << "Present Left \n" << endl;
result = vkQueuePresentKHR(presentQueue, &presentInfo);
if (result != VK_SUCCESS) {
throw std::runtime_error("failed to present swap chain image!");
}
}
void Application::drawRight()
{
if (showDrawDebug) cout << "call drawRight curFrame:" << to_string(currentFrame) << endl;
// 1. 等待前一帧完成
vkWaitForFences(device, 1, &inFlightFences_Right, VK_TRUE, UINT64_MAX);
if (showDrawDebug) cout << "vkWaitForFences inFlightFences_Right" << endl;
// 2. 获取交换链图像 - 使用当前帧的信号量
uint32_t imageIndex;
VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores_Right, VK_NULL_HANDLE, &imageIndex);
if (showDrawDebug) cout << "vkAcquireNextImageKHR set imageAvailableSemaphores_Right ImageIndex:" << to_string(imageIndex) << endl;
if (result != VK_SUCCESS) {
throw std::runtime_error("failed to acquire swap chain image!");
}
if (imageIndex == 0)
{
// 3. 检查该图像是否正在被之前的帧使用
if (imagesInFlight_Left != VK_NULL_HANDLE) {
if (showDrawDebug) cout << "vkWaitForFences imagesInFlight_Left ImageIndex:0" << endl;
vkWaitForFences(device, 1, &imagesInFlight_Left, VK_TRUE, UINT64_MAX);
}
if (showDrawDebug) cout << "imagesInFlight_Left = inFlightFences_Right ImageIndex:0" << endl;
// 标记该图像正在被当前帧使用
imagesInFlight_Left = inFlightFences_Right;
}
else
{
// 3. 检查该图像是否正在被之前的帧使用
if (imagesInFlight_Right != VK_NULL_HANDLE) {
if (showDrawDebug) cout << "vkWaitForFences imagesInFlight_Right ImageIndex:1" << endl;
vkWaitForFences(device, 1, &imagesInFlight_Right, VK_TRUE, UINT64_MAX);
}
else {
if (showDrawDebug) cout << "imagesInFlight_Right is NULL" << endl;
}
if (showDrawDebug) cout << "imagesInFlight_Right = inFlightFences_Right ImageIndex:1" << endl;
imagesInFlight_Right = inFlightFences_Right;
}
if (showDrawDebug) cout << "vkResetFences inFlightFences_Right" << endl;
// 4. 重置栅栏
vkResetFences(device, 1, &inFlightFences_Right);
if (showDrawDebug) cout << "Process commandBuffers_Right" << endl;
// 5. 记录命令缓冲区
vkResetCommandBuffer(commandBuffers_Right, 0);
recordCommandBuffer(commandBuffers_Right, imageIndex);
// 6. 提交命令缓冲区
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
// 等待图像获取完成
VkSemaphore waitSemaphores[] = { imageAvailableSemaphores_Right };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffers_Right;
VkSemaphore signalSemaphores[1];
if (imageIndex == 0)
{
if (showDrawDebug) cout << "renderFinishedSemaphores_Left ImageIndex:0" << endl;
// 使用对应图像的渲染完成信号量
signalSemaphores[0] = { renderFinishedSemaphores_Left };
}
else
{
if (showDrawDebug) cout << "renderFinishedSemaphores_Right ImageIndex:1" << endl;
// 使用对应图像的渲染完成信号量
signalSemaphores[0] = { renderFinishedSemaphores_Right };
}
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
if (showDrawDebug) cout << "vkQueueSubmit inFlightFences_Right" << endl;
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences_Right) != VK_SUCCESS) {
throw std::runtime_error("failed to submit draw command buffer!");
}
// 7. 呈现图像
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;
if (showDrawDebug) cout << "Present Right \n" << endl;
result = vkQueuePresentKHR(presentQueue, &presentInfo);
if (result != VK_SUCCESS) {
throw std::runtime_error("failed to present swap chain image!");
}
}
void Application::drawFrame()
{
if (currentFrame % 2 == 0)
{
drawLeft();
}
else
{
drawRight();
}
currentFrame++;
}
void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) {
auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
if (func != nullptr) {
func(instance, debugMessenger, pAllocator);
}
}
void Application::createColorResources() {
VkFormat colorFormat = swapChainImageFormat;
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = colorFormat;
imageInfo.extent.width = swapChainExtent.width;
imageInfo.extent.height = swapChainExtent.height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = VK_SAMPLE_COUNT_8_BIT; // ←←← 8x MSAA
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateImage(device, &imageInfo, nullptr, &colorImage) != VK_SUCCESS) {
throw std::runtime_error("failed to create MSAA color image!");
}
VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(device, colorImage, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(physicalDevice, memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (vkAllocateMemory(device, &allocInfo, nullptr, &colorImageMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate MSAA color image memory!");
}
vkBindImageMemory(device, colorImage, colorImageMemory, 0);
// 创建 ImageView
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = colorImage;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = colorFormat;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(device, &viewInfo, nullptr, &colorImageView) != VK_SUCCESS) {
throw std::runtime_error("failed to create MSAA color image view!");
}
}
uint32_t Application::findMemoryType(VkPhysicalDevice physicalDevice, 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 Application::cleanup() {
if (enableValidationLayers) {
DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
}
// 等待设备空闲,确保所有命令都完成
vkDeviceWaitIdle(device);
// 正确销毁所有同步对象
vkDestroySemaphore(device, imageAvailableSemaphores_Left, nullptr);
vkDestroySemaphore(device, renderFinishedSemaphores_Left, nullptr);
vkDestroyFence(device, inFlightFences_Left, nullptr);
// 正确销毁所有同步对象
vkDestroySemaphore(device, imageAvailableSemaphores_Right, nullptr);
vkDestroySemaphore(device, renderFinishedSemaphores_Right, nullptr);
vkDestroyFence(device, inFlightFences_Right, nullptr);
// 不需要手动释放commandBuffers,销毁命令池时会自动释放
// 销毁命令池
vkDestroyCommandPool(device, commandPool, nullptr);
// 销毁图形管线
vkDestroyPipeline(device, graphicsPipeline, nullptr);
// 销毁管线布局
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
// 销毁渲染流程
vkDestroyRenderPass(device, renderPass, nullptr);
// 销毁图像视图
for (auto imageView : swapChainImageViews) {
vkDestroyImageView(device, imageView, nullptr);
}
vkDestroyImageView(device, colorImageView, nullptr);
vkDestroyImage(device, colorImage, nullptr);
vkFreeMemory(device, colorImageMemory, nullptr);
// 销毁交换链
vkDestroySwapchainKHR(device, swapChain, nullptr);
// 销毁命令池
vkDestroyCommandPool(device, commandPool, nullptr);
// 销毁逻辑设备
vkDestroyDevice(device, nullptr);
// 销毁窗口表面
vkDestroySurfaceKHR(instance, surface, nullptr);
// 销毁 Vulkan 实例
vkDestroyInstance(instance, nullptr);
#ifdef _WIN32
// 销毁 GLFW 窗口
glfwDestroyWindow(window);
// 终止 GLFW
glfwTerminate();
#endif
}