完成swapchain随窗口大小改变重建

master
InkSoul 2024-03-10 22:13:49 +08:00
parent dae58772e2
commit c6d688a055
2 changed files with 131 additions and 46 deletions

View File

@ -22,12 +22,14 @@ const bool enableValidationLayers = true;
#endif // NDEBUG
//window init
GLFWwindow* HelloTriangleApplication::initWindow(int Width, int Height) {
void HelloTriangleApplication::initWindow(int Width, int Height) {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(Width, Height, "vulkan", nullptr, nullptr);
return window;
glfwSetWindowUserPointer(window, this);
glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
}
// vulkan instace create
void HelloTriangleApplication::createInstance() {
@ -110,7 +112,7 @@ void HelloTriangleApplication::initVulkan() {
createSwapChain();
creatImageView();
createImageView();
createRenderPass();
createGraphicPipeline();
@ -143,38 +145,32 @@ void HelloTriangleApplication::mainLoop(GLFWwindow* window){
void HelloTriangleApplication::cleanup(GLFWwindow* window) {
std::cout << "\nstart to destroy resource\n" << std::endl;
std::cout << "\n======== start to destroy resource ========\n" << std::endl;
vkDestroySemaphore(device, imageAvailableSemaphore, nullptr);
vkDestroySemaphore(device, renderFinishedSemaphore, nullptr);
vkDestroyFence(device, inFlightFence, nullptr);
vkDestroyCommandPool(device, commandPool, nullptr);
for (auto framebuffer : swapChainFramebuffers)
{
vkDestroyFramebuffer(device, framebuffer, nullptr);
}
cleanupSwapChain();
vkDestroyPipeline(device, graphicsPipeline, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyRenderPass(device, renderPass, nullptr);
for (auto imageView : swapChainImageViews)
for (size_t i = 0; i < MAX_FRAME_IN_FLIGHT; i++)
{
vkDestroyImageView(device, imageView, nullptr);
vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
vkDestroyFence(device, inFlightFences[i], nullptr);
}
vkDestroySwapchainKHR(device, swapChain, nullptr);
vkDestroySurfaceKHR(instance, surface, nullptr);
vkDestroyCommandPool(device, commandPool, nullptr);
vkDestroyDevice(device, nullptr);
if (enableValidationLayers)
{
DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
}
vkDestroyDevice(device, nullptr);
vkDestroySurfaceKHR(instance, surface, nullptr);
vkDestroyInstance(instance, nullptr);
@ -561,7 +557,47 @@ void HelloTriangleApplication::createSwapChain()
}
void HelloTriangleApplication::creatImageView()
void HelloTriangleApplication::cleanupSwapChain()
{
for (auto framebuffer : swapChainFramebuffers)
{
vkDestroyFramebuffer(device, framebuffer, nullptr);
}
for (auto imageView : swapChainImageViews)
{
vkDestroyImageView(device, imageView, nullptr);
}
vkDestroySwapchainKHR(device, swapChain, nullptr);
}
void HelloTriangleApplication::recreateSwapChain()
{
int width = 0, height = 0;
glfwGetFramebufferSize(window, &width, &height);
while (width == 0 || height == 0)
{
if (glfwWindowShouldClose(window))
{
return;
}
glfwGetFramebufferSize(window, &width, &height);
glfwWaitEvents();
}
vkDeviceWaitIdle(device);
cleanupSwapChain();
createSwapChain();
createImageView();
creatFramebuffers();
}
void HelloTriangleApplication::createImageView()
{
swapChainImageViews.resize(swapChainImages.size());
@ -673,13 +709,15 @@ void HelloTriangleApplication::createCommandPool()
void HelloTriangleApplication::createCommandBuffer()
{
commandBuffers.resize(MAX_FRAME_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 = 1;
allocInfo.commandBufferCount = (uint32_t) commandBuffers.size();
if (vkAllocateCommandBuffers(device,&allocInfo,&commandBuffer) != VK_SUCCESS)
if (vkAllocateCommandBuffers(device,&allocInfo,commandBuffers.data()) != VK_SUCCESS)
{
throw std::runtime_error("failed to allocate command buffers in createCommandBuffer");
}
@ -737,33 +775,46 @@ void HelloTriangleApplication::recordCommandBuffer(VkCommandBuffer commandBuffer
void HelloTriangleApplication::drawFrame()
{
//等待所有fence收到信号后返回uint64_max禁用超时
vkWaitForFences(device, 1, &inFlightFence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &inFlightFence);
uint32_t currentFrame = 0;
uint32_t imageIndex;
vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
//等待所有fence收到信号后返回uint64_max禁用超时
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
vkResetCommandBuffer(commandBuffer, 0);
recordCommandBuffer(commandBuffer, 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 in drawFrame");
}
vkResetFences(device, 1, &inFlightFences[currentFrame]);
//vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
vkResetCommandBuffer(commandBuffers[currentFrame], 0);
recordCommandBuffer(commandBuffers[currentFrame], imageIndex);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = { imageAvailableSemaphore };
VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame]};
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
submitInfo.pCommandBuffers = &commandBuffers[currentFrame];
VkSemaphore signalSemaphores[] = { renderFinishedSemaphore };
VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame]};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
if (vkQueueSubmit(graphicQueue,1,&submitInfo,inFlightFence) != VK_SUCCESS)
if (vkQueueSubmit(graphicQueue,1,&submitInfo,inFlightFences[currentFrame]) != VK_SUCCESS)
{
throw std::runtime_error("failed to submit draw command buffer in drawFrame");
}
@ -779,12 +830,29 @@ void HelloTriangleApplication::drawFrame()
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
presentInfo.pResults = nullptr;
vkQueuePresentKHR(presentQueue, &presentInfo);
//vkQueuePresentKHR(presentQueue, &presentInfo);
result = vkQueuePresentKHR(presentQueue, &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
{
framebufferResized = false;
recreateSwapChain();
}
else if (result != VK_SUCCESS)
{
throw std::runtime_error("failed to present swap chain image in drawFrame");
}
currentFrame = (currentFrame + 1) % MAX_FRAME_IN_FLIGHT;//前进下一帧
}
void HelloTriangleApplication::createSyncObjects()
{
imageAvailableSemaphores.resize(MAX_FRAME_IN_FLIGHT);
renderFinishedSemaphores.resize(MAX_FRAME_IN_FLIGHT);
inFlightFences.resize(MAX_FRAME_IN_FLIGHT);
VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
@ -792,15 +860,22 @@ void HelloTriangleApplication::createSyncObjects()
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;//防止vkWaitForFences在第一帧无限期阻塞
if (vkCreateSemaphore(device,&semaphoreInfo,nullptr,&imageAvailableSemaphore) != VK_SUCCESS ||
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore) != VK_SUCCESS ||
vkCreateFence(device,&fenceInfo,nullptr,&inFlightFence) != VK_SUCCESS)
if (vkCreateSemaphore(device,&semaphoreInfo,nullptr,imageAvailableSemaphores.data()) != VK_SUCCESS ||
vkCreateSemaphore(device, &semaphoreInfo, nullptr, renderFinishedSemaphores.data()) != VK_SUCCESS ||
vkCreateFence(device,&fenceInfo,nullptr,inFlightFences.data()) != VK_SUCCESS)
{
throw std::runtime_error("failed to create semaphores in creatSyncObjects");
}
}
void HelloTriangleApplication::framebufferResizeCallback(GLFWwindow* window, int width, int height)
{
auto app = reinterpret_cast<HelloTriangleApplication*>(glfwGetWindowUserPointer(window));
app->framebufferResized = true;
}
void HelloTriangleApplication::createRenderPass()
{

View File

@ -30,10 +30,12 @@ class HelloTriangleApplication
{
public:
const int MAX_FRAME_IN_FLIGHT = 2;
HelloTriangleApplication();
~HelloTriangleApplication();
void run(int Width, int Height) {
GLFWwindow* window = initWindow(Width,Height);
initWindow(Width,Height);
initVulkan();
mainLoop(window);
cleanup(window);
@ -68,9 +70,7 @@ private:
VkPipeline graphicsPipeline;
VkSemaphore imageAvailableSemaphore;
VkSemaphore renderFinishedSemaphore;
VkFence inFlightFence;
struct QueueFamilyIndices
{
@ -93,9 +93,15 @@ private:
VkCommandPool commandPool;
VkCommandBuffer commandBuffer;
std::vector<VkCommandBuffer> commandBuffers;
GLFWwindow* initWindow(int Width, int Height);
std::vector<VkSemaphore> imageAvailableSemaphores;
std::vector<VkSemaphore> renderFinishedSemaphores;
std::vector<VkFence> inFlightFences;
bool framebufferResized = false;
void initWindow(int Width, int Height);
void createInstance();
@ -137,8 +143,10 @@ private:
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes);
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
void createSwapChain();
void cleanupSwapChain();
void recreateSwapChain();
void creatImageView();
void createImageView();
void createRenderPass();
void createGraphicPipeline();
@ -159,6 +167,8 @@ private:
void createSyncObjects();
static void framebufferResizeCallback(GLFWwindow* window, int width, int height);
};
HelloTriangleApplication::HelloTriangleApplication()