Warning vkacquirenextimagekhr error 1000001003 recreating swap chain

Swap chain recreation Introduction The application we have now successfully draws a triangle, but there are some circumstances that it isn’t handling properly yet. It is possible for the window surface to change such that the swap chain is no longer compatible with it. One of the reasons that could cause this to happen […]

Содержание

  1. Swap chain recreation
  2. Introduction
  3. Recreating the swap chain
  4. Suboptimal or out-of-date swap chain
  5. Fixing a deadlock
  6. Handling resizes explicitly
  7. Handling minimization

Swap chain recreation

Introduction

The application we have now successfully draws a triangle, but there are some circumstances that it isn’t handling properly yet. It is possible for the window surface to change such that the swap chain is no longer compatible with it. One of the reasons that could cause this to happen is the size of the window changing. We have to catch these events and recreate the swap chain.

Recreating the swap chain

Create a new recreateSwapChain function that calls createSwapChain and all of the creation functions for the objects that depend on the swap chain or the window size.

We first call vkDeviceWaitIdle , because just like in the last chapter, we shouldn’t touch resources that may still be in use. Obviously, we’ll have to recreate the swap chain itself. The image views need to be recreated because they are based directly on the swap chain images. Finally, the framebuffers directly depend on the swap chain images, and thus must be recreated as well.

To make sure that the old versions of these objects are cleaned up before recreating them, we should move some of the cleanup code to a separate function that we can call from the recreateSwapChain function. Let’s call it cleanupSwapChain :

Note that we don’t recreate the renderpass here for simplicity. In theory it can be possible for the swap chain image format to change during an applications’ lifetime, e.g. when moving a window from an standard range to an high dynamic range monitor. This may require the application to recreate the renderpass to make sure the change between dynamic ranges is properly reflected.

We’ll move the cleanup code of all objects that are recreated as part of a swap chain refresh from cleanup to cleanupSwapChain :

Note that in chooseSwapExtent we already query the new window resolution to make sure that the swap chain images have the (new) right size, so there’s no need to modify chooseSwapExtent (remember that we already had to use glfwGetFramebufferSize get the resolution of the surface in pixels when creating the swap chain).

That’s all it takes to recreate the swap chain! However, the disadvantage of this approach is that we need to stop all rendering before creating the new swap chain. It is possible to create a new swap chain while drawing commands on an image from the old swap chain are still in-flight. You need to pass the previous swap chain to the oldSwapChain field in the VkSwapchainCreateInfoKHR struct and destroy the old swap chain as soon as you’ve finished using it.

Suboptimal or out-of-date swap chain

Now we just need to figure out when swap chain recreation is necessary and call our new recreateSwapChain function. Luckily, Vulkan will usually just tell us that the swap chain is no longer adequate during presentation. The vkAcquireNextImageKHR and vkQueuePresentKHR functions can return the following special values to indicate this.

  • VK_ERROR_OUT_OF_DATE_KHR : The swap chain has become incompatible with the surface and can no longer be used for rendering. Usually happens after a window resize.
  • VK_SUBOPTIMAL_KHR : The swap chain can still be used to successfully present to the surface, but the surface properties are no longer matched exactly.

If the swap chain turns out to be out of date when attempting to acquire an image, then it is no longer possible to present to it. Therefore we should immediately recreate the swap chain and try again in the next drawFrame call.

You could also decide to do that if the swap chain is suboptimal, but I’ve chosen to proceed anyway in that case because we’ve already acquired an image. Both VK_SUCCESS and VK_SUBOPTIMAL_KHR are considered «success» return codes.

The vkQueuePresentKHR function returns the same values with the same meaning. In this case we will also recreate the swap chain if it is suboptimal, because we want the best possible result.

Fixing a deadlock

If we try to run the code now, it is possible to encounter a deadlock. Debugging the code, we find that the application reaches vkWaitForFences but never continues past it. This is because when vkAcquireNextImageKHR returns VK_ERROR_OUT_OF_DATE_KHR , we recreate the swapchain and then return from drawFrame . But before that happens, the current frame’s fence was waited upon and reset. Since we return immediately, no work is submitted for execution and the fence will never be signaled, causing vkWaitForFences to halt forever.

There is a simple fix thankfully. Delay resetting the fence until after we know for sure we will be submitting work with it. Thus, if we return early, the fence is still signaled and vkWaitForFences wont deadlock the next time we use the same fence object.

The beginning of drawFrame should now look like this:

Handling resizes explicitly

Although many drivers and platforms trigger VK_ERROR_OUT_OF_DATE_KHR automatically after a window resize, it is not guaranteed to happen. That’s why we’ll add some extra code to also handle resizes explicitly. First add a new member variable that flags that a resize has happened:

The drawFrame function should then be modified to also check for this flag:

It is important to do this after vkQueuePresentKHR to ensure that the semaphores are in a consistent state, otherwise a signaled semaphore may never be properly waited upon. Now to actually detect resizes we can use the glfwSetFramebufferSizeCallback function in the GLFW framework to set up a callback:

The reason that we’re creating a static function as a callback is because GLFW does not know how to properly call a member function with the right this pointer to our HelloTriangleApplication instance.

However, we do get a reference to the GLFWwindow in the callback and there is another GLFW function that allows you to store an arbitrary pointer inside of it: glfwSetWindowUserPointer :

This value can now be retrieved from within the callback with glfwGetWindowUserPointer to properly set the flag:

Now try to run the program and resize the window to see if the framebuffer is indeed resized properly with the window.

Handling minimization

There is another case where a swap chain may become out of date and that is a special kind of window resizing: window minimization. This case is special because it will result in a frame buffer size of 0 . In this tutorial we will handle that by pausing until the window is in the foreground again by extending the recreateSwapChain function:

The initial call to glfwGetFramebufferSize handles the case where the size is already correct and glfwWaitEvents would have nothing to wait on.

Congratulations, you’ve now finished your very first well-behaved Vulkan program! In the next chapter we’re going to get rid of the hardcoded vertices in the vertex shader and actually use a vertex buffer.

Источник

Содержание

  1. Swap chain recreation
  2. Introduction
  3. Recreating the swap chain
  4. Suboptimal or out-of-date swap chain
  5. Fixing a deadlock
  6. Handling resizes explicitly
  7. Handling minimization
  8. Name already in use
  9. VulkanTutorial / en / 03_Drawing_a_triangle / 04_Swap_chain_recreation.md

Swap chain recreation

Introduction

The application we have now successfully draws a triangle, but there are some circumstances that it isn’t handling properly yet. It is possible for the window surface to change such that the swap chain is no longer compatible with it. One of the reasons that could cause this to happen is the size of the window changing. We have to catch these events and recreate the swap chain.

Recreating the swap chain

Create a new recreateSwapChain function that calls createSwapChain and all of the creation functions for the objects that depend on the swap chain or the window size.

We first call vkDeviceWaitIdle , because just like in the last chapter, we shouldn’t touch resources that may still be in use. Obviously, we’ll have to recreate the swap chain itself. The image views need to be recreated because they are based directly on the swap chain images. Finally, the framebuffers directly depend on the swap chain images, and thus must be recreated as well.

To make sure that the old versions of these objects are cleaned up before recreating them, we should move some of the cleanup code to a separate function that we can call from the recreateSwapChain function. Let’s call it cleanupSwapChain :

Note that we don’t recreate the renderpass here for simplicity. In theory it can be possible for the swap chain image format to change during an applications’ lifetime, e.g. when moving a window from an standard range to an high dynamic range monitor. This may require the application to recreate the renderpass to make sure the change between dynamic ranges is properly reflected.

We’ll move the cleanup code of all objects that are recreated as part of a swap chain refresh from cleanup to cleanupSwapChain :

Note that in chooseSwapExtent we already query the new window resolution to make sure that the swap chain images have the (new) right size, so there’s no need to modify chooseSwapExtent (remember that we already had to use glfwGetFramebufferSize get the resolution of the surface in pixels when creating the swap chain).

That’s all it takes to recreate the swap chain! However, the disadvantage of this approach is that we need to stop all rendering before creating the new swap chain. It is possible to create a new swap chain while drawing commands on an image from the old swap chain are still in-flight. You need to pass the previous swap chain to the oldSwapChain field in the VkSwapchainCreateInfoKHR struct and destroy the old swap chain as soon as you’ve finished using it.

