From 109f836675d43d84a88821680eea1a711df01c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 6 Jul 2022 23:07:20 +0200 Subject: [PATCH] Add support for VK_KHR_portability_enumeration The use of this extension is required to enable the MoltenVK physical device as of Vulkan SDK 1.3.216.0. This is because MoltenVK is still very (very) slightly non-conformant. This was adapted to 3.3-stable from 3b3d58df47166865494c29cf3aeb826d1dd29777 and 84e165ef64ce117c5f1fa99b607f5bd143973e65. --- tests/glfwinfo.c | 179 +++++++++++++++++++++++----------------- tests/triangle-vulkan.c | 24 ++++-- 2 files changed, 116 insertions(+), 87 deletions(-) diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index 074bcbd6..f681e0a5 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -210,30 +210,6 @@ static void list_context_extensions(int client, int major, int minor) } } -static void list_vulkan_instance_extensions(void) -{ - uint32_t i, ep_count = 0; - VkExtensionProperties* ep; - - printf("Vulkan instance extensions:\n"); - - if (vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL) != VK_SUCCESS) - return; - - ep = calloc(ep_count, sizeof(VkExtensionProperties)); - - if (vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep) != VK_SUCCESS) - { - free(ep); - return; - } - - for (i = 0; i < ep_count; i++) - printf(" %s (v%u)\n", ep[i].extensionName, ep[i].specVersion); - - free(ep); -} - static void list_vulkan_instance_layers(void) { uint32_t i, lp_count = 0; @@ -263,30 +239,6 @@ static void list_vulkan_instance_layers(void) free(lp); } -static void list_vulkan_device_extensions(VkInstance instance, VkPhysicalDevice device) -{ - uint32_t i, ep_count; - VkExtensionProperties* ep; - - printf("Vulkan device extensions:\n"); - - if (vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, NULL) != VK_SUCCESS) - return; - - ep = calloc(ep_count, sizeof(VkExtensionProperties)); - - if (vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, ep) != VK_SUCCESS) - { - free(ep); - return; - } - - for (i = 0; i < ep_count; i++) - printf(" %s (v%u)\n", ep[i].extensionName, ep[i].specVersion); - - free(ep); -} - static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice device) { uint32_t i, lp_count; @@ -346,11 +298,6 @@ static void print_version(void) printf("GLFW library version string: \"%s\"\n", glfwGetVersionString()); } -static GLADapiproc glad_vulkan_callback(const char* name, void* user) -{ - return glfwGetInstanceProcAddress((VkInstance) user, name); -} - int main(int argc, char** argv) { int ch, client, major, minor, revision, profile; @@ -812,14 +759,16 @@ int main(int argc, char** argv) if (glfwVulkanSupported()) { uint32_t loader_version = VK_API_VERSION_1_0; - uint32_t i, re_count, pd_count; + int portability_enumeration = GLFW_FALSE; + uint32_t i, j, glfw_re_count, re_count, pd_count, ep_count; + const char** glfw_re; const char** re; VkApplicationInfo ai = {0}; VkInstanceCreateInfo ici = {0}; VkInstance instance; VkPhysicalDevice* pd; - gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, NULL); + gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, NULL); if (vkEnumerateInstanceVersion) { @@ -832,20 +781,47 @@ int main(int argc, char** argv) VK_VERSION_MAJOR(loader_version), VK_VERSION_MINOR(loader_version)); - re = glfwGetRequiredInstanceExtensions(&re_count); + glfw_re = glfwGetRequiredInstanceExtensions(&glfw_re_count); - printf("Vulkan required instance extensions:"); - if (re) + re_count = glfw_re_count; + re = calloc(glfw_re_count, sizeof(char*)); + + printf("Vulkan window surface required instance extensions:\n"); + if (glfw_re) { - for (i = 0; i < re_count; i++) - printf(" %s", re[i]); - putchar('\n'); + for (i = 0; i < glfw_re_count; i++) + { + printf(" %s\n", glfw_re[i]); + re[i] = glfw_re[i]; + } } else printf(" missing\n"); + vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL); + VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties)); + vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep); + if (list_extensions) - list_vulkan_instance_extensions(); + { + printf("Vulkan instance extensions:\n"); + + for (i = 0; i < ep_count; i++) + printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion); + } + + for (i = 0; i < ep_count; i++) + { + if (strcmp(ep[i].extensionName, "VK_KHR_portability_enumeration") != 0) + continue; + + re_count++; + re = realloc((void*) re, sizeof(char*) * re_count); + re[re_count - 1] = "VK_KHR_portability_enumeration"; + portability_enumeration = GLFW_TRUE; + } + + free(ep); if (list_layers) list_vulkan_instance_layers(); @@ -866,34 +842,27 @@ int main(int argc, char** argv) ici.enabledExtensionCount = re_count; ici.ppEnabledExtensionNames = re; + if (portability_enumeration) + ici.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS) { glfwTerminate(); exit(EXIT_FAILURE); } - gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, instance); + free((void*) re); - if (vkEnumeratePhysicalDevices(instance, &pd_count, NULL) != VK_SUCCESS) - { - vkDestroyInstance(instance, NULL); - glfwTerminate(); - exit(EXIT_FAILURE); - } + gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, instance); + vkEnumeratePhysicalDevices(instance, &pd_count, NULL); pd = calloc(pd_count, sizeof(VkPhysicalDevice)); - - if (vkEnumeratePhysicalDevices(instance, &pd_count, pd) != VK_SUCCESS) - { - free(pd); - vkDestroyInstance(instance, NULL); - glfwTerminate(); - exit(EXIT_FAILURE); - } + vkEnumeratePhysicalDevices(instance, &pd_count, pd); for (i = 0; i < pd_count; i++) { VkPhysicalDeviceProperties pdp; + uint32_t qfp_count, ep_count; vkGetPhysicalDeviceProperties(pd[i], &pdp); @@ -903,8 +872,62 @@ int main(int argc, char** argv) VK_VERSION_MAJOR(pdp.apiVersion), VK_VERSION_MINOR(pdp.apiVersion)); + vkGetPhysicalDeviceQueueFamilyProperties(pd[i], &qfp_count, NULL); + + vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, NULL); + VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties)); + vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, ep); + + if (portability_enumeration) + { + int conformant = GLFW_TRUE; + + for (j = 0; j < ep_count; j++) + { + if (strcmp(ep[j].extensionName, "VK_KHR_portability_subset") == 0) + { + conformant = GLFW_FALSE; + break; + } + } + + printf("Vulkan %s %s device: \"%s\" (API version %i.%i)\n", + conformant ? "conformant" : "non-conformant", + get_device_type_name(pdp.deviceType), + pdp.deviceName, + VK_VERSION_MAJOR(pdp.apiVersion), + VK_VERSION_MINOR(pdp.apiVersion)); + } + else + { + printf("Vulkan %s device: \"%s\" (API version %i.%i)\n", + get_device_type_name(pdp.deviceType), + pdp.deviceName, + VK_VERSION_MAJOR(pdp.apiVersion), + VK_VERSION_MINOR(pdp.apiVersion)); + } + + if (glfw_re_count) + { + printf("Vulkan device queue family presentation support:\n"); + for (j = 0; j < qfp_count; j++) + { + printf(" %u: ", j); + if (glfwGetPhysicalDevicePresentationSupport(instance, pd[i], j)) + printf("supported\n"); + else + printf("no\n"); + } + } + if (list_extensions) - list_vulkan_device_extensions(instance, pd[i]); + { + printf("Vulkan device extensions:\n"); + for (j = 0; j < ep_count; j++) + printf(" %s (spec version %u)\n", ep[j].extensionName, ep[j].specVersion); + } + + free(ep); if (list_layers) list_vulkan_device_layers(instance, pd[i]); diff --git a/tests/triangle-vulkan.c b/tests/triangle-vulkan.c index 7f783694..3a4bfb18 100644 --- a/tests/triangle-vulkan.c +++ b/tests/triangle-vulkan.c @@ -65,11 +65,6 @@ exit(1); \ } while (0) -static GLADapiproc glad_vulkan_callback(const char* name, void* user) -{ - return glfwGetInstanceProcAddress((VkInstance) user, name); -} - static const uint32_t fragShaderCode[] = { 0x07230203,0x00010000,0x00080007,0x00000014,0x00000000,0x00020011,0x00000001,0x0006000b, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, @@ -1251,7 +1246,7 @@ static void demo_prepare_pipeline(struct demo *demo) { VkPipelineDepthStencilStateCreateInfo ds; VkPipelineViewportStateCreateInfo vp; VkPipelineMultisampleStateCreateInfo ms; - VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE]; + VkDynamicState dynamicStateEnables[2]; VkPipelineDynamicStateCreateInfo dynamicState; VkResult U_ASSERT_ONLY err; @@ -1565,6 +1560,7 @@ static VkBool32 demo_check_layers(uint32_t check_count, const char **check_names static void demo_init_vk(struct demo *demo) { VkResult err; + VkBool32 portability_enumeration = VK_FALSE; uint32_t i = 0; uint32_t required_extension_count = 0; uint32_t instance_extension_count = 0; @@ -1672,6 +1668,13 @@ static void demo_init_vk(struct demo *demo) { } } assert(demo->enabled_extension_count < 64); + if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + demo->extension_names[demo->enabled_extension_count++] = + VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME; + portability_enumeration = VK_TRUE; + } + assert(demo->enabled_extension_count < 64); } free(instance_extensions); @@ -1696,6 +1699,9 @@ static void demo_init_vk(struct demo *demo) { .ppEnabledExtensionNames = (const char *const *)demo->extension_names, }; + if (portability_enumeration) + inst_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + uint32_t gpu_count; err = vkCreateInstance(&inst_info, NULL, &demo->inst); @@ -1715,7 +1721,7 @@ static void demo_init_vk(struct demo *demo) { "vkCreateInstance Failure"); } - gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, demo->inst); + gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, demo->inst); /* Make initial call to query gpu_count, then second call for gpu info*/ err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL); @@ -1738,7 +1744,7 @@ static void demo_init_vk(struct demo *demo) { "vkEnumeratePhysicalDevices Failure"); } - gladLoadVulkanUserPtr(demo->gpu, glad_vulkan_callback, demo->inst); + gladLoadVulkanUserPtr(demo->gpu, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, demo->inst); /* Look for device extensions */ uint32_t device_extension_count = 0; @@ -1966,7 +1972,7 @@ static void demo_init_connection(struct demo *demo) { exit(1); } - gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, NULL); + gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, NULL); } static void demo_init(struct demo *demo, const int argc, const char *argv[])