diff mbox

[7/7] radv: add VK_EXT_display_control to radv driver [v3]

Message ID 20180615025256.10657-8-keithp@keithp.com
State New, archived
Headers show

Commit Message

Keith Packard June 15, 2018, 2:52 a.m. UTC
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>

Signed-off-by: Keith Packard <keithp@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 mbox

Patch

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);
+}
+