radv: add VK_EXT_display_control to radv driver [v5]
authorKeith Packard <keithp@keithp.com>
Fri, 16 Jun 2017 04:00:56 +0000 (21:00 -0700)
committerKeith Packard <keithp@keithp.com>
Sat, 23 Jun 2018 14:59:00 +0000 (07:59 -0700)
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.

v2:
Rework fence integration into the driver so that waiting for
any of a mixture of fence types (wsi, driver or syncobjs)
causes the driver to poll, while a list of just syncobjs or
just driver fences will block. When we get syncobjs for wsi
fences, we'll adapt to use them.

v3: Adopt Jason Ekstrand's coding conventions

Declare variables at first use, eliminate extra whitespace between
types and names. Wrap lines to 80 columns.

Suggested-by: Jason Ekstrand <jason.ekstrand@intel.com>
v4: Adapt to WSI fence API change. It now returns VkResult and
no longer has an option for relative timeouts.

v5: wsi_register_display_event and wsi_register_device_event now
use the default allocator when NULL is provided, so remove the
computation of 'alloc' here.

Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
src/amd/vulkan/radv_device.c
src/amd/vulkan/radv_extensions.py
src/amd/vulkan/radv_private.h
src/amd/vulkan/radv_wsi_display.c

index b72b5d969df82f3b5d40b7dcccf04e75762b17d2..62e1b9dba66ff174969e2f59f27b86c6ce2c57a7 100644 (file)
@@ -3251,6 +3251,7 @@ VkResult radv_CreateFence(
        if (!fence)
                return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
 
+       fence->fence_wsi = NULL;
        fence->submitted = false;
        fence->signalled = !!(pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT);
        fence->temp_syncobj = 0;
@@ -3295,6 +3296,8 @@ void radv_DestroyFence(
                device->ws->destroy_syncobj(device->ws, fence->syncobj);
        if (fence->fence)
                device->ws->destroy_fence(fence->fence);
+       if (fence->fence_wsi)
+               fence->fence_wsi->destroy(fence->fence_wsi);
        vk_free2(&device->alloc, pAllocator, fence);
 }
 
@@ -3320,7 +3323,19 @@ static bool radv_all_fences_plain_and_submitted(uint32_t fenceCount, const VkFen
 {
        for (uint32_t i = 0; i < fenceCount; ++i) {
                RADV_FROM_HANDLE(radv_fence, fence, pFences[i]);
-               if (fence->syncobj || fence->temp_syncobj || (!fence->signalled && !fence->submitted))
+               if (fence->fence == NULL || fence->syncobj ||
+                   fence->temp_syncobj ||
+                   (!fence->signalled && !fence->submitted))
+                       return false;
+       }
+       return true;
+}
+
+static bool radv_all_fences_syncobj(uint32_t fenceCount, const VkFence *pFences)
+{
+       for (uint32_t i = 0; i < fenceCount; ++i) {
+               RADV_FROM_HANDLE(radv_fence, fence, pFences[i]);
+               if (fence->syncobj == 0 && fence->temp_syncobj == 0)
                        return false;
        }
        return true;
@@ -3336,7 +3351,9 @@ VkResult radv_WaitForFences(
        RADV_FROM_HANDLE(radv_device, device, _device);
        timeout = radv_get_absolute_timeout(timeout);
 
-       if (device->always_use_syncobj) {
+       if (device->always_use_syncobj &&
+           radv_all_fences_syncobj(fenceCount, pFences))
+       {
                uint32_t *handles = malloc(sizeof(uint32_t) * fenceCount);
                if (!handles)
                        return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -3406,21 +3423,34 @@ VkResult radv_WaitForFences(
                if (fence->signalled)
                        continue;
 
-               if (!fence->submitted) {
-                       while(radv_get_current_time() <= timeout && !fence->submitted)
-                               /* Do nothing */;
+               if (fence->fence) {
+                       if (!fence->submitted) {
+                               while(radv_get_current_time() <= timeout &&
+                                     !fence->submitted)
+                                       /* Do nothing */;
 
-                       if (!fence->submitted)
-                               return VK_TIMEOUT;
+                               if (!fence->submitted)
+                                       return VK_TIMEOUT;
+
+                               /* Recheck as it may have been set by
+                                * submitting operations. */
 
-                       /* Recheck as it may have been set by submitting operations. */
-                       if (fence->signalled)
-                               continue;
+                               if (fence->signalled)
+                                       continue;
+                       }
+
+                       expired = device->ws->fence_wait(device->ws,
+                                                        fence->fence,
+                                                        true, timeout);
+                       if (!expired)
+                               return VK_TIMEOUT;
                }
 
-               expired = device->ws->fence_wait(device->ws, fence->fence, true, timeout);
-               if (!expired)
-                       return VK_TIMEOUT;
+               if (fence->fence_wsi) {
+                       VkResult result = fence->fence_wsi->wait(fence->fence_wsi, timeout);
+                       if (result != VK_SUCCESS)
+                               return result;
+               }
 
                fence->signalled = true;
        }
@@ -3472,9 +3502,19 @@ VkResult radv_GetFenceStatus(VkDevice _device, VkFence _fence)
                return VK_SUCCESS;
        if (!fence->submitted)
                return VK_NOT_READY;
-       if (!device->ws->fence_wait(device->ws, fence->fence, false, 0))
-               return VK_NOT_READY;
+       if (fence->fence) {
+               if (!device->ws->fence_wait(device->ws, fence->fence, false, 0))
+                       return VK_NOT_READY;
+       }
+       if (fence->fence_wsi) {
+               VkResult result = fence->fence_wsi->wait(fence->fence_wsi, 0);
 
+               if (result != VK_SUCCESS) {
+                       if (result == VK_TIMEOUT)
+                               return VK_NOT_READY;
+                       return result;
+               }
+       }
        return VK_SUCCESS;
 }
 
index 601a345b114dbbd93b0b7abf1eb3999c0dbea683..ebc3f6bc2b585d7222d176371bf69c695372bcac 100644 (file)
@@ -90,6 +90,7 @@ EXTENSIONS = [
     Extension('VK_EXT_direct_mode_display',               1, 'VK_USE_PLATFORM_DISPLAY_KHR'),
     Extension('VK_EXT_acquire_xlib_display',              1, 'VK_USE_PLATFORM_XLIB_XRANDR_EXT'),
     Extension('VK_EXT_display_surface_counter',           1, 'VK_USE_PLATFORM_DISPLAY_KHR'),
+    Extension('VK_EXT_display_control',                   1, 'VK_USE_PLATFORM_DISPLAY_KHR'),
     Extension('VK_EXT_debug_report',                      9, True),
     Extension('VK_EXT_depth_range_unrestricted',          1, True),
     Extension('VK_EXT_descriptor_indexing',               2, True),
index c77a8b297f8a8093f13fc497e21c08166b9aa707..f001b836c8feaf5eda1ea88469525f62d0177560 100644 (file)
@@ -1781,6 +1781,7 @@ void radv_initialize_dcc(struct radv_cmd_buffer *cmd_buffer,
 
 struct radv_fence {
        struct radeon_winsys_fence *fence;
+       struct wsi_fence *fence_wsi;
        bool submitted;
        bool signalled;
 
index 84431019dbb40eb14cc9870d6b3e92a0c0e23186..3a4774e2f566cc540baabe39eb8ef5a84c399e88 100644 (file)
@@ -194,3 +194,104 @@ radv_GetRandROutputDisplayEXT(VkPhysicalDevice  physical_device,
                                            display);
 }
 #endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
+
+/* VK_EXT_display_control */
+
+VkResult
+radv_DisplayPowerControlEXT(VkDevice                    _device,
+                           VkDisplayKHR                display,
+                           const VkDisplayPowerInfoEXT *display_power_info)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+
+       return wsi_display_power_control(_device,
+                                        &device->physical_device->wsi_device,
+                                        display,
+                                        display_power_info);
+}
+
+VkResult
+radv_RegisterDeviceEventEXT(VkDevice                    _device,
+                           const VkDeviceEventInfoEXT  *device_event_info,
+                           const VkAllocationCallbacks *allocator,
+                           VkFence                     *_fence)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+       struct radv_fence            *fence;
+       VkResult                     ret;
+
+       fence = vk_alloc2(&device->instance->alloc, allocator, sizeof (*fence),
+                         8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       if (!fence)
+               return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+       fence->fence = NULL;
+       fence->submitted = true;
+       fence->signalled = false;
+       fence->syncobj = 0;
+       fence->temp_syncobj = 0;
+
+       ret = wsi_register_device_event(_device,
+                                       &device->physical_device->wsi_device,
+                                       device_event_info,
+                                       allocator,
+                                       &fence->fence_wsi);
+       if (ret == VK_SUCCESS)
+               *_fence = radv_fence_to_handle(fence);
+       else
+               vk_free2(&device->instance->alloc, allocator, fence);
+       return ret;
+}
+
+VkResult
+radv_RegisterDisplayEventEXT(VkDevice                           _device,
+                            VkDisplayKHR                       display,
+                            const VkDisplayEventInfoEXT        *display_event_info,
+                            const VkAllocationCallbacks        *allocator,
+                            VkFence                            *_fence)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+
+       struct radv_fence            *fence;
+       VkResult                     ret;
+
+       fence = vk_alloc2(&device->instance->alloc, allocator, sizeof (*fence),
+                         8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       if (!fence)
+               return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+       fence->fence = NULL;
+       fence->submitted = true;
+       fence->signalled = false;
+       fence->syncobj = 0;
+       fence->temp_syncobj = 0;
+
+       ret = wsi_register_display_event(_device,
+                                        &device->physical_device->wsi_device,
+                                        display,
+                                        display_event_info,
+                                        allocator,
+                                        &(fence->fence_wsi));
+
+       if (ret == VK_SUCCESS)
+               *_fence = radv_fence_to_handle(fence);
+       else
+               vk_free2(&device->instance->alloc, allocator, fence);
+       return ret;
+}
+
+VkResult
+radv_GetSwapchainCounterEXT(VkDevice                    _device,
+                           VkSwapchainKHR              swapchain,
+                           VkSurfaceCounterFlagBitsEXT flag_bits,
+                           uint64_t                    *value)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+
+       return wsi_get_swapchain_counter(_device,
+                                        &device->physical_device->wsi_device,
+                                        swapchain,
+                                        flag_bits,
+                                        value);
+}
+