&vk_physical_device_from_handle(pdevice)->supported_extensions;
wsi->has_import_memory_host =
supported_extensions->EXT_external_memory_host;
+ wsi->khr_present_wait =
+ supported_extensions->KHR_present_id &&
+ supported_extensions->KHR_present_wait;
+
+ /* We cannot expose KHR_present_wait without timeline semaphores. */
+ assert(!wsi->khr_present_wait || supported_extensions->KHR_timeline_semaphore);
list_inithead(&wsi->hotplug_fences);
WSI_GET_CB(WaitForFences);
WSI_GET_CB(MapMemory);
WSI_GET_CB(UnmapMemory);
+ if (wsi->khr_present_wait)
+ WSI_GET_CB(WaitSemaphoresKHR);
#undef WSI_GET_CB
#ifdef VK_USE_PLATFORM_XCB_KHR
}
chain->wsi->DestroySemaphore(chain->device, chain->dma_buf_semaphore,
&chain->alloc);
+ chain->wsi->DestroySemaphore(chain->device, chain->present_id_timeline,
+ &chain->alloc);
int cmd_pools_count = chain->buffer_blit_queue != VK_NULL_HANDLE ?
1 : chain->wsi->queue_family_count;
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
+ if (wsi_device->khr_present_wait) {
+ const VkSemaphoreTypeCreateInfo type_info = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
+ .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
+ };
+
+ const VkSemaphoreCreateInfo sem_info = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ .pNext = &type_info,
+ .flags = 0,
+ };
+
+ /* We assume here that a driver exposing present_wait also exposes VK_KHR_timeline_semaphore. */
+ result = wsi_device->CreateSemaphore(_device, &sem_info, alloc, &swapchain->present_id_timeline);
+ if (result != VK_SUCCESS) {
+ swapchain->destroy(swapchain, alloc);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ }
+
if (swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
swapchain->buffer_blit_semaphores = vk_zalloc(alloc,
sizeof (*swapchain->buffer_blit_semaphores) * swapchain->image_count,
sizeof (*swapchain->buffer_blit_semaphores),
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!swapchain->buffer_blit_semaphores) {
+ wsi_device->DestroySemaphore(_device, swapchain->present_id_timeline, alloc);
swapchain->destroy(swapchain, alloc);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
_device, pAcquireInfo, pImageIndex);
}
+static VkResult wsi_signal_present_id_timeline(struct wsi_swapchain *swapchain,
+ VkQueue queue, uint64_t present_id)
+{
+ assert(swapchain->present_id_timeline);
+
+ const VkTimelineSemaphoreSubmitInfo timeline_info = {
+ .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
+ .pSignalSemaphoreValues = &present_id,
+ .signalSemaphoreValueCount = 1,
+ };
+
+ const VkSubmitInfo submit_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .pNext = &timeline_info,
+ .signalSemaphoreCount = 1,
+ .pSignalSemaphores = &swapchain->present_id_timeline,
+ };
+
+ return swapchain->wsi->QueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
+}
+
VkResult
wsi_common_queue_present(const struct wsi_device *wsi,
VkDevice device,
if (present_ids && present_ids->pPresentIds)
present_id = present_ids->pPresentIds[i];
+ if (present_id) {
+ result = wsi_signal_present_id_timeline(swapchain, queue, present_id);
+ if (result != VK_SUCCESS)
+ goto fail_present;
+ }
+
result = swapchain->queue_present(swapchain, image_index, present_id, region);
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
goto fail_present;
return wsi->BindImageMemory(chain->device, vk_image, image->memory, 0);
}
+VkResult
+wsi_swapchain_wait_for_present_semaphore(const struct wsi_swapchain *chain,
+ uint64_t present_id, uint64_t timeout)
+{
+ assert(chain->present_id_timeline);
+ const VkSemaphoreWaitInfo wait_info = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+ .semaphoreCount = 1,
+ .pSemaphores = &chain->present_id_timeline,
+ .pValues = &present_id,
+ };
+
+ return chain->wsi->WaitSemaphoresKHR(chain->device, &wait_info, timeout);
+}
+
uint32_t
wsi_select_memory_type(const struct wsi_device *wsi,
VkMemoryPropertyFlags req_props,