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.ekstr...@intel.com>

Signed-off-by: Keith Packard <kei...@keithp.com>
---
 src/amd/vulkan/radv_device.c      |  68 +++++++++++++-----
 src/amd/vulkan/radv_extensions.py |   1 +
 src/amd/vulkan/radv_private.h     |   1 +
 src/amd/vulkan/radv_wsi_display.c | 113 ++++++++++++++++++++++++++++++
 4 files changed, 167 insertions(+), 16 deletions(-)

diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index 59ee503c8c2..fd80db1c9b4 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -3240,6 +3240,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;
@@ -3284,6 +3285,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);
 }
 
@@ -3309,7 +3312,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;
@@ -3325,7 +3340,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);
@@ -3395,21 +3412,35 @@ 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. */
-                       if (fence->signalled)
-                               continue;
+                               /* Recheck as it may have been set by
+                                * submitting operations. */
+
+                               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) {
+                       expired = fence->fence_wsi->wait(fence->fence_wsi,
+                                                        true, timeout);
+                       if (!expired)
+                               return VK_TIMEOUT;
+               }
 
                fence->signalled = true;
        }
@@ -3461,9 +3492,14 @@ 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) {
+               if (!fence->fence_wsi->wait(fence->fence_wsi, false, 0))
+                       return VK_NOT_READY;
+       }
        return VK_SUCCESS;
 }
 
diff --git a/src/amd/vulkan/radv_extensions.py 
b/src/amd/vulkan/radv_extensions.py
index 601a345b114..ebc3f6bc2b5 100644
--- a/src/amd/vulkan/radv_extensions.py
+++ b/src/amd/vulkan/radv_extensions.py
@@ -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),
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 3d71d3bdb03..1e881a61018 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -1778,6 +1778,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;
 
diff --git a/src/amd/vulkan/radv_wsi_display.c 
b/src/amd/vulkan/radv_wsi_display.c
index 0f88ce13942..5c0460378af 100644
--- a/src/amd/vulkan/radv_wsi_display.c
+++ b/src/amd/vulkan/radv_wsi_display.c
@@ -188,3 +188,116 @@ 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);
+       const VkAllocationCallbacks  *alloc;
+       struct radv_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_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,
+                                       alloc,
+                                       &fence->fence_wsi);
+       if (ret == VK_SUCCESS)
+               *_fence = radv_fence_to_handle(fence);
+       else
+               vk_free(alloc, 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);
+
+       const VkAllocationCallbacks  *alloc;
+       struct radv_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_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,
+                                        alloc,
+                                        &(fence->fence_wsi));
+
+       if (ret == VK_SUCCESS)
+               *_fence = radv_fence_to_handle(fence);
+       else
+               vk_free(alloc, 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);
+}
+
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to