Suboptimal or out-of-date swap chain

Now we just need to figure out when swap chain recreation is necessary and call our new recreateSwapChain function. Luckily, Vulkan will usually just tell us that the swap chain is no longer adequate during presentation. The vkAcquireNextImageKHR and vkQueuePresentKHR functions can return the following special values to indicate this.

  • VK_ERROR_OUT_OF_DATE_KHR : The swap chain has become incompatible with the surface and can no longer be used for rendering. Usually happens after a window resize.
  • VK_SUBOPTIMAL_KHR : The swap chain can still be used to successfully present to the surface, but the surface properties are no longer matched exactly.

If the swap chain turns out to be out of date when attempting to acquire an image, then it is no longer possible to present to it. Therefore we should immediately recreate the swap chain and try again in the next drawFrame call.

You could also decide to do that if the swap chain is suboptimal, but I’ve chosen to proceed anyway in that case because we’ve already acquired an image. Both VK_SUCCESS and VK_SUBOPTIMAL_KHR are considered «success» return codes.

The vkQueuePresentKHR function returns the same values with the same meaning. In this case we will also recreate the swap chain if it is suboptimal, because we want the best possible result.

Fixing a deadlock

If we try to run the code now, it is possible to encounter a deadlock. Debugging the code, we find that the application reaches vkWaitForFences but never continues past it. This is because when vkAcquireNextImageKHR returns VK_ERROR_OUT_OF_DATE_KHR , we recreate the swapchain and then return from drawFrame . But before that happens, the current frame’s fence was waited upon and reset. Since we return immediately, no work is submitted for execution and the fence will never be signaled, causing vkWaitForFences to halt forever.

There is a simple fix thankfully. Delay resetting the fence until after we know for sure we will be submitting work with it. Thus, if we return early, the fence is still signaled and vkWaitForFences wont deadlock the next time we use the same fence object.

The beginning of drawFrame should now look like this:

Handling resizes explicitly

Although many drivers and platforms trigger VK_ERROR_OUT_OF_DATE_KHR automatically after a window resize, it is not guaranteed to happen. That’s why we’ll add some extra code to also handle resizes explicitly. First add a new member variable that flags that a resize has happened:

The drawFrame function should then be modified to also check for this flag:

It is important to do this after vkQueuePresentKHR to ensure that the semaphores are in a consistent state, otherwise a signaled semaphore may never be properly waited upon. Now to actually detect resizes we can use the glfwSetFramebufferSizeCallback function in the GLFW framework to set up a callback:

The reason that we’re creating a static function as a callback is because GLFW does not know how to properly call a member function with the right this pointer to our HelloTriangleApplication instance.

However, we do get a reference to the GLFWwindow in the callback and there is another GLFW function that allows you to store an arbitrary pointer inside of it: glfwSetWindowUserPointer :

This value can now be retrieved from within the callback with glfwGetWindowUserPointer to properly set the flag:

Now try to run the program and resize the window to see if the framebuffer is indeed resized properly with the window.

Handling minimization

There is another case where a swap chain may become out of date and that is a special kind of window resizing: window minimization. This case is special because it will result in a frame buffer size of 0 . In this tutorial we will handle that by pausing until the window is in the foreground again by extending the recreateSwapChain function:

The initial call to glfwGetFramebufferSize handles the case where the size is already correct and glfwWaitEvents would have nothing to wait on.

Congratulations, you’ve now finished your very first well-behaved Vulkan program! In the next chapter we’re going to get rid of the hardcoded vertices in the vertex shader and actually use a vertex buffer.

Источник

Name already in use

VulkanTutorial / en / 03_Drawing_a_triangle / 04_Swap_chain_recreation.md

  • Go to file T
  • Go to line L
  • Copy path
  • Copy permalink

Copy raw contents

Copy raw contents

The application we have now successfully draws a triangle, but there are some circumstances that it isn’t handling properly yet. It is possible for the window surface to change such that the swap chain is no longer compatible with it. One of the reasons that could cause this to happen is the size of the window changing. We have to catch these events and recreate the swap chain.

Recreating the swap chain

Create a new recreateSwapChain function that calls createSwapChain and all of the creation functions for the objects that depend on the swap chain or the window size.

We first call vkDeviceWaitIdle , because just like in the last chapter, we shouldn’t touch resources that may still be in use. Obviously, we’ll have to recreate the swap chain itself. The image views need to be recreated because they are based directly on the swap chain images. Finally, the framebuffers directly depend on the swap chain images, and thus must be recreated as well.

To make sure that the old versions of these objects are cleaned up before recreating them, we should move some of the cleanup code to a separate function that we can call from the recreateSwapChain function. Let’s call it cleanupSwapChain :

Note that we don’t recreate the renderpass here for simplicity. In theory it can be possible for the swap chain image format to change during an applications’ lifetime, e.g. when moving a window from an standard range to an high dynamic range monitor. This may require the application to recreate the renderpass to make sure the change between dynamic ranges is properly reflected.

We’ll move the cleanup code of all objects that are recreated as part of a swap chain refresh from cleanup to cleanupSwapChain :

Note that in chooseSwapExtent we already query the new window resolution to make sure that the swap chain images have the (new) right size, so there’s no need to modify chooseSwapExtent (remember that we already had to use glfwGetFramebufferSize get the resolution of the surface in pixels when creating the swap chain).

That’s all it takes to recreate the swap chain! However, the disadvantage of this approach is that we need to stop all rendering before creating the new swap chain. It is possible to create a new swap chain while drawing commands on an image from the old swap chain are still in-flight. You need to pass the previous swap chain to the oldSwapChain field in the VkSwapchainCreateInfoKHR struct and destroy the old swap chain as soon as you’ve finished using it.

Suboptimal or out-of-date swap chain

Now we just need to figure out when swap chain recreation is necessary and call our new recreateSwapChain function. Luckily, Vulkan will usually just tell us that the swap chain is no longer adequate during presentation. The vkAcquireNextImageKHR and vkQueuePresentKHR functions can return the following special values to indicate this.

  • VK_ERROR_OUT_OF_DATE_KHR : The swap chain has become incompatible with the surface and can no longer be used for rendering. Usually happens after a window resize.
  • VK_SUBOPTIMAL_KHR : The swap chain can still be used to successfully present to the surface, but the surface properties are no longer matched exactly.

If the swap chain turns out to be out of date when attempting to acquire an image, then it is no longer possible to present to it. Therefore we should immediately recreate the swap chain and try again in the next drawFrame call.

You could also decide to do that if the swap chain is suboptimal, but I’ve chosen to proceed anyway in that case because we’ve already acquired an image. Both VK_SUCCESS and VK_SUBOPTIMAL_KHR are considered «success» return codes.

The vkQueuePresentKHR function returns the same values with the same meaning. In this case we will also recreate the swap chain if it is suboptimal, because we want the best possible result.

Fixing a deadlock

If we try to run the code now, it is possible to encounter a deadlock. Debugging the code, we find that the application reaches vkWaitForFences but never continues past it. This is because when vkAcquireNextImageKHR returns VK_ERROR_OUT_OF_DATE_KHR , we recreate the swapchain and then return from drawFrame . But before that happens, the current frame’s fence was waited upon and reset. Since we return immediately, no work is submitted for execution and the fence will never be signaled, causing vkWaitForFences to halt forever.

There is a simple fix thankfully. Delay resetting the fence until after we know for sure we will be submitting work with it. Thus, if we return early, the fence is still signaled and vkWaitForFences wont deadlock the next time we use the same fence object.

The beginning of drawFrame should now look like this:

Handling resizes explicitly

Although many drivers and platforms trigger VK_ERROR_OUT_OF_DATE_KHR automatically after a window resize, it is not guaranteed to happen. That’s why we’ll add some extra code to also handle resizes explicitly. First add a new member variable that flags that a resize has happened:

The drawFrame function should then be modified to also check for this flag:

It is important to do this after vkQueuePresentKHR to ensure that the semaphores are in a consistent state, otherwise a signaled semaphore may never be properly waited upon. Now to actually detect resizes we can use the glfwSetFramebufferSizeCallback function in the GLFW framework to set up a callback:

The reason that we’re creating a static function as a callback is because GLFW does not know how to properly call a member function with the right this pointer to our HelloTriangleApplication instance.

