@@ -60,6 +60,8 @@ static XContext vulkan_swapchain_context;
60
60
61
61
static struct list surface_list = LIST_INIT ( surface_list );
62
62
63
+ #define NO_IMAGE_INDEX UINT32_MAX
64
+
63
65
struct wine_vk_surface
64
66
{
65
67
LONG ref ;
@@ -73,6 +75,8 @@ struct wine_vk_surface
73
75
HDC hdc ;
74
76
HWND hwnd ;
75
77
DWORD hwnd_thread_id ;
78
+ VkDevice device ;
79
+ uint32_t next_image_index ;
76
80
};
77
81
78
82
typedef struct VkXlibSurfaceCreateInfoKHR
@@ -108,6 +112,8 @@ static VkResult (*pvkQueuePresentKHR)(VkQueue, const VkPresentInfoKHR *);
108
112
static VkResult (* pvkWaitForFences )(VkDevice device , uint32_t fenceCount , const VkFence * pFences , VkBool32 waitAll , uint64_t timeout );
109
113
static VkResult (* pvkCreateFence )(VkDevice device , const VkFenceCreateInfo * pCreateInfo , const VkAllocationCallbacks * pAllocator , VkFence * pFence );
110
114
static void (* pvkDestroyFence )(VkDevice device , VkFence fence , const VkAllocationCallbacks * pAllocator );
115
+ static void (* pvkGetDeviceQueue )(VkDevice device , uint32_t queueFamilyIndex , uint32_t queueIndex , VkQueue * pQueue );
116
+ static VkResult (* pvkQueueSubmit )(VkQueue queue , uint32_t submitCount , const VkSubmitInfo * pSubmits , VkFence fence );
111
117
112
118
static void * X11DRV_get_vk_device_proc_addr (const char * name );
113
119
static void * X11DRV_get_vk_instance_proc_addr (VkInstance instance , const char * name );
@@ -153,6 +159,8 @@ static BOOL WINAPI wine_vk_init(INIT_ONCE *once, void *param, void **context)
153
159
LOAD_FUNCPTR (vkWaitForFences );
154
160
LOAD_FUNCPTR (vkCreateFence );
155
161
LOAD_FUNCPTR (vkDestroyFence );
162
+ LOAD_FUNCPTR (vkGetDeviceQueue );
163
+ LOAD_FUNCPTR (vkQueueSubmit );
156
164
#undef LOAD_FUNCPTR
157
165
#undef LOAD_OPTIONAL_FUNCPTR
158
166
@@ -405,15 +413,12 @@ static VkResult X11DRV_vkAcquireNextImageKHR(VkDevice device,
405
413
{
406
414
struct wine_vk_surface * surface = NULL ;
407
415
VkResult result ;
408
- VkFence orig_fence ;
409
416
BOOL wait_fence = FALSE;
410
- HDC hdc = 0 ;
411
417
412
418
EnterCriticalSection (& context_section );
413
419
if (!XFindContext (gdi_display , (XID )swapchain , vulkan_swapchain_context , (char * * )& surface ))
414
420
{
415
421
wine_vk_surface_grab (surface );
416
- hdc = surface -> hdc ;
417
422
}
418
423
LeaveCriticalSection (& context_section );
419
424
@@ -423,25 +428,44 @@ static VkResult X11DRV_vkAcquireNextImageKHR(VkDevice device,
423
428
surface -> present_mode == VK_PRESENT_MODE_FIFO_KHR )
424
429
wait_fence = TRUE;
425
430
426
- orig_fence = fence ;
427
- if (wait_fence && !fence )
431
+ if (wait_fence && surface -> next_image_index != NO_IMAGE_INDEX )
428
432
{
429
- VkFenceCreateInfo create_info ;
430
- create_info .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO ;
431
- create_info .pNext = NULL ;
432
- create_info .flags = 0 ;
433
- pvkCreateFence (device , & create_info , NULL , & fence );
434
- }
433
+ //the app expets the fence and the semaphore to be signaled
434
+ VkSubmitInfo submit_info ;
435
+ submit_info .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO ;
436
+ submit_info .pNext = NULL ;
437
+ submit_info .waitSemaphoreCount = 0 ;
438
+ submit_info .pWaitSemaphores = NULL ;
439
+ submit_info .pWaitDstStageMask = NULL ;
440
+ submit_info .commandBufferCount = 0 ;
441
+ submit_info .pCommandBuffers = NULL ;
442
+ submit_info .signalSemaphoreCount = semaphore != VK_NULL_HANDLE ;
443
+ submit_info .pSignalSemaphores = & semaphore ;
444
+
445
+ VkQueue queue = NULL ;
446
+ pvkGetDeviceQueue (device , 0 , 0 , & queue );
447
+ if (!queue )
448
+ {
449
+ return VK_NOT_READY ; //random error
450
+ }
451
+
452
+ VkResult submit_result = pvkQueueSubmit (queue , 1 , & submit_info , fence );
453
+ if (submit_result != VK_SUCCESS )
454
+ {
455
+ return submit_result ;
456
+ }
457
+
458
+ * image_index = surface -> next_image_index ;
435
459
436
- result = pvkAcquireNextImageKHR (device , swapchain , timeout , semaphore , fence , image_index );
437
- if ((result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR ) && hdc && surface && surface -> offscreen )
460
+
461
+ if (surface ) wine_vk_surface_release (surface );
462
+
463
+ return VK_SUCCESS ;
464
+ }
465
+ else
438
466
{
439
- if ( wait_fence ) pvkWaitForFences ( device , 1 , & fence , 0 , timeout );
467
+ return pvkAcquireNextImageKHR ( device , swapchain , timeout , semaphore , fence , image_index );
440
468
}
441
-
442
- if (fence != orig_fence ) pvkDestroyFence (device , fence , NULL );
443
- if (surface ) wine_vk_surface_release (surface );
444
- return result ;
445
469
}
446
470
447
471
static VkResult X11DRV_vkAcquireNextImage2KHR (VkDevice device ,
@@ -466,6 +490,9 @@ static VkResult X11DRV_vkCreateSwapchainKHR(VkDevice device,
466
490
VkSwapchainCreateInfoKHR create_info_host ;
467
491
VkResult result ;
468
492
493
+ x11_surface -> next_image_index = NO_IMAGE_INDEX ;
494
+ x11_surface -> device = device ;
495
+
469
496
TRACE ("%p %p %p %p\n" , device , create_info , allocator , swapchain );
470
497
471
498
if (allocator )
@@ -865,7 +892,7 @@ static VkResult X11DRV_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *
865
892
static int once ;
866
893
struct x11drv_escape_present_drawable escape ;
867
894
struct wine_vk_surface * surface = NULL ;
868
- VkFence orig_fence ;
895
+ VkFence acquire_fence ;
869
896
BOOL wait_fence = FALSE;
870
897
HDC hdc = 0 ;
871
898
@@ -908,12 +935,28 @@ static VkResult X11DRV_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *
908
935
}
909
936
LeaveCriticalSection (& context_section );
910
937
938
+ BOOL needs_sync = surface -> present_mode == VK_PRESENT_MODE_MAILBOX_KHR ||
939
+ surface -> present_mode == VK_PRESENT_MODE_FIFO_KHR ;
940
+
941
+ //if needed wait fence to avoid tearing
942
+ if (hdc && surface && surface -> offscreen && needs_sync )
943
+ {
944
+ VkFenceCreateInfo create_info ;
945
+ create_info .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO ;
946
+ create_info .pNext = NULL ;
947
+ create_info .flags = 0 ;
948
+ pvkCreateFence (surface -> device , & create_info , NULL , & acquire_fence );
949
+
950
+ pvkAcquireNextImageKHR (surface -> device , swapchain , UINT64_MAX , VK_NULL_HANDLE , acquire_fence , & surface -> next_image_index );
951
+
952
+ pvkWaitForFences (surface -> device , 1 , & acquire_fence , 0 , UINT64_MAX );
953
+ }
954
+
911
955
if (hdc && surface && surface -> offscreen )
912
956
{
913
957
escape .code = X11DRV_PRESENT_DRAWABLE ;
914
958
escape .drawable = surface -> window ;
915
959
escape .flush = TRUE;
916
-
917
960
ExtEscape (hdc , X11DRV_ESCAPE , sizeof (escape ), (char * )& escape , 0 , NULL );
918
961
if (surface -> present_mode == VK_PRESENT_MODE_MAILBOX_KHR )
919
962
if (once ++ ) FIXME ("Application requires child window rendering with mailbox present mode, expect possible tearing!\n" );
0 commit comments