aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md17
-rw-r--r--sokol_app.h20
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