diff --git a/attachments/17_swap_chain_recreation.cpp b/attachments/17_swap_chain_recreation.cpp index a1ada280..20657e80 100644 --- a/attachments/17_swap_chain_recreation.cpp +++ b/attachments/17_swap_chain_recreation.cpp @@ -513,17 +513,24 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } - if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. + else if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -537,35 +544,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/18_vertex_input.cpp b/attachments/18_vertex_input.cpp index 10061e61..ded31e38 100644 --- a/attachments/18_vertex_input.cpp +++ b/attachments/18_vertex_input.cpp @@ -532,17 +532,24 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -556,37 +563,25 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } - frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; + frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } [[nodiscard]] vk::raii::ShaderModule createShaderModule(const std::vector &code) const diff --git a/attachments/19_vertex_buffer.cpp b/attachments/19_vertex_buffer.cpp index 07fc80d2..e726f047 100644 --- a/attachments/19_vertex_buffer.cpp +++ b/attachments/19_vertex_buffer.cpp @@ -568,17 +568,24 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -592,35 +599,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/20_staging_buffer.cpp b/attachments/20_staging_buffer.cpp index 28f1f40b..a641a2c0 100644 --- a/attachments/20_staging_buffer.cpp +++ b/attachments/20_staging_buffer.cpp @@ -588,17 +588,24 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -612,35 +619,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/21_index_buffer.cpp b/attachments/21_index_buffer.cpp index e427a625..2cb13ee1 100644 --- a/attachments/21_index_buffer.cpp +++ b/attachments/21_index_buffer.cpp @@ -614,17 +614,24 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -638,35 +645,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/22_descriptor_layout.cpp b/attachments/22_descriptor_layout.cpp index bb379979..30a02dc1 100644 --- a/attachments/22_descriptor_layout.cpp +++ b/attachments/22_descriptor_layout.cpp @@ -673,18 +673,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -698,35 +705,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/23_descriptor_sets.cpp b/attachments/23_descriptor_sets.cpp index 269a76a9..2b4062ec 100644 --- a/attachments/23_descriptor_sets.cpp +++ b/attachments/23_descriptor_sets.cpp @@ -701,18 +701,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -726,35 +733,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/24_texture_image.cpp b/attachments/24_texture_image.cpp index 5a622955..61b26f98 100644 --- a/attachments/24_texture_image.cpp +++ b/attachments/24_texture_image.cpp @@ -810,18 +810,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -835,35 +842,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/25_sampler.cpp b/attachments/25_sampler.cpp index 9bff8a0b..5285bfaa 100644 --- a/attachments/25_sampler.cpp +++ b/attachments/25_sampler.cpp @@ -846,18 +846,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -871,35 +878,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/26_texture_mapping.cpp b/attachments/26_texture_mapping.cpp index b5d67f96..7c7e1fcf 100644 --- a/attachments/26_texture_mapping.cpp +++ b/attachments/26_texture_mapping.cpp @@ -911,18 +911,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -936,35 +943,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/27_depth_buffering.cpp b/attachments/27_depth_buffering.cpp index 6fd30340..e9b23894 100644 --- a/attachments/27_depth_buffering.cpp +++ b/attachments/27_depth_buffering.cpp @@ -1012,18 +1012,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -1037,35 +1044,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/28_model_loading.cpp b/attachments/28_model_loading.cpp index adc3e40d..d6e4712f 100644 --- a/attachments/28_model_loading.cpp +++ b/attachments/28_model_loading.cpp @@ -1068,18 +1068,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -1093,35 +1100,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/29_mipmapping.cpp b/attachments/29_mipmapping.cpp index 77347ebb..6760e216 100644 --- a/attachments/29_mipmapping.cpp +++ b/attachments/29_mipmapping.cpp @@ -1138,18 +1138,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -1163,35 +1170,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/30_multisampling.cpp b/attachments/30_multisampling.cpp index 3c0b58b1..517317ba 100644 --- a/attachments/30_multisampling.cpp +++ b/attachments/30_multisampling.cpp @@ -1201,18 +1201,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -1226,35 +1233,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/31_compute_shader.cpp b/attachments/31_compute_shader.cpp index 6b38a90a..75f08643 100644 --- a/attachments/31_compute_shader.cpp +++ b/attachments/31_compute_shader.cpp @@ -413,7 +413,7 @@ class ComputeShaderApplication .format = swapChainSurfaceFormat.format, .components = {vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity}, .subresourceRange = {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}}; - for (auto& image : swapChainImages) + for (auto &image : swapChainImages) { imageViewCreateInfo.image = image; swapChainImageViews.emplace_back(device, imageViewCreateInfo); @@ -811,7 +811,7 @@ class ComputeShaderApplication void drawFrame() { auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, nullptr, *inFlightFences[frameIndex]); - auto fenceResult = device.waitForFences(*inFlightFences[frameIndex], vk::True, UINT64_MAX); + auto fenceResult = device.waitForFences(*inFlightFences[frameIndex], vk::True, UINT64_MAX); if (fenceResult != vk::Result::eSuccess) { throw std::runtime_error("failed to wait for fence!"); @@ -884,7 +884,7 @@ class ComputeShaderApplication if (result != vk::Result::eSuccess) { throw std::runtime_error("failed to wait for semaphore!"); - } + } vk::PresentInfoKHR presentInfo{ .waitSemaphoreCount = 0, // No binary semaphores needed @@ -893,30 +893,18 @@ class ComputeShaderApplication .pSwapchains = &*swapChain, .pImageIndices = &imageIndex}; - try + result = queue.presentKHR(presentInfo); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - result = queue.presentKHR(presentInfo); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; diff --git a/attachments/32_ecosystem_utilities.cpp b/attachments/32_ecosystem_utilities.cpp index 8fef1204..596f424e 100644 --- a/attachments/32_ecosystem_utilities.cpp +++ b/attachments/32_ecosystem_utilities.cpp @@ -1592,18 +1592,25 @@ class HelloTriangleApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -1656,35 +1663,23 @@ class HelloTriangleApplication queue.submit(submitInfo, *inFlightFences[frameIndex]); } - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/33_vulkan_profiles.cpp b/attachments/33_vulkan_profiles.cpp index a0627897..edb5e9f1 100644 --- a/attachments/33_vulkan_profiles.cpp +++ b/attachments/33_vulkan_profiles.cpp @@ -1554,27 +1554,33 @@ class HelloTriangleApplication void drawFrame() { - vk::Result result = device.waitForFences({*inFlightFences[frameIndex]}, VK_TRUE, UINT64_MAX); - if (result != vk::Result::eSuccess) + vk::Result fenceResult = device.waitForFences({*inFlightFences[frameIndex]}, VK_TRUE, UINT64_MAX); + if (fenceResult != vk::Result::eSuccess) { throw std::runtime_error("failed to wait for fence!"); } - uint32_t imageIndex; - try - { - auto [result, idx] = swapChain.acquireNextImage(UINT64_MAX, *imageAvailableSemaphores[frameIndex]); - imageIndex = idx; - } - catch (vk::OutOfDateKHRError &) + auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *imageAvailableSemaphores[frameIndex], nullptr); + + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. + if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) + { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); + throw std::runtime_error("failed to acquire swap chain image!"); + } updateUniformBuffer(frameIndex); - device.resetFences({*inFlightFences[frameIndex]}); + // Only reset the fence if we are submitting work + device.resetFences(*inFlightFences[frameIndex]); commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -1590,36 +1596,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*presentCompleteSemaphore[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*presentCompleteSemaphore[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{ - .waitSemaphoreCount = 1, - .pWaitSemaphores = &*presentCompleteSemaphore[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - auto result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/34_android.cpp b/attachments/34_android.cpp index ce26e3ca..af41e8f9 100644 --- a/attachments/34_android.cpp +++ b/attachments/34_android.cpp @@ -1317,22 +1317,28 @@ class HelloTriangleApplication { static_cast(device.waitForFences({*inFlightFences[frameIndex]}, VK_TRUE, UINT64_MAX)); - uint32_t imageIndex; - try - { - auto [result, idx] = swapChain.acquireNextImage(UINT64_MAX, *imageAvailableSemaphores[frameIndex]); - imageIndex = idx; - } - catch (vk::OutOfDateKHRError &) + auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *imageAvailableSemaphores[frameIndex], nullptr); + + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. + if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) + { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); + throw std::runtime_error("failed to acquire swap chain image!"); + } // Update uniform buffer with current transformation updateUniformBuffer(frameIndex); - device.resetFences({*inFlightFences[frameIndex]}); + // Only reset the fence if we are submitting work + device.resetFences(*inFlightFences[frameIndex]); commandBuffers[frameIndex].reset(); recordCommandBuffer(commandBuffers[frameIndex], imageIndex); @@ -1348,38 +1354,23 @@ class HelloTriangleApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{ - .waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - - vk::Result result = queue.presentKHR(presentInfoKHR); - - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("Failed to present swap chain image"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; diff --git a/attachments/35_gltf_ktx.cpp b/attachments/35_gltf_ktx.cpp index 89b99135..1e2f0528 100644 --- a/attachments/35_gltf_ktx.cpp +++ b/attachments/35_gltf_ktx.cpp @@ -1401,18 +1401,25 @@ class VulkanApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -1426,35 +1433,23 @@ class VulkanApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/36_multiple_objects.cpp b/attachments/36_multiple_objects.cpp index 3949071b..2ee3aed7 100644 --- a/attachments/36_multiple_objects.cpp +++ b/attachments/36_multiple_objects.cpp @@ -1534,20 +1534,27 @@ class VulkanApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } // Update uniform buffers for all objects updateUniformBuffers(); + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -1561,35 +1568,23 @@ class VulkanApplication .pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]}; queue.submit(submitInfo, *inFlightFences[frameIndex]); - try + const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; + result = queue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, - .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], - .swapchainCount = 1, - .pSwapchains = &*swapChain, - .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } - catch (const vk::SystemError &e) + else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/37_multithreading.cpp b/attachments/37_multithreading.cpp index 90c60ff5..3ea2d09c 100644 --- a/attachments/37_multithreading.cpp +++ b/attachments/37_multithreading.cpp @@ -1201,13 +1201,19 @@ class MultithreadedApplication // Acquire the next image auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *imageAvailableSemaphores[frameIndex], nullptr); + + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. else if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } @@ -1326,15 +1332,17 @@ class MultithreadedApplication .pImageIndices = &imageIndex}; result = queue.presentKHR(presentInfo); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { framebufferResized = false; recreateSwapChain(); - return; } - else if (result != vk::Result::eSuccess) + else { - throw std::runtime_error("failed to present swap chain image!"); + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } // Move to the next frame diff --git a/attachments/38_ray_tracing.cpp b/attachments/38_ray_tracing.cpp index d091c4cb..c87af500 100644 --- a/attachments/38_ray_tracing.cpp +++ b/attachments/38_ray_tracing.cpp @@ -1831,13 +1831,18 @@ class VulkanRaytracingApplication auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. if (result == vk::Result::eErrorOutOfDateKHR) { recreateSwapChain(); return; } + // On other success codes than eSuccess and eSuboptimalKHR we just throw an exception. + // On any error code, aquireNextImage already threw an exception. if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } updateUniformBuffer(frameIndex); @@ -1846,7 +1851,9 @@ class VulkanRaytracingApplication updateTopLevelAS(ubo.model); #endif // LAB_TASK_LEVEL >= LAB_TASK_AS_ANIMATION + // Only reset the fence if we are submitting work device.resetFences(*inFlightFences[frameIndex]); + commandBuffers[frameIndex].reset(); recordCommandBuffer(imageIndex); @@ -1866,14 +1873,17 @@ class VulkanRaytracingApplication .pSwapchains = &*swapChain, .pImageIndices = &imageIndex}; result = presentQueue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { framebufferResized = false; recreateSwapChain(); } - else if (result != vk::Result::eSuccess) + else { - throw std::runtime_error("failed to present swap chain image!"); + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; } diff --git a/attachments/CMakeLists.txt b/attachments/CMakeLists.txt index 113fe20b..1261ca30 100644 --- a/attachments/CMakeLists.txt +++ b/attachments/CMakeLists.txt @@ -14,7 +14,7 @@ endif() find_package (glfw3 REQUIRED) find_package (glm REQUIRED) -find_package (Vulkan REQUIRED) +find_package (Vulkan 1.4.335 REQUIRED) # Require Vulkan SDK version 1.4.335 or higher find_package (tinyobjloader REQUIRED) find_package (tinygltf REQUIRED) find_package (KTX REQUIRED) @@ -139,6 +139,9 @@ function (add_chapter CHAPTER_NAME) target_compile_definitions(${CHAPTER_NAME} PRIVATE USE_CPP20_MODULES=1) endif() + # Define VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS to treat VK_ERROR_OUT_OF_DATE_KHR as a success code + target_compile_definitions(${CHAPTER_NAME} PRIVATE "VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS" ) + if(WIN32) if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*") set_target_properties(${CHAPTER_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/${CHAPTER_NAME}") diff --git a/en/03_Drawing_a_triangle/04_Swap_chain_recreation.adoc b/en/03_Drawing_a_triangle/04_Swap_chain_recreation.adoc index f0a90011..d7d12559 100644 --- a/en/03_Drawing_a_triangle/04_Swap_chain_recreation.adoc +++ b/en/03_Drawing_a_triangle/04_Swap_chain_recreation.adoc @@ -79,22 +79,26 @@ You need to pass the previous swap chain to the `oldSwapchain` field in the `VkS 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. +The `vk::raii::SwapchainKHR::acquireNextImage` and `vk::raii::Queue::presentKHR` 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. +* `vk::Result::eErrorOutOfDateKHR`: 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. +Note that “vk::Result::eErrorOutOfDateKHR” is actually an error code and would trigger an exception by default. By defining “VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS,” this is treated as a success code and can therefore be returned by “vk::raii::SwapchainKHR::acquireNextImage” and “vk::raii::Queue::presentKHR.” +* `vk::Result::eSuboptimalKHR`: The swap chain can still be used to successfully present to the surface, but the surface properties are no longer matched exactly. [,c++] ---- -auto [result, imageIndex] = swapChain.acquireNextImage( UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr ); +auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); -if (result == vk::Result::eErrorOutOfDateKHR) { - recreateSwapChain(); - return; +if (result == vk::Result::eErrorOutOfDateKHR) +{ + recreateSwapChain(); + return; } -if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) { - throw std::runtime_error("failed to acquire swap chain image!"); +if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) +{ + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); + throw std::runtime_error("failed to acquire swap chain image!"); } ---- @@ -102,90 +106,89 @@ If the swap chain turns out to be out of date when attempting to acquire an imag 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. +Both `vk::Result::eSuccess` and `vk::Result::eSuboptimalKHR` are considered "success" return codes. [,c++] ---- -result = presentQueue.presentKHR( presentInfoKHR ); -if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR) { - recreateSwapChain(); -} else if (result != vk::Result::eSuccess) { - throw std::runtime_error("failed to present swap chain image!"); +result = queue.presentKHR(presentInfoKHR); +if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR)) +{ + recreateSwapChain(); +} +else +{ + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; ---- -The `vkQueuePresentKHR` function returns the same values with the same meaning. +The `vk::raii::Queue::presentKHR` 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. [,c++] ---- -try +const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, + .pWaitSemaphores = &*renderFinishedSemaphores[imageIndex], + .swapchainCount = 1, + .pSwapchains = &*swapChain, + .pImageIndices = &imageIndex}; +result = queue.presentKHR(presentInfoKHR); +if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) { - const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, .pWaitSemaphores = &*renderFinishedSemaphore[imageIndex], .swapchainCount = 1, .pSwapchains = &*swapChain, .pImageIndices = &imageIndex}; - result = queue.presentKHR(presentInfoKHR); - if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) - { - framebufferResized = false; - recreateSwapChain(); - } - else if (result != vk::Result::eSuccess) - { - throw std::runtime_error("failed to present swap chain image!"); - } + framebufferResized = false; + recreateSwapChain(); } -catch (const vk::SystemError &e) +else { - if (e.code().value() == static_cast(vk::Result::eErrorOutOfDateKHR)) - { - recreateSwapChain(); - return; - } - else - { - throw; - } + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); } ---- -Recent versions of Vulkan-hpp throw exceptions on unsuccessful return codes. To handle exceptions thrown by `vkQueuePresentKHR`, catch `vk::SystemError` and check the error code as shown above. - == 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`. +Debugging the code, we find that the application reaches `vk::raii::Device::waitForFences` but never continues past it. +This is because when `vk::raii::SwapchainKHR::acquireNextImage` returns `vk::Result::eErrorOutOfDateKHR`, 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. +Since we return immediately, no work is submitted for execution and the fence will never be signaled, causing `vk::raii::Device::waitForFences` 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. +Thus, if we return early, the fence is still signaled and `vk::raii::Device::waitForFences` wont deadlock the next time we use the same fence object. The beginning of `drawFrame` should now look like this: [,c++] ---- -vkWaitForFences(device, 1, &inFlightFences[frameIndex], VK_TRUE, UINT64_MAX); +auto fenceResult = device.waitForFences(*inFlightFences[frameIndex], vk::True, UINT64_MAX); +if (fenceResult != vk::Result::eSuccess) +{ + throw std::runtime_error("failed to wait for fence!"); +} -uint32_t imageIndex; -VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[frameIndex], VK_NULL_HANDLE, &imageIndex); +auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); -if (result == VK_ERROR_OUT_OF_DATE_KHR) { +if (result == vk::Result::eErrorOutOfDateKHR) +{ recreateSwapChain(); return; -} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { +} +else if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) +{ + assert(result == vk::Result::eTimeout || result == vk::Result::eNotReady); throw std::runtime_error("failed to acquire swap chain image!"); } // Only reset the fence if we are submitting work -vkResetFences(device, 1, &inFlightFences[frameIndex]); +device.resetFences(*inFlightFences[frameIndex]); ---- == 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. +Although many drivers and platforms trigger `vk::Result::eErrorOutOfDateKHR` 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: @@ -203,12 +206,14 @@ The `drawFrame` function should then be modified to also check for this flag: if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) { framebufferResized = false; recreateSwapChain(); -} else if (result != vk::Result::eSuccess) { +} +else +{ ... } ---- -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. +It is important to do this after `vk::raii::Queue::presentKHR` 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: [,c++]