完成swapchain随窗口大小改变重建
parent
dae58772e2
commit
c6d688a055
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue