Fix validation error when resizing window

Sometimes when resizing the window we may get the following validation
error:

ERROR: VALIDATION - Message Id Number: -370888023 | Message Id Name:
VUID-vkAcquireNextImageKHR-semaphore-01286
	Validation Error: [ VUID-vkAcquireNextImageKHR-semaphore-01286 ]
Object 0: handle = 0xdcc8fd0000000012, type = VK_OBJECT_TYPE_SEMAPHORE;
| MessageID = 0xe9e4b2a9 | vkAcquireNextImageKHR: Semaphore must not be
currently signaled or in a wait state. The Vulkan spec states: If
semaphore is not VK_NULL_HANDLE it must be unsignaled
(https://vulkan.lunarg.com/doc/view/1.2.198.1/linux/1.2-extensions/vkspec.html#VUID-vkAcquireNextImageKHR-semaphore-01286)

In VulkanContext::prepare_buffers the problem was that
vkAcquireNextImageKHR returned VK_SUBOPTIMAL_KHR but it already signaled
the semaphore (because it is possible to continue normally with a
VK_SUBOPTIMAL_KHR result).

Then we recreate the swapchain and reuse the
w->image_acquired_semaphores[frame_index] which is in an inconsistent
state.

Fixed by recreating the semamphores along the swapchain.

Fix #80570
This commit is contained in:
Matias N. Goldberg 2023-08-12 20:32:28 -03:00
parent 4714e95896
commit 0b09fdd96c
1 changed files with 22 additions and 14 deletions

View File

@ -1700,17 +1700,6 @@ Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, Display
Error err = _update_swap_chain(&window);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
VkSemaphoreCreateInfo semaphoreCreateInfo = {
/*sType*/ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
/*pNext*/ nullptr,
/*flags*/ 0,
};
for (uint32_t i = 0; i < FRAME_LAG; i++) {
VkResult vkerr = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &window.image_acquired_semaphores[i]);
ERR_FAIL_COND_V(vkerr, ERR_CANT_CREATE);
}
windows[p_window_id] = window;
return OK;
}
@ -1760,9 +1749,6 @@ VkFramebuffer VulkanContext::window_get_framebuffer(DisplayServer::WindowID p_wi
void VulkanContext::window_destroy(DisplayServer::WindowID p_window_id) {
ERR_FAIL_COND(!windows.has(p_window_id));
_clean_up_swap_chain(&windows[p_window_id]);
for (uint32_t i = 0; i < FRAME_LAG; i++) {
vkDestroySemaphore(device, windows[p_window_id].image_acquired_semaphores[i], nullptr);
}
vkDestroySurfaceKHR(inst, windows[p_window_id].surface, nullptr);
windows.erase(p_window_id);
@ -1792,6 +1778,17 @@ Error VulkanContext::_clean_up_swap_chain(Window *window) {
if (separate_present_queue) {
vkDestroyCommandPool(device, window->present_cmd_pool, nullptr);
}
for (uint32_t i = 0; i < FRAME_LAG; i++) {
// Destroy the semaphores now (we'll re-create it later if we have to).
// We must do this because the semaphore cannot be reused if it's in a signaled state
// (which happens if vkAcquireNextImageKHR returned VK_ERROR_OUT_OF_DATE_KHR or VK_SUBOPTIMAL_KHR)
// The only way to reset it would be to present the swapchain... the one we just destroyed.
// And the API has no way to "unsignal" the semaphore.
vkDestroySemaphore(device, window->image_acquired_semaphores[i], nullptr);
window->image_acquired_semaphores[i] = 0;
}
return OK;
}
@ -2175,6 +2172,17 @@ Error VulkanContext::_update_swap_chain(Window *window) {
// Reset current buffer.
window->current_buffer = 0;
VkSemaphoreCreateInfo semaphoreCreateInfo = {
/*sType*/ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
/*pNext*/ nullptr,
/*flags*/ 0,
};
for (uint32_t i = 0; i < FRAME_LAG; i++) {
VkResult vkerr = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &window->image_acquired_semaphores[i]);
ERR_FAIL_COND_V(vkerr, ERR_CANT_CREATE);
}
return OK;
}