However, we do get a reference to the GLFWwindow in the callback and there is another GLFW function that allows you to store an arbitrary pointer inside of it: glfwSetWindowUserPointer :

This value can now be retrieved from within the callback with glfwGetWindowUserPointer to properly set the flag:

Now try to run the program and resize the window to see if the framebuffer is indeed resized properly with the window.

There is another case where a swap chain may become out of date and that is a special kind of window resizing: window minimization. This case is special because it will result in a frame buffer size of 0 . In this tutorial we will handle that by pausing until the window is in the foreground again by extending the recreateSwapChain function:

The initial call to glfwGetFramebufferSize handles the case where the size is already correct and glfwWaitEvents would have nothing to wait on.

Congratulations, you’ve now finished your very first well-behaved Vulkan program! In the next chapter we’re going to get rid of the hardcoded vertices in the vertex shader and actually use a vertex buffer.

Источник

  • Introduction

  • Recreating the swap chain

  • Suboptimal or out-of-date swap chain

  • Fixing a deadlock

  • Handling resizes explicitly

  • Handling minimization

Introduction

The application we have now successfully draws a triangle, but there are some
circumstances that it isn’t handling properly yet. It is possible for the window
surface to change such that the swap chain is no longer compatible with it. One
of the reasons that could cause this to happen is the size of the window
changing. We have to catch these events and recreate the swap chain.

Recreating the swap chain

Create a new recreateSwapChain function that calls createSwapChain and all
of the creation functions for the objects that depend on the swap chain or the
window size.

void recreateSwapChain() {
    vkDeviceWaitIdle(device);

    createSwapChain();
    createImageViews();
    createFramebuffers();
}

We first call vkDeviceWaitIdle, because just like in the last chapter, we
shouldn’t touch resources that may still be in use. Obviously, we’ll have to recreate
the swap chain itself. The image views need to be recreated because they are based
directly on the swap chain images. Finally, the framebuffers directly depend on the
swap chain images, and thus must be recreated as well.

To make sure that the old versions of these objects are cleaned up before
recreating them, we should move some of the cleanup code to a separate function
that we can call from the recreateSwapChain function. Let’s call it
cleanupSwapChain:

void cleanupSwapChain() {

}

void recreateSwapChain() {
    vkDeviceWaitIdle(device);

    cleanupSwapChain();

    createSwapChain();
    createImageViews();
    createFramebuffers();
}

Note that we don’t recreate the renderpass here for simplicity. In theory it can be possible for the swap chain image format to change during an applications’ lifetime, e.g. when moving a window from an standard range to an high dynamic range monitor. This may require the application to recreate the renderpass to make sure the change between dynamic ranges is properly reflected.

We’ll move the cleanup code of all objects that are recreated as part of a swap
chain refresh from cleanup to cleanupSwapChain:

void cleanupSwapChain() {
    for (size_t i = 0; i < swapChainFramebuffers.size(); i++) {
        vkDestroyFramebuffer(device, swapChainFramebuffers[i], nullptr);
    }

    for (size_t i = 0; i < swapChainImageViews.size(); i++) {
        vkDestroyImageView(device, swapChainImageViews[i], nullptr);
    }

    vkDestroySwapchainKHR(device, swapChain, nullptr);
}

void cleanup() {
    cleanupSwapChain();

    vkDestroyPipeline(device, graphicsPipeline, nullptr);
    vkDestroyPipelineLayout(device, pipelineLayout, nullptr);

    vkDestroyRenderPass(device, renderPass, nullptr);

    for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
        vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
        vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
        vkDestroyFence(device, inFlightFences[i], nullptr);
    }

    vkDestroyCommandPool(device, commandPool, nullptr);

    vkDestroyDevice(device, nullptr);

    if (enableValidationLayers) {
        DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
    }

    vkDestroySurfaceKHR(instance, surface, nullptr);
    vkDestroyInstance(instance, nullptr);

    glfwDestroyWindow(window);

    glfwTerminate();
}

Note that in chooseSwapExtent we already query the new window resolution to
make sure that the swap chain images have the (new) right size, so there’s no
need to modify chooseSwapExtent (remember that we already had to use
glfwGetFramebufferSize get the resolution of the surface in pixels when
creating the swap chain).

That’s all it takes to recreate the swap chain! However, the disadvantage of
this approach is that we need to stop all rendering before creating the new swap
chain. It is possible to create a new swap chain while drawing commands on an
image from the old swap chain are still in-flight. You need to pass the previous
swap chain to the oldSwapChain field in the VkSwapchainCreateInfoKHR struct
and destroy the old swap chain as soon as you’ve finished using it.

Suboptimal or out-of-date swap chain

Now we just need to figure out when swap chain recreation is necessary and call
our new recreateSwapChain function. Luckily, Vulkan will usually just tell us that the swap chain is no longer adequate during presentation. The vkAcquireNextImageKHR and
vkQueuePresentKHR functions can return the following special values to
indicate this.

  • VK_ERROR_OUT_OF_DATE_KHR: The swap chain has become incompatible with the
    surface and can no longer be used for rendering. Usually happens after a window resize.
  • VK_SUBOPTIMAL_KHR: The swap chain can still be used to successfully present
    to the surface, but the surface properties are no longer matched exactly.
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!");
}

If the swap chain turns out to be out of date when attempting to acquire an
image, then it is no longer possible to present to it. Therefore we should
immediately recreate the swap chain and try again in the next drawFrame call.

You could also decide to do that if the swap chain is suboptimal, but I’ve
chosen to proceed anyway in that case because we’ve already acquired an image.
Both VK_SUCCESS and VK_SUBOPTIMAL_KHR are considered «success» return codes.

result = vkQueuePresentKHR(presentQueue, &presentInfo);

if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
    recreateSwapChain();
} else if (result != VK_SUCCESS) {
    throw std::runtime_error("failed to present swap chain image!");
}

currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;

The vkQueuePresentKHR function returns the same values with the same meaning.
In this case we will also recreate the swap chain if it is suboptimal, because
we want the best possible result.

Fixing a deadlock

If we try to run the code now, it is possible to encounter a deadlock.
Debugging the code, we find that the application reaches vkWaitForFences but
never continues past it. This is because when vkAcquireNextImageKHR returns
VK_ERROR_OUT_OF_DATE_KHR, we recreate the swapchain and then return from
drawFrame. But before that happens, the current frame’s fence was waited upon
and reset. Since we return immediately, no work is submitted for execution and
the fence will never be signaled, causing vkWaitForFences to halt forever.

There is a simple fix thankfully. Delay resetting the fence until after we
know for sure we will be submitting work with it. Thus, if we return early, the
fence is still signaled and vkWaitForFences wont deadlock the next time we
use the same fence object.

The beginning of drawFrame should now look like this:

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!");
}

// Only reset the fence if we are submitting work
vkResetFences(device, 1, &inFlightFences[currentFrame]);

Handling resizes explicitly

Although many drivers and platforms trigger VK_ERROR_OUT_OF_DATE_KHR automatically after a window resize, it is not guaranteed to happen. That’s why we’ll add some extra code to also handle resizes explicitly. First add a new member variable that flags that a resize has happened:

std::vector<VkFence> inFlightFences;

bool framebufferResized = false;

The drawFrame function should then be modified to also check for this flag:

if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {
    framebufferResized = false;
    recreateSwapChain();
} else if (result != VK_SUCCESS) {
    ...
}

It is important to do this after vkQueuePresentKHR to ensure that the semaphores are in a consistent state, otherwise a signaled semaphore may never be properly waited upon. Now to actually detect resizes we can use the glfwSetFramebufferSizeCallback function in the GLFW framework to set up a callback:

void initWindow() {
    glfwInit();

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

    window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
    glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
}

static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {

}

The reason that we’re creating a static function as a callback is because GLFW does not know how to properly call a member function with the right this pointer to our HelloTriangleApplication instance.

However, we do get a reference to the GLFWwindow in the callback and there is another GLFW function that allows you to store an arbitrary pointer inside of it: glfwSetWindowUserPointer:

window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
glfwSetWindowUserPointer(window, this);
glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);

This value can now be retrieved from within the callback with glfwGetWindowUserPointer to properly set the flag:

static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {
    auto app = reinterpret_cast<HelloTriangleApplication*>(glfwGetWindowUserPointer(window));
    app->framebufferResized = true;
}

Now try to run the program and resize the window to see if the framebuffer is indeed resized properly with the window.

