diff options
| -rw-r--r-- | CHANGELOG.md | 17 | ||||
| -rw-r--r-- | sokol_app.h | 20 |
2 files changed, 36 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index df88a5ce..412a748b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ ## Updates +### 01-Feb-2026 + +- sokol_gfx.h vulkan: the frame-sync-related validation layer errors on Windows + have been fixed (at least on the configs I can currently test: RTX5070 and Intel + Meteor Lake GPU). Unfortunately that doesn't guarantee that all other configs + are validation-error-clean. There are still a couple of issues on Windows to + deal with (especially a very high input-to-display lag compared to the + D3D11/DXGI backend, and moving/resizing the application window is stuttery on + NVIDIA (this is caused by the render-during-window-move/resize code waiting + for vsync). The next step will be to port the swapchain code to `VK_KHR_swpachain_maintenance1` + (which probably would have been a good idea right from the start). + + Also please keep in mind that the Vulkan backend is still deep in + 'highly experimental state'. + + PR: https://github.com/floooh/sokol/pull/1430 + ### 26-Jan-2026 - sokol_gfx.h: added support for dual-source-blending behind a new diff --git a/sokol_app.h b/sokol_app.h index db2e8dcb..eef6c736 100644 --- a/sokol_app.h +++ b/sokol_app.h @@ -4764,6 +4764,20 @@ _SOKOL_PRIVATE void _sapp_vk_swapchain_create_surface( _sapp_vk_set_object_label(VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)surf->view, view_debug_label); } +_SOKOL_PRIVATE uint32_t _sapp_vk_swapchain_min_image_count(const VkSurfaceCapabilitiesKHR* surf_caps) { + // FIXME: figure out why at least 3 swapchain images are required to appease the validation layer + // (on the Linux Intel driver, present-mode-fifo has a surf_caps.minImageCount == 3, while + // on Windows surf_caps.minImageCount == 2, and using this directly causes validation layer + // errors about the present-complete semaphore (to reproduce simply change the '= 3' below to '= 2') + SOKOL_ASSERT(surf_caps); + const uint32_t required_image_count = 3; + uint32_t min_image_count = surf_caps->minImageCount; + if (min_image_count < required_image_count) { + min_image_count = required_image_count; + } + return min_image_count; +} + _SOKOL_PRIVATE void _sapp_vk_create_swapchain(bool recreate) { SOKOL_ASSERT(_sapp.vk.physical_device); SOKOL_ASSERT(_sapp.vk.surface); @@ -4797,7 +4811,7 @@ _SOKOL_PRIVATE void _sapp_vk_create_swapchain(bool recreate) { create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; create_info.flags = 0; // FIXME? create_info.surface = _sapp.vk.surface; - create_info.minImageCount = surf_caps.minImageCount; + create_info.minImageCount = _sapp_vk_swapchain_min_image_count(&surf_caps); create_info.imageFormat = _sapp.vk.surface_format.format; create_info.imageColorSpace = _sapp.vk.surface_format.colorSpace; create_info.imageExtent.width = width; @@ -4965,6 +4979,8 @@ _SOKOL_PRIVATE void _sapp_vk_present(void) { _SAPP_STRUCT(VkPresentInfoKHR, present_info); present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present_info.waitSemaphoreCount = 1; + // NOTE: using the current swapchain image index here instead of `sync_slot` is *NOT* a bug! The render_finished_semaphore *must* + // be associated with the current swapchain image in case the swapchain implementation doesn't return swapchain images in order present_info.pWaitSemaphores = &_sapp.vk.sync[_sapp.vk.cur_swapchain_image_index].render_finished_sem; present_info.swapchainCount = 1; present_info.pSwapchains = &_sapp.vk.swapchain; @@ -14005,6 +14021,8 @@ SOKOL_API_IMPL sapp_swapchain sapp_get_swapchain(void) { } res.vulkan.depth_stencil_image = (const void*) _sapp.vk.depth.img; res.vulkan.depth_stencil_view = (const void*) _sapp.vk.depth.view; + // NOTE: using the current swapchain image index here is *NOT* a bug! The render_finished_semaphore *must* + // be associated with its swapchain image in case the swapchain implementation doesn't return swapchain images in order res.vulkan.render_finished_semaphore = _sapp.vk.sync[img_idx].render_finished_sem; res.vulkan.present_complete_semaphore = _sapp.vk.sync[_sapp.vk.sync_slot].present_complete_sem; #endif |