From 01caeebc5aaf8c16906fe2eb07906045b039cceb Mon Sep 17 00:00:00 2001
From: Faith Ekstrand <faith.ekstrand@collabora.com>
Date: Thu, 20 Feb 2025 11:05:59 -0600
Subject: [PATCH] ext_external_objects: Enable VK_KHR_timeline_semaphore if
 available

This also adds a helper to check if an extension is supported.

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/piglit/-/merge_requests/992>
---
 tests/spec/ext_external_objects/vk.c | 60 ++++++++++++++++++++++++++--
 tests/spec/ext_external_objects/vk.h |  6 +++
 2 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/tests/spec/ext_external_objects/vk.c b/tests/spec/ext_external_objects/vk.c
index ddef27477..b527787b1 100644
--- a/tests/spec/ext_external_objects/vk.c
+++ b/tests/spec/ext_external_objects/vk.c
@@ -151,8 +151,13 @@ select_physical_device(VkInstance inst)
 static VkDevice
 create_device(struct vk_ctx *ctx, VkPhysicalDevice pdev)
 {
-	const char *deviceExtensions[] = { "VK_KHR_external_memory_fd",
-					   "VK_KHR_external_semaphore_fd" };
+	const char *required_exts[] = {
+		"VK_KHR_external_memory_fd",
+		"VK_KHR_external_semaphore_fd",
+	};
+	const char *optional_exts[] = {
+		"VK_KHR_timeline_semaphore",
+	};
 	VkDeviceQueueCreateInfo dev_queue_info;
 	VkDeviceCreateInfo dev_info;
 	VkDevice dev;
@@ -161,6 +166,36 @@ create_device(struct vk_ctx *ctx, VkPhysicalDevice pdev)
 	uint32_t i;
 	float qprio = 0;
 
+	VkExtensionProperties *ext_props;
+	uint32_t n_ext_props = 0;
+	vkEnumerateDeviceExtensionProperties(pdev, NULL, &n_ext_props, NULL);
+	ext_props = calloc(n_ext_props, sizeof *ext_props);
+	vkEnumerateDeviceExtensionProperties(pdev, NULL, &n_ext_props, ext_props);
+
+	const char *exts[ARRAY_SIZE(required_exts) + ARRAY_SIZE(optional_exts)];
+	uint32_t n_exts = 0;
+
+	/* Unconditionally add these. Device create will fail if one of them
+	 * isn't supported.
+	 */
+	for (uint32_t i = 0; i < ARRAY_SIZE(required_exts); i++)
+		exts[n_exts++] = required_exts[i];
+
+	for (uint32_t i = 0; i < n_ext_props; i++) {
+		for (uint32_t j = 0; j < ARRAY_SIZE(optional_exts); j++) {
+			if (!strcmp(ext_props[i].extensionName, optional_exts[j]))
+				exts[n_exts++] = optional_exts[j];
+		}
+	}
+
+	free(ext_props);
+
+	/* Stash them in the context for extension support checks */
+	ctx->dev_exts = calloc(n_exts, sizeof *ctx->dev_exts);
+	for (uint32_t i = 0; i < n_exts; i++)
+		ctx->dev_exts[i] = exts[i];
+	ctx->n_dev_exts = n_exts;
+
 	ctx->qfam_idx = -1;
 	vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, 0);
 
@@ -185,8 +220,8 @@ create_device(struct vk_ctx *ctx, VkPhysicalDevice pdev)
 	dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
 	dev_info.queueCreateInfoCount = 1;
 	dev_info.pQueueCreateInfos = &dev_queue_info;
-	dev_info.enabledExtensionCount = ARRAY_SIZE(deviceExtensions);
-	dev_info.ppEnabledExtensionNames = deviceExtensions;
+	dev_info.enabledExtensionCount = n_exts;
+	dev_info.ppEnabledExtensionNames = exts;
 
 	if (vkCreateDevice(pdev, &dev_info, 0, &dev) != VK_SUCCESS)
 		return VK_NULL_HANDLE;
@@ -1018,6 +1053,17 @@ fail:
 	return false;
 }
 
+bool
+vk_device_extension_supported(struct vk_ctx *ctx, const char *ext_name)
+{
+	for (uint32_t i = 0; i < ctx->n_dev_exts; i++) {
+		if (!strcmp(ctx->dev_exts[i], ext_name))
+			return true;
+	}
+
+	return false;
+}
+
 bool
 vk_init_ctx_for_rendering(struct vk_ctx *ctx)
 {
@@ -1065,6 +1111,12 @@ vk_cleanup_ctx(struct vk_ctx *ctx)
 		ctx->cmd_pool = VK_NULL_HANDLE;
 	}
 
+	if (ctx->dev_exts != NULL) {
+		free(ctx->dev_exts);
+		ctx->dev_exts = NULL;
+		ctx->n_dev_exts = 0;
+	}
+
 	if (ctx->dev != VK_NULL_HANDLE) {
 		vkDestroyDevice(ctx->dev, 0);
 		ctx->dev = VK_NULL_HANDLE;
diff --git a/tests/spec/ext_external_objects/vk.h b/tests/spec/ext_external_objects/vk.h
index 5b9cba8c2..bbe1ca6d7 100644
--- a/tests/spec/ext_external_objects/vk.h
+++ b/tests/spec/ext_external_objects/vk.h
@@ -36,6 +36,9 @@ struct vk_ctx
 	VkPhysicalDevice pdev;
 	VkDevice dev;
 
+	const char **dev_exts;
+	uint32_t n_dev_exts;
+
 	VkCommandPool cmd_pool;
 	VkCommandBuffer cmd_buf;
 
@@ -147,6 +150,9 @@ struct vk_dims
 bool
 vk_init_ctx(struct vk_ctx *ctx);
 
+bool
+vk_device_extension_supported(struct vk_ctx *ctx, const char *ext_name);
+
 bool
 vk_init_ctx_for_rendering(struct vk_ctx *ctx);
 
-- 
GitLab