Handling minimization

There is another case where a swap chain may become out of date and that is a special kind of window resizing: window minimization. This case is special because it will result in a frame buffer size of 0. In this tutorial we will handle that by pausing until the window is in the foreground again by extending the recreateSwapChain function:

void recreateSwapChain() {
    int width = 0, height = 0;
    glfwGetFramebufferSize(window, &width, &height);
    while (width == 0 || height == 0) {
        glfwGetFramebufferSize(window, &width, &height);
        glfwWaitEvents();
    }

    vkDeviceWaitIdle(device);

    ...
}

The initial call to glfwGetFramebufferSize handles the case where the size is already correct and glfwWaitEvents would have nothing to wait on.

Congratulations, you’ve now finished your very first well-behaved Vulkan
program! In the next chapter we’re going to get rid of the hardcoded vertices in
the vertex shader and actually use a vertex buffer.

C++ code /
Vertex shader /
Fragment shader

* Docking: added comments. added experimental TabItemFlagsOverrideSet to ImGuiWindowClass.

(Could probably do something similar with TabBarFlagsOverrideSet+Clear for ocornut#2700 later.)

* Docking: docked window honor tab and text colors by storing them. (ocornut#2771)

Later to lead into ocornut#2700 and ocornut#2539
Move tab submission block above in DockNodeUpdateTabBar(), not strictly necessary for this change as is, but useful if needing to apply override for TitleBg* as we'd need a value for node->VisibleWindow earlier than currently set.

* Fixed some compile warnings with Clang on Windows (ocornut#3754)

* Viewports, Backends: Vulkan: handle VK_ERROR_OUT_OF_DATE_KHR when resizing secondary viewport (ocornut#3766, ocornut#3758)

Cannot repro here but appears to a user on Linux. Fix may be not super solid.

* Docking: on node split, update memorized DockId for currently closed windows (ocornut#3716)

Amended by @ocornut with same fix in DockBuilderRemoveNodeChildNodes().

* Docking: fix gap in hit test hold when using ImGuiDockNodeFlags_PassthruCentralNode touching the edge of a viewport. (ocornut#3733)

* Viewports: (breaking) removed ImGuiPlatformIO::MainViewport which is now pretty much unused and duplicate (and misleading as we will evolve the concept)

Use GetMainViewport() if stuck.

* Viewports: Moved in own section of imgui.h ahead of merging a small part of viewport interface to master.

* Viewports: trying to treat GetMainViewport() as const. Reducing unnecessary casts of ImGuiViewportP*

Metrics: readded root Drawlists node in metrics to match master.
The (void*) casts are implying const-casst but currently left GetMainViewport() as returning non-const.

* Viewports: (Breaking) turned GetWorkPos(), GetWorkSize() into straight fields -> WorkPos, WorkSize before exposing in master branch.

* Fix for compiling imgui_internal.h without operators + made GetWorkRect() consistent with clamped WorkSize.

* Misc tweaks - mostly toward minimizing diff in upcoming backport merge of a few viewport structures in master

* Viewports: Fix issue inferring viewport z-order when new popups gets created. (ocornut#3734) + Metrics updates.

Revert 6bc5266
Showing inferred order and missing flags in metrics.

* Viewports: Setting the new (currently dummy) flags on viewports. (ocornut#3789, ocornut#1542, ocornut#3680, ocornut#3350, ocornut#3012, ocornut#2471)

Amend the merging of f14042c (merge ee59d7a)

* Remove redundant GetMainViewport decl in imgui.h (ocornut#3801, ocornut#3800)

* Docking: Made close button enable logic consistent on dockspace. When no docked window have a close button or it is disabled on the node, the space is given to tabs.

Clarified close_button_is_visible vs close_button_is_enabled behavior in DockNodeUpdateTabBar().. (ocornut#3633, ocornut#3521)
Reduced alpha of disabled close button a little bit further.
Removed 'EnableCloseButton' which was actually unused (can't be infered early, need ->VisibleWindow anyway, which is not == ->ActiveWindow)

* Examples: DX9-DX11: Removed half-assed DPI awareness enable. Updated Docking/Viewports part of Changelog (e.g. removed bits that are now already in master, clarified some added bits)

* Viewports: Fix setting of ImGuiViewportFlags_NoRendererClear. (ocornut#3213)

* Internals: Add a way to request window to not process any interactions for specified number of frames.

* Added missing IMGUI_API to internal docking-related structs. (ocornut#3850)

* Internals: Docking: some renaming.

* Internals: rename RootWindow->RootWindowDockTree, RootWindowDockStop->RootWindow.

Why?  So by default RootWindow matches user expectation on both branches, and RootWindowDockTree is more intentful.
(Actually should reduce diff between master<>docking)

* Viewports, Backend: SDL: Fix missing ImGuiBackendFlags_HasSetMousePos flag in docking branch (ok in master), GLFW: Fix application of WantSetMousePos. (ocornut#1542, ocornut#787)

Shows how little this feature is used with nav (was designed for small devices and frankly may be dropped) - but the backend support itself we will make use of for other features.

* Viewports, Internals: added GetViewportPlatformMonitor() will a safety net to keep code portable + simplified handling of disconnected monitor in Begin().

* ImDrawFlags: rework/revert c2d6d26 + 39432bf in a way that is closer to old version and back to opt-in but with default 0 = all corners.

* Removed deprecated flag stopping compilation (ocornut#3902)

* Docking: Dockspace() never draws a background. (ocornut#3924)

* Docking: undocking nodes/windows covering most of the monitor max their size down to 90% to ease further manipulations.

Kind of a welcome hack.

* Docking: Add support for split_outer in DockContextCalcDropPosForDocking().
Misc: Add FIXME regarding behavior of some window fields.

* Viewports, Backends: Vulkan: Rebuild swapchain on VK_SUBOPTIMAL_KHR. (ocornut#3881)

* BeginMainMenuBar(): remove expectation that we don't know menu bar height ahead, allowing up to generalize placement in any direction (will be done in master)

Amend 75de34e

* Viewports: Hotfix for crash in monitor array access, caused by 4b9bc49. (ocornut#3967)

* TabBar: Use mouse position instead of hardcoded +1/-1 offset when reordering tabs.

Fixes tab reordering in test engine when using fast mode.

# Conflicts:
#	imgui_widgets.cpp

* TabBar: Amend previous commit. Fix tab reordering when tab bar has scrolling.

Some tidying up with helpers + honor 16-bit offsets as with other tab bar features (unlikely single reorder can reach that but consistent)

* Backends, Viewports: GLFW: Add a workaround for stuck keys after closing a GLFW window (ocornut#3837).

* Docking: DockSpace() returns its node ID + adding branch changelog.

* Docking: fix undocking from tab-bar by moving mouse horizontally, broken by d705192.

* Docking: removed io.ConfigDockingWithShift option. (ocornut#2109)

* Docking: fix undocking from tab-bar by moving mouse horizontally, amend 3ed07a8 + d705192.

Automation system may drag e.g. right-most tab far left (and vice-versa) and one frame and our current logic would fail at it.

* Fix popup positioning, broken by 84e6fe4. (ocornut#3991, ocornut#3982)

* Docking: Fixed restoring of tab order within a dockspace or a split node.

(tests in "docking_tab_order")

* Docking: Fixed multiple simultaneously reappearing window from appearing undocked in their initial frame.

* Docking: Fixed reappearing docked windows with no close button showing a tab with extraneous space for one frame.

* Docking: move NavWindow to SelectedTabId application lower to leave a chance for in-between code to alter focus. + store per-node window menu button id to simplify usage.

* Docking: Fix window menu button. Broken by 3f16a52 (ocornut#4043)

Worked on single-frame click.

* Changelog: added docking+entries from 1.72 to 1.82 to increase their visibility.

* Backends: Vulkan: Fix for using IMGUI_IMPL_VULKAN_NO_PROTOTYPES (ocornut#4151, ocornut#3759, ocornut#3227)

* Docking: Docking node tab bar honors ItemInnerSpacing.x before first tab. Tweak rendering and alignment of dock node menu marker. (ocornut#4130)

+ Fix ~0 in EndFrameDrawDimmedBackgrounds() which is obsolete way of signifying "all round corners".

* Docking: Fix IsWindowAppearing() and ImGuiCond_Appearing on docked windows. (ocornut#4177, ocornut#3982, ocornut#1497, ocornut#1061)

* Docking: Amend 91704b7, window->DockXXX booleans not properly cleared when window not docked. (ocornut#4177, ocornut#3982, ocornut#1497, ocornut#1061)

Fix issue with freshly split windows/nodes incorrectly returning true to IsWindowAppearing().

* Docking: Fix IsWindowAppearing() unnecessarily returning true twice in a row. (ocornut#4177, ocornut#3982, ocornut#1497, ocornut#1061) + added a zealous assert.

* Docking: Clicking on the right-most close button of a docking node closes all windows. (ocornut#4186)

* Docking: comments (ocornut#4189)

* Added PushDisabled(), PopDisabled() currently only exposed in imgui_internal.h (ocornut#211)

* ImVector: added clear_delete(), clear_destruct() helpers.

# Conflicts:
#	imgui.cpp

* Nav, Drag and Drop, Docking: fixed two issues leading nav result to conflict with moving a window. (ocornut#4211, ocornut#3025)

* Backends, Viewports: Vulkan: Fix the use of the incorrect fence in wait for fence. (ocornut#4208)

The fence being waited upon was not the one associated with the current frame.
This results in validation error detecting a reset of command buffers still in use and resetting fences while still in use.
Read more details in ocornut#4208

* Metrics: Tentative fix for bad printf format.

Ref b53b8f5, a7a1b3b

* Viewport: extracted code out of Begin() into WindowSyncOwnedViewport() - no other change

* Viewports: Fix popup/tooltip created without a parent window from being given a ParentViewportId value of the implicit/fallback window. (ocornut#4236, ocornut#2409)

Amend 3ead982

* Backends: amends to 1db1066 + merge minor bits from docking incl SetActiveIdUsingNavAndKeys().

No need to clear fields before deletion. DX12: renamed to match docking branch.

* Backends: Viewports: renamed viewport storage structures ImGuiViewportDataXXXX -> ImGui_ImplXXXX_ViewportData and locals (matching naming convention in 70c6038)

* Docking: removed DockNodeFlagsOverrideClear flags from ImGuiWindowClass. (ocornut#2999, ocornut#3521, ocornut#3633)

+ extraded bits of metrics into DebugNodeDockNodeFlags()

* Docking: Reworked node flags saving/inheritance... (ocornut#4292, ocornut#3834, ocornut#3633, ocornut#3521, ocornut#3492, ocornut#3335, ocornut#2999, ocornut#2648)

..so that flags enforced by docked windows via the DockNodeFlagsOverrideSet mechanism are are not left in empty dockspace nodes once the windows gets undocked.

* Docking: Added ImGuiDockNodeFlags_NoDockingOverEmpty. Breaking definition of ImGuiDockNodeFlags_NoDockingOverOther which now means "non empty node". (ocornut#3492, ocornut#2648, ocornut#4292)

* Docking: Fixed crash issues using DockBuilderRemoveNode() in some situations. (ocornut#3111, ocornut#3179, ocornut#3203, ocornut#4295)

If the deleted root node isn't part of a dockspace with a central node, it won't be "protected" but removed when last window gets removed.

* Docking: Fix crash when a dock node gets re-qualified as dockspace>floating>dockspace.. (ocornut#3203, ocornut#4295)

Which tends to happen when incorrectly calling DockBuilderAddNode() without ImGuiDockNodeFlags_Dockspace and using it as a Dockspace on the next frame after the floating window hosting the node has been automatically created.

* Added missing IMGUI_API to GetViewportPlatformMonitor. (ocornut#4309)

* Backends: Win32, SDL, GLFW: only honor io.WantSetMousePos when focused + fix GLFW uninstalling handler + tweaks to reduce branch drift with docking. (ocornut#787, ocornut#2445, ocornut#2696, ocornut#3751, ocornut#4377)

# Conflicts:
#	backends/imgui_impl_glfw.cpp
#	backends/imgui_impl_sdl.cpp
#	backends/imgui_impl_win32.cpp

* IO: modify io.AddFocusEvent() to tolerate in/out for multi-viewports. Amend 2f40be6. (ocornut#3532)

* Fix BeginDisabled(false), (ocornut#211, ocornut#4452)

* Fix BeginDisabled(false), again, (ocornut#211, ocornut#4452, ocornut#4453) Version 1.84.1

(forced pushed since our earlier versioning didn't sort correctly in github web)

# Conflicts:
#	docs/CHANGELOG.txt

* Backends: GLFW: Fixed unused variable warning for empty assert macro. (ocornut#4459)

* Docking: fixed settings load issue when mouse wheeling. (ocornut#4310)

* Docking: fix 58f5092 (ocornut#4310)

If we clear _ChildWindow flag we must remove it from here otherwise render loop will fail.

* Docking: warning fix for when IM_ASSERT() is empty

* Fixed bad merge of Changelog in docking branch

* Internals: refactored IsWindowHovered()/IsWindowFocused() to make their logic more similar + change underlying value of ImGuiHoveredFlags_AllowWhenBlockedByPopup + comment out docking only flags.

* Fixed _ChildWindows from leaking docking hierarchy. Added ImGuiFocusedFlags_DockHierarchy and ImGuiHoveredFlags_DockHierarchy.

* Viewports: fixed unnecessary creation of temporary viewports when multiple docked windows got reassigned to a new node (created mid-frame) which already has a HostWindow

* Viewports: Fixed a crash while a window owning its viewport disappear while being dragged.

t would manifest when e.g. reconfiguring dock nodes while dragging.

* Viewports: fix window with viewport ini data immediately merged into a host viewport from leaving a temporary viewport alive for a frame (would leak into backend).

* Fixed IsWindowFocused/IsWindowHovered with _ChildWindows for not following through popup parents (amend 6b1e094, fix ocornut#4527)

* Viewports: extracted DestroyViewport() out of UpdateViewportsNewFrame() function.

* Docking: bits.

* Docking: floating node with a central node hides properly when nothing is docked + rename.

* Docking: Improved resizing system so that non-central zone are better at keeping their fixed size.

* Nav: Fixed an issue with losing focus on docked windows when pressing Alt while keyboard navigation is disabled. (ocornut#4547, ocornut#4439)

* Docking: Fixed IsItemHovered() and functions depending on it (e.g. BeginPopupContextItem()) when called after Begin() on a docked window (ocornut#3851)

Fix ee643b2

* Added ImGuiFocusedFlags_NoPopupHierarchy and ImGuiHoveredFlags_NoPopupHierarchy (followup ocornut#4527)

IsWindowFocused: fix flag usage (amend 6b1e094) was technically harmless because of light typing.

* Docking: reinstate io.ConfigDockingWithShift option. (ocornut#4643)

This more or less reverts commit 3ed07a8.

* Fixed nested BeginDisabled()/EndDisabled() bug in Docking branch due to bad merge. (ocornut#4655, ocornut#4452, ocornut#4453, ocornut#4462)

* Backends: Made it possible to shutdown default Platform Backends before the Renderer backends. (ocornut#4656)

* Viewports: Made it possible to explicitly assign ImGuiWindowClass::ParentViewportId to 0. (ocornut#3152, ocornut#2871)

* Fixed tooltip in own viewport over modal from being incorrectly dimmed. (ocornut#4729)

Normally we would aim to ensure that g.Windows[] gets maintained to reflect display layer but it is presently non trivial.

* Fixed crash on right-click without modal, introduced by previous commit a3667f4,  (ocornut#4729)

* Viewports: fix missing default per-window value for ParentViewportId due to zero-cleared in-window instance (ocornut#4756)

Broken by 2080d12

* Docking: Fixed a bug undocking windows docked into a non-visible or _KeepAliveOnly dockspace. (ocornut#4757)

* Docking: Fix typo (had no side effect) (ocornut#4778)

Co-authored-by: Mikko Sivulainen <mikko.sivulainen@supercell.com>

* Viewports: Fixed CTRL+TAB highlight outline on docked windows not always fitting in host viewport + moved EndFrameDrawDimmedBackgrounds() call + removed duplicate code in Begin() already in EndFrameDrawDimmedBackgrounds()

* Docking: Fixed incorrectly rounded tab bars for dock node that are not at the top of their dock tree.

* Docking: Fixed single-frame node pos/size inconsistencies when window stop or start being submitted.

Fix 718e15c while preserving its intended property. Tested by "docking_window_appearing_layout". (ocornut#2109)

* Docking: internals: extracted rounding corner calculation into reusable CalcRoundingFlagsForRectInRect() function.

* Docking: docked windows honor ImGuiCol_WindowBg. Host window in charge of rendering seams. (ocornut#2700, ocornut#2539 + Docked windows honor display their border properly. (ocornut#2522)

Plus: better support for transparent one in nodes
Side effects: DockContextBindNodeToWindow doesn't alter node->IsVisible.
Side effects: ImDrawList:: _ResetForNewFrame() needs to merge, sane (in case of
(Amended, force-pushed)

* Docking: Amend b16f738 fixed dimming of docked window + removed thin highlight around windows (never worked on docked window, not viewports friendly, hard to move to EndFrame) (ocornut#2700, ocornut#2539, ocornut#2522)

* Nav, Docking: reworked modal/ctrl+tab dimming system to be entirely processed at end of the frame, which will simplify things for an upcoming commit.

(Will backport some of this back to master now.)

* Nav, Docking: Fix dimming on docked windows.

* Nav, Docking: Fix crash on dimming docked window and DockSpaceOverViewport() with PassthruCentralNode.

(amend 1dc3af3, 23ef6c1, 657073a)

* Added an assertion for the common user mistake of using "" as an identifier at the root level of a window. (ocornut#1414, ocornut#2562, ocornut#2807, ocornut#4008, ocornut#4158, ocornut#4375, ocornut#4548, ocornut#4657, ocornut#4796)

  ocornut#4158, ocornut#4375, ocornut#4548, ocornut#4657, ocornut#4796)

* Docking: prevent docking any window created above a popup/modal. (ocornut#4317)

* Internals: UpdateWindowInFocusOrderList: amend a528398 to fix docking. (ocornut#3496, ocornut#4797)

* Internals: reduced side-effects of setting window->HiddenFramesForRenderOnly > 0

* Viewports: Fixed a CTRL+TAB crash with viewports enabled (ocornut#4023, ocornut#787) (amend 1dc3af3, 23ef6c1, 657073a)

+ Expose FindHoveredViewportFromPlatformWindowStack() in imgui_internal.h

* Update .gitignore

* Backends: OSX: Fixed typo.

* Rename io.AddKeyModEvent() -> io.AddKeyModsEvent() and updated backends accordingly. (ocornut#2625, ocornut#4858)

Amend 790132a (breaking)

# Conflicts:
#	backends/imgui_impl_glfw.cpp
#	backends/imgui_impl_sdl.cpp
#	backends/imgui_impl_win32.cpp

* IO: fix SetKeyEventNativeData() not handling ImGuiKey_None the same way as AddKeyEvent(). (ocornut#4905, ocornut#4858)

* Merge "Backends: SDL: Fix for Emscriptem. Amend 98ce013." + Fix bad merge from master of "is_app_focused" property (Amend 0647ba3)

* Viewports: Fixed active InputText() from preventing viewports to merge. (ocornut#4212)

* Viewports: Relaxed specs for backend supporting ImGuiBackendFlags_HasMouseHoveredViewport. Backends: SDL: Added support for simplified HasMouseHoveredViewport. (ocornut#1542, ocornut#4665)

* IO: added AddMouseViewportEvent() + used in backends.

* Docking: Fixed a CTRL+TAB crash when aiming at an empty docked window. (ocornut#4792)

* Revert moving ImGuiKeyModFlags to internal.h (amendc906c65)

# Conflicts:
#	imgui.cpp

* Backends: SDL: no support for ImGuiBackendFlags_HasMouseHoveredViewport under OSX/LInux (ocornut#4960)

* Docking: Fixed size constraints not working on single window holding on a dock id (still doesn't work on docked windows).

* Docking: Tabs use their own identifier (in order to make window->ID refer to whole window in test engine).  Also prevents Tab ID from clashing with "" which was common.

* Docking: Fixed CTRL+TAB back into a docked window not selecting menu layer when no item are on main layer.

Could merge on master.

* Backends: SDL: Amend 08350e5, multi-viewports mouse tracking works under Linux. (ocornut#4960) + Reword tests to help static analysis.

* Docking: fixed potential crash if a passthrough dock node is submitted without a child intermediate (currently not possible via API)

* Internals: rework RenderMouseCursor() signature so we can use it in docking branch more naturally. (Merged from master+ rework for docking)

# Conflicts:
#	imgui.cpp
#	imgui_draw.cpp

* Viewports: Fixed main viewport size not matching ImDrawData::DisplaySize for one frame during resize when multi-viewports are disabled. (ocornut#4900)

* Docking: Fixed floating docked nodes not being clamped into viewport workrect to stay reachable when g.ConfigWindowsMoveFromTitleBarOnly is set and multi-viewports are disabled. (ocornut#5044)

* Viewports: Fixed translating a host viewport from briefly altering the size of AlwaysAutoResize windows. (ocornut#5057)

* Backends: SDL: Fix multi-viewport dragging issue with SDL on some systems. (ocornut#5012)

* Backends: SDL: Fix more dragging issues. SDL_CaptureMouse() is essentially broken. (ocornut#5012, ocornut#5082)

master got c5f6721 which is combining f337378 and this commit.

* Windows: Fixed first-time windows appearing in negative coordinates. (ocornut#5215, ocornut#3414)

Regression added in 6af92b0

* Backends: OSX, Metal: Added multi-viewports support. (ocornut#4821, ocornut#2778)

* Backends: OSX, Metal: Amend d111133, tidying up, remove unused, misc tweaks. . (ocornut#4821, ocornut#2778)

* Backends: OSX: Implement ImGui_ImplOSX_ShowWindow(). (ocornut#5299)

* Examples: Apple+OpenGL: Fix build.

* Docking: Fixed moving window being interrupted when undocing a window with "io.ConfigDockingAlwaysTabBar = true". (ocornut#5324)

Regression introduced in 6b77668

* Docking: Fix unhiding tab bar regression. (ocornut#5325, ocornut#5181)

Broken by 9038678

* Misc: Fix custom assertion macro failing to compile imgui.cpp (ocornut#5378)

* Docking: Fixed incorrect focus highlight on docking node when focusing empty central node or a child window which was manually injected into a dockspace window.

* Backends: SDL+GLFW, Examples: SDL+Metal, GLFW+Metal: Fix viewport support with Metal backend.

Fixes ocornut#5392 + alignment fixes and removed static_cast<> + Amended with fix.

* Docking, Modal: Fixed a crash when opening popup from a parent which is being docked on the same frame. (ocornut#5401)

Ideally we should untangle the purpose of parent_window_in_stack / ParentWindowInBeginStack better.

* Docking: Amend 24dfebf. Fixed incorrect focus highlight on docking node with nested hierarchies.

* Backends: GLFW: Fixed leftover static variable preventing from changing or reinitializing backend while application is running. (ocornut#4616, ocornut#5434)

* Backends, Viewport: Metal: Pull format from shared context. (ocornut#5403, ocornut#5437)

* Docking, Nav: Fixed using gamepad/keyboard navigation not being able enter menu layer  (ocornut#5463, ocornut#4792)

Fix 37958ca

* Docking: Fix docked window contents not rendering when switching with CTRL+Tab.

(regression from 8eb8689).

* Internals: Docking: make DockContextFindNodeByID() more visible (instead of DockBuilderGetNode)

+ using defines for channel changes.

* Docking: Fixed splitting/docking into a node that has buttons amended into tab bar. Windows were not moved correctly. (ocornut#5515)

* Docking: Fixed amending into an existing tab bar from rendering invisible items. (ocornut#5515, amend b16f738 ocornut#2700, ocornut#2539)

Commit b16f738 left us with a "current" channel 0 which seems inadequate. Undoing that, assuming default is always 1, code filling bg color does a switch. Only DockContextEndFrame() leave it at 0 and it's not particularly necessary.

* Docking+Viewports: Fix undocking window node causing parent viewport to become unresponsive. (ocornut#5503)

Amend 67be485, Somehow ties to 58f5092 + 0eb45a0 (ocornut#4310)
Unsure of exact chain of event but this caused a parent link msimatch between the time of the MouseMoving test in AddUpdateViewport() setting _NoInputs on the wrong parent., and the release clearing _NoInputs on the rght one.

* Docking: Simplify logic of moving tabs between nodes. Amends 0abe7d. (ocornut#5515)

The idea is that in the absence of a tab bar, as new one gets created new tabs will be sorted based on window->DockOrder so this may work but we're not 100% sure.

* Docking: Add source dock node parameter DockContextCalcDropPosForDocking() to facilitate test engine (un)docking nodes before they are split out to their own window.
Metrics: Display dock_node->Windows in node metrics.

* Internals: Docking: rename HoveredDockNode to DebugHoveredDockNode to clarify that it isn't usable for much other than debugging.

* Nav: Fixed regression in e99c4fc preventing CTR+Tab to work without NavEnableKeyboard (ocornut#5504, ocornut#4023);

* Obsoleted using SetCursorPos()/SetCursorScreenPos() to extend parent window/cell boundaries. (ocornut#5548)

This incorrect pattern has been mentioned or suggested in: ocornut#4510, ocornut#3355, ocornut#1760, ocornut#1490, ocornut#4152, ocornut#150

# Conflicts:
#	imgui.cpp

* Backends: SDL: Fixed building backend under non-OSX Apple targets (e.g. iPhone). (ocornut#5665)

* Docking: Fixed incorrect focus highlight on docking node when focusing a menu. (ocornut#5702)

* Backends: OpenGL: Add ability to #define IMGUI_IMPL_OPENGL_DEBUG. (ocornut#4468, ocornut#4825, ocornut#4832, ocornut#5127, ocornut#5655, ocornut#5709)

# Conflicts:
#	backends/imgui_impl_opengl3.cpp

* Update imgui_impl_vulkan.h to match martty/imgui

https://github.com/martty/imgui/blob/master/examples/imgui_impl_vulkan.h

* Update imgui_impl_vulkan.cpp to match martty/imgui

https://github.com/martty/imgui/blob/master/examples/imgui_impl_vulkan.cpp

* Viewports: Fix AddMouseViewportEvent() to honor AppAcceptingEvents, filter duplicate, add to debug log.

* Docking: Fixed missing highlight when using dock node host window borders. (ocornut#5702)

Amend 8f43487, 9764adc, 24dfebf

* Fixed ImGuiWindowFlags_UnsavedDocument clipping label in docked windows with no close button. [changes for docking] (ocornut#5745)

+ TabBar: starts displaying the unsaved document marker with a frame delay to match how close button is processed, otherwise the transition would be noticeable.

* Fix for Vulkan validation layer warnings

Fix from: TheCherno@add065f
ocornut#3957

Co-authored-by: ocornut <omarcornut@gmail.com>
Co-authored-by: Sammy Fatnassi <sammyfreg@gmail.com>
Co-authored-by: GamingMinds-DanielC <daniel.cremers@gamingmindsstudios.com>
Co-authored-by: Adam Kewley <contact@adamkewley.com>
Co-authored-by: Rokas Kupstys <rokups@zoho.com>
Co-authored-by: David Maas <contact@pathogenstudios.com>
Co-authored-by: CheckmateAt7 <66566308+CheckmateAt7@users.noreply.github.com>
Co-authored-by: warriormaster12 <streng.alexander@gmail.com>
Co-authored-by: Michel Lesoinne <michel.lesoinne@androdevllc.com>
Co-authored-by: Mikko Sivulainen <mikko.sivulainen@gmail.com>
Co-authored-by: Mikko Sivulainen <mikko.sivulainen@supercell.com>
Co-authored-by: Dima Koltun <koltundimachamp@gmail.com>
Co-authored-by: stuartcarnie <stuart.carnie@gmail.com>
Co-authored-by: omar <ocornut@users.noreply.github.com>
Co-authored-by: Andrej Redeky <41929176+WSSDude420@users.noreply.github.com>
Co-authored-by: Runik <rtoumazet@free.fr>
Co-authored-by: Stephen H. Gerstacker <stephen@gerstacker.us>

This vulkan tutorial discusses swapchain recreation:

You could also decide to [recreate the swapchain] that if the swap chain is suboptimal, but I’ve chosen to proceed anyway in that case because we’ve already acquired an image.

My question is: how would one recreate the swapchain and not proceed in this case of VK_SUBOPTIMAL_KHR?

To see what I mean, let’s look at the tutorial’s render function:

void drawFrame() {
        vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);

        uint32_t imageIndex;
        VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);

        if (result == VK_ERROR_OUT_OF_DATE_KHR) { 
            recreateSwapChain();
            return;
        /* else if (result == VK_SUBOPTIMAL_KHR) { createSwapchain(); ??? } */
        } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
            throw std::runtime_error("failed to acquire swap chain image!");
        }

        if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
            vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
        }
        imagesInFlight[imageIndex] = inFlightFences[currentFrame];

        VkSubmitInfo submitInfo{};
        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

        VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]};
        VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
        submitInfo.waitSemaphoreCount = 1;
        submitInfo.pWaitSemaphores = waitSemaphores;
        submitInfo.pWaitDstStageMask = waitStages;

        submitInfo.commandBufferCount = 1;
        submitInfo.pCommandBuffers = &commandBuffers[imageIndex];

        VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]};
        submitInfo.signalSemaphoreCount = 1;
        submitInfo.pSignalSemaphores = signalSemaphores;

        vkResetFences(device, 1, &inFlightFences[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 = signalSemaphores;

        VkSwapchainKHR swapChains[] = {swapChain};
        presentInfo.swapchainCount = 1;
        presentInfo.pSwapchains = swapChains;

        presentInfo.pImageIndices = &imageIndex;

        result = vkQueuePresentKHR(presentQueue, &presentInfo);

        if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {
            framebufferResized = false;
            recreateSwapChain();
        } else if (result != VK_SUCCESS) {
            throw std::runtime_error("failed to present swap chain image!");
        }

        currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
    }

The trouble is as follows:

  1. vkAcquireImageKHR succeeds, signaling the semaphore and returning a valid, suboptimal image
  2. Recreate the swapchain
  3. We can’t present the image from 1 with the swapchain from 2 due to VUID-VkPresentInfoKHR-pImageIndices-01430. We need to call vkAcquireImageKHR again to get a new image.
  4. When we call vkAcquireImageKHR again, the semaphore is in the signaled state which is not allowed (VUID-vkAcquireNextImageKHR-semaphore-01286), we need to ‘unsignal’ it.

Is the best solution here to destroy and recreate the semaphore?

Ошибка обозначает отсутствие API Vulkan для этого приложения, но у меня установлены все драйвера и присутствует Вулкан, облазил весь интернет. Года 2 назад скачивал, всё работало.
— Удалял папку Base
— Устанавливал VulkanRT для Nvidia (многим вроде помогало)

Winsock Initialized
idCommonLocal::Init() time 20: 0.029s
—— Initializing File System ——
Current search path:
— C:/Users/47A8~1/SAVEDG~1/MachineGames/Wolfenstein II The New Colossus/base/
— C:/Games/Wolfenstein II The New Colossus/base/
—— File System initialized.
WARNING: ReadJsonFile: could not read file: packagechunklist.json
Executing build.cfg…
—— Command Line ——
«C:GamesWolfenstein II The New ColossusNewColossus_x64vk.exe»
—— CPU Information ——
1 CPU package, 6 physical cores, 12 logical cores
3394 MHz AMD CPU with MMX & SSE & SSE2 & SSE3 & SSSE3 & SSE41 & SSE42 & AVX & HTT
65536 kB 1st level cache, 524288 kB 2nd level cache, 8388608 kB 3rd level cache
16336 MB System Memory
idCommonLocal::Init() time 30: 0.032s
found dlc id 1 at ../dlc//dlc_1
found dlc id 2 at ../dlc//dlc_2
found dlc id 3 at ../dlc//dlc_3
SearchDLC: found 3 dlcs
idLib::SetProduction( PROD_PRODUCTION )
idCommonLocal::Init() time 40: 0.060s
——- Initializing renderSystem ———
PreliminaryRenderSetup
…registered window class
————————-
Application Info
————————-
App : Wolfenstein II The New Colossus — 1.0.3
Engine : idTech — 6.5.0
————————-
Instance Extensions
————————-
+ VK_KHR_surface
+ VK_KHR_win32_surface
+ VK_KHR_get_physical_device_properties2
————————-
Device Extensions
————————-
+ VK_AMD_shader_ballot
+ VK_AMD_shader_trinary_minmax
+ VK_AMD_gcn_shader
+ VK_EXT_shader_subgroup_ballot
+ VK_AMD_gpu_shader_half_float
+ VK_AMD_gpu_shader_int16
DeviceName: Radeon RX 5500 XT
DeviceType: VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
————————-
Using device: 0 — ‘Radeon RX 5500 XT’ because of device type VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
————————-
Device Extensions
————————-
+ VK_KHR_swapchain
+ VK_AMD_shader_ballot
+ VK_AMD_shader_trinary_minmax
+ VK_AMD_gcn_shader
+ VK_EXT_shader_subgroup_ballot
+ VK_AMD_gpu_shader_half_float
+ VK_AMD_gpu_shader_int16

————————-
Vulkan Device Info:
————————-
Vendor : AMD
GPU : Radeon RX 5500 XT
VRAM : 8176 MiB
Driver : 22.11.2 (008000e9)
VK API : 1.3.217

Initializing Vulkan subsystem
ShowGameWindow: (0, 0) 1280 x 720, full screen
RENDER THREAD STACK SIZE: 4194304
Applying: exec initial_video_low.cfg -s
TIMER: idPhysicalPages::EmptyCache 1 pages took 0.0650 ms
TIMER: idPhysicalPages::EmptyCache 1 pages took 0.0190 ms
TIMER: idPhysicalPages::EmptyCache 1 pages took 0.0190 ms
TIMER: idRenderSystemLocal::Init() took 926.4950 ms
Executing default.cfg for device #0…
Setting up single-player key bindings…
Finished executing default.cfg.
Executing default.cfg for device #1…
Setting up single-player key bindings…
Finished executing default.cfg.
Executing default.cfg for device #2…
Setting up single-player key bindings…
Finished executing default.cfg.
Executing default.cfg for device #3…
Setting up single-player key bindings…
Finished executing default.cfg.
TIMER: idCommonLocal::Init(), input dev init took 45.7250 ms
Unknown command ‘build_packageParent’
Unknown command ‘build_packageBranch’
TIMER: idSessionLocal::InitForge() took 2.2520 ms
idCommonLocal::Init() time 50: 1.039s
—— Build Information ——
Cheat Mode: OFF
Host Name: DESKTOP-VV6FT8E
Host Domain Name:
GFX AMD dv:22.11.2 api:1.3.217 ‘Radeon RX 5500 XT’ 8176MiB
Binary Build:
Version: 6.5.0
Target: shippingretail
Name: 20181106-173844-88267_yellow-turquoise
Requestor: user:autocompiler:forge
URL: http://www.forge.ad.machinegames.com/builds/binaries/20181106-173844-88267_yellow-turquoise
Relevant CLs: 030e17b91499e0756e3e58f8b7dffed56323dc1d
Binary Spec: win64-vulkan retail.
Package:
Name: 20181107-000045-88267_diamond-pliers
Map Set: Mercury game, Next deliverable, E3 2017 DEMO, Press tour, Retail Package Test, Mercury DLC0, Arkane_Opt
Requestor: user:pipeline:forge
URL: http://www.forge.ad.machinegames.com/builds/packages/20181107-000045-88267_diamond-pliers
Relevant CLs: 230433
idCommonLocal::Init() time 60: 1.039s
Set language to: russian
—— Initializing Decls ——
268 types, 0 declSource in 1 ms
——————————
idCommonLocal::Init() time 70: 1.041s
Reading strings/russian.lang as UTF-8
22280 strings read
Initializing class hierarchy

——- Input Initialization ——-
Initializing DirectInput…
mouse: DirectInput initialized.
keyboard: DirectInput initialized.
————————————
idCommonLocal::Init() time 80: 1.190s
NetGetVersionChecksum — checksum : 2786635601
DownloadPlatformTitleStorage: Loaded
0: X
8 channels, 48000 Hz
Default Console Device, Multimedia Device, and Game Device
1: Realtek Digital Output (Realtek(R) Audio)
8 channels, 48000 Hz
2: Realtek Digital Output (Realtek(R) Audio)
8 channels, 44100 Hz
Default Communications Device
Using audio device for voice 2
TIMER: idHavokPhysics::PreInit() took 29.3540 ms
—— Initializing Sound System ——
WARNING: [SOUND] idSoundWwiseIO::LoadSFXPackage: could not open sound pack file sound/soundbanks/pc/patch_4_russian.pack
TIMER: idSoundHardware_WWise::LoadBanks() took 24.5580 ms
[SOUND] 0.68 seconds to load all banks
sound system initialized.
—————————————
TIMER: idSoundSystemLocal::Init() took 777.0280 ms
———- ResetPersistHeap ———-
Global heap: Can’t HeapWalk() in this configuration
Map heap : GlobalMemoryStatus: 15.95GB dwTotalPhys
GlobalMemoryStatus: 9.24GB dwAvailPhys
GlobalMemoryStatus: 6.71GB used phys
GlobalMemoryStatus: 7.56GB used virtual
0.0 seconds to start load screen video
0.0 seconds to init the hdc
0.0 seconds to prep vts
0.0 seconds to figure out container
Resources skipped by layer tests: 0
0.0 seconds to allocate and defer load 1755 resources, 33 skipped
Load 1788 resources
idResourceStorageDiskStreamer::Init took 0.001s to collect 1744 (44 skipped) resources
Disk streamer stats:
Init took 0.001s to collect 1744 resources:
Forground: 1744 reads, 5.660 MiB (149.099 MiB/s)
Background: 6 reads, 5.871 MiB (141.463 MiB/s), 33 gaps ( 0.144 MiB), 0 file opens
0.1 seconds to preload resources
0 : preload model count
viewDescriptorSetHash: 72ee6a3c5b267a10
——- Initializing renderSystem parm states ———
Start time of bink video bink/boot/boot_pc.bk2 in ms: 2228
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
idFile_Bink::WaitForBufferToComplete stall
LOAD VIDEO
0.1 seconds to start load screen video
0.0 seconds to init the hdc
0.0 seconds to prep vts
0.0 seconds to figure out container
Resources skipped by layer tests: 0
0.0 seconds to allocate and defer load 10232 resources, 2314 skipped
Load 12546 resources
idResourceStorageDiskStreamer::Init took 0.007s to collect 10216 (2330 skipped) resources
Disk streamer stats:
Init took 0.007s to collect 10216 resources:
Forground: 10215 reads, 97.699 MiB (1799.257 MiB/s)
Background: 248 reads, 124.875 MiB (254.286 MiB/s), 3037 gaps (26.939 MiB), 0 file opens
2.4 seconds to preload resources
0 : preload model count
WARNING: No address, error: 126
WARNING: No address, error: 126
WARNING: No address, error: 126
WARNING: No address, error: 126
WARNING: No address, error: 126
WARNING: No address, error: 126
? @ 0x000282ad( ) + bytes () : ** UNKNOWN **( ** FUNC_PARAM_ERROR ** )
? @ 0xfffffffe( ) + bytes () : ** UNKNOWN **( ** FUNC_PARAM_ERROR ** )
? @ 0x6d7ef630( ) + bytes () : ** UNKNOWN **( ** FUNC_PARAM_ERROR ** )
? @ 0x01d43fe8( ) + bytes () : ** UNKNOWN **( ** FUNC_PARAM_ERROR ** )
? @ 0x01d43fe8( ) + bytes () : ** UNKNOWN **( ** FUNC_PARAM_ERROR ** )
? @ 0x00000000( ) + bytes () : ** UNKNOWN **( ** FUNC_PARAM_ERROR ** )
FATAL ERROR: CheckCodeResources: Resource error for renderProgResource:computeTAA = container entry defaulted — check that you have latest code and assets
TIMER: idResourceManagerLocal::Init2() took 2435.6321 ms
WARNING: vkAcquireNextImageKHR error (1000001003), recreating swap chain
WARNING: vkQueuePresentKHR error (1000001003), recreating swap chain
WARNING: vkAcquireNextImageKHR error (1000001003), recreating swap chain

Понравилась статья? Поделить с друзьями:
  • Warning unexpected error in verified check processing info later
  • Warning to error message sap
  • Warning to avoid system error please do not press and hold the power button хуавей
  • Warning to avoid system error please do not press and hold the power button перевод
  • Warning there was an error checking the latest version of pip