This extension provides fences and frame count information to direct display contexts. It uses new kernel ioctls to provide 64-bits of vblank sequence and nanosecond resolution. Signed-off-by: Keith Packard <keithp@xxxxxxxxxx> --- src/intel/vulkan/anv_extensions.py | 1 + src/intel/vulkan/anv_private.h | 4 ++ src/intel/vulkan/anv_queue.c | 59 ++++++++++++++++++--- src/intel/vulkan/anv_wsi_display.c | 103 +++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 7 deletions(-) diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py index 32643e31045..1c6c4f8e27b 100644 --- a/src/intel/vulkan/anv_extensions.py +++ b/src/intel/vulkan/anv_extensions.py @@ -90,6 +90,7 @@ EXTENSIONS = [ Extension('VK_EXT_debug_report', 8, True), Extension('VK_EXT_external_memory_dma_buf', 1, True), Extension('VK_EXT_display_surface_counter', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), + Extension('VK_EXT_display_control', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), ] class VkVersion: diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index d38dd9e4220..1d3e5fcd921 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1941,6 +1941,7 @@ enum anv_fence_type { ANV_FENCE_TYPE_NONE = 0, ANV_FENCE_TYPE_BO, ANV_FENCE_TYPE_SYNCOBJ, + ANV_FENCE_TYPE_WSI, }; enum anv_bo_fence_state { @@ -1975,6 +1976,9 @@ struct anv_fence_impl { /** DRM syncobj handle for syncobj-based fences */ uint32_t syncobj; + + /** WSI fence */ + struct wsi_fence *fence_wsi; }; }; diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c index c6b2e01c628..d0bfad742d7 100644 --- a/src/intel/vulkan/anv_queue.c +++ b/src/intel/vulkan/anv_queue.c @@ -320,6 +320,10 @@ anv_fence_impl_cleanup(struct anv_device *device, case ANV_FENCE_TYPE_SYNCOBJ: anv_gem_syncobj_destroy(device, impl->syncobj); return; + + case ANV_FENCE_TYPE_WSI: + impl->fence_wsi->destroy(impl->fence_wsi); + return; } unreachable("Invalid fence type"); @@ -465,11 +469,32 @@ anv_wait_for_syncobj_fences(struct anv_device *device, uint32_t *syncobjs = vk_zalloc(&device->alloc, sizeof(*syncobjs) * fenceCount, 8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + uint32_t syncobjCount = 0; if (!syncobjs) return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); for (uint32_t i = 0; i < fenceCount; i++) { ANV_FROM_HANDLE(anv_fence, fence, pFences[i]); + + if (fence->permanent.type == ANV_FENCE_TYPE_WSI) { + struct anv_fence_impl *impl = &fence->permanent; + bool expired = impl->fence_wsi->wait(impl->fence_wsi, true, _timeout); + + VkResult result; + + if (!expired) { + result = VK_TIMEOUT; + goto done; + } + if (!waitAll) { + result = VK_SUCCESS; + goto done; + } + continue; + done: + vk_free(&device->alloc, syncobjs); + return result; + } assert(fence->permanent.type == ANV_FENCE_TYPE_SYNCOBJ); struct anv_fence_impl *impl = @@ -477,7 +502,7 @@ anv_wait_for_syncobj_fences(struct anv_device *device, &fence->temporary : &fence->permanent; assert(impl->type == ANV_FENCE_TYPE_SYNCOBJ); - syncobjs[i] = impl->syncobj; + syncobjs[syncobjCount++] = impl->syncobj; } int64_t abs_timeout_ns = 0; @@ -499,7 +524,7 @@ anv_wait_for_syncobj_fences(struct anv_device *device, */ int ret; do { - ret = anv_gem_syncobj_wait(device, syncobjs, fenceCount, + ret = anv_gem_syncobj_wait(device, syncobjs, syncobjCount, abs_timeout_ns, waitAll); } while (ret == -1 && errno == ETIME && gettime_ns() < abs_timeout_ns); @@ -545,14 +570,33 @@ anv_wait_for_bo_fences(struct anv_device *device, for (uint32_t i = 0; i < fenceCount; i++) { ANV_FROM_HANDLE(anv_fence, fence, pFences[i]); - /* This function assumes that all fences are BO fences and that they - * have no temporary state. Since BO fences will never be exported, - * this should be a safe assumption. + /* This function assumes that all fences have no temporary + * state.Since BO fences will never be exported, this should be a + * safe assumption. */ - assert(fence->permanent.type == ANV_FENCE_TYPE_BO); assert(fence->temporary.type == ANV_FENCE_TYPE_NONE); struct anv_fence_impl *impl = &fence->permanent; + /* This function assumes that all fences are either BO fences or WSI + * fences + */ + + if (impl->type == ANV_FENCE_TYPE_WSI) { + bool expired = impl->fence_wsi->wait(impl->fence_wsi, true, timeout); + + if (!expired) { + result = VK_TIMEOUT; + goto done; + } + if (!waitAll) { + result = VK_SUCCESS; + goto done; + } + continue; + } + + assert(impl->type == ANV_FENCE_TYPE_BO); + switch (impl->bo.state) { case ANV_BO_FENCE_STATE_RESET: /* This fence hasn't been submitted yet, we'll catch it the next @@ -610,7 +654,8 @@ anv_wait_for_bo_fences(struct anv_device *device, uint32_t now_pending_fences = 0; for (uint32_t i = 0; i < fenceCount; i++) { ANV_FROM_HANDLE(anv_fence, fence, pFences[i]); - if (fence->permanent.bo.state == ANV_BO_FENCE_STATE_RESET) + if (fence->permanent.type == ANV_FENCE_TYPE_BO && + fence->permanent.bo.state == ANV_BO_FENCE_STATE_RESET) now_pending_fences++; } assert(now_pending_fences <= pending_fences); diff --git a/src/intel/vulkan/anv_wsi_display.c b/src/intel/vulkan/anv_wsi_display.c index e87aed49f7d..32a948d76ca 100644 --- a/src/intel/vulkan/anv_wsi_display.c +++ b/src/intel/vulkan/anv_wsi_display.c @@ -168,3 +168,106 @@ anv_GetRandROutputDisplayEXT(VkPhysicalDevice physical_device, display); } #endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */ + +/* VK_EXT_display_control */ + +VkResult +anv_DisplayPowerControlEXT(VkDevice _device, + VkDisplayKHR display, + const VkDisplayPowerInfoEXT *display_power_info) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + + return wsi_display_power_control(_device, + &device->instance->physicalDevice.wsi_device, + display, + display_power_info); +} + +VkResult +anv_RegisterDeviceEventEXT(VkDevice _device, + const VkDeviceEventInfoEXT *device_event_info, + const VkAllocationCallbacks *allocator, + VkFence *_fence) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + const VkAllocationCallbacks *alloc; + struct anv_fence *fence; + VkResult ret; + + if (allocator) + alloc = allocator; + else + alloc = &device->instance->alloc; + + fence = vk_alloc(alloc, sizeof (*fence), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!fence) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + + fence->permanent.type = ANV_FENCE_TYPE_WSI; + + ret = wsi_register_device_event(_device, + &device->instance->physicalDevice.wsi_device, + device_event_info, + alloc, + &fence->permanent.fence_wsi); + if (ret == VK_SUCCESS) + *_fence = anv_fence_to_handle(fence); + else + vk_free(alloc, fence); + return ret; +} + +VkResult +anv_RegisterDisplayEventEXT(VkDevice _device, + VkDisplayKHR display, + const VkDisplayEventInfoEXT *display_event_info, + const VkAllocationCallbacks *allocator, + VkFence *_fence) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + const VkAllocationCallbacks *alloc; + struct anv_fence *fence; + VkResult ret; + + if (allocator) + alloc = allocator; + else + alloc = &device->instance->alloc; + + fence = vk_zalloc2(&device->alloc, allocator, sizeof (*fence), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!fence) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + fence->permanent.type = ANV_FENCE_TYPE_WSI; + + ret = wsi_register_display_event(_device, + &device->instance->physicalDevice.wsi_device, + display, + display_event_info, + alloc, + &(fence->permanent.fence_wsi)); + + if (ret == VK_SUCCESS) + *_fence = anv_fence_to_handle(fence); + else + vk_free(alloc, fence); + return ret; +} + +VkResult +anv_GetSwapchainCounterEXT(VkDevice _device, + VkSwapchainKHR swapchain, + VkSurfaceCounterFlagBitsEXT flag_bits, + uint64_t *value) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + + return wsi_get_swapchain_counter(_device, + &device->instance->physicalDevice.wsi_device, + swapchain, + flag_bits, + value); +} -- 2.15.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel