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
3b3d58df47 and
84e165ef64.
This commit is contained in:
Camilla Löwy 2022-07-06 23:07:20 +02:00
parent 2568d703cd
commit 109f836675
2 changed files with 116 additions and 87 deletions

View File

@ -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) static void list_vulkan_instance_layers(void)
{ {
uint32_t i, lp_count = 0; uint32_t i, lp_count = 0;
@ -263,30 +239,6 @@ static void list_vulkan_instance_layers(void)
free(lp); 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) static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice device)
{ {
uint32_t i, lp_count; uint32_t i, lp_count;
@ -346,11 +298,6 @@ static void print_version(void)
printf("GLFW library version string: \"%s\"\n", glfwGetVersionString()); 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 main(int argc, char** argv)
{ {
int ch, client, major, minor, revision, profile; int ch, client, major, minor, revision, profile;
@ -812,14 +759,16 @@ int main(int argc, char** argv)
if (glfwVulkanSupported()) if (glfwVulkanSupported())
{ {
uint32_t loader_version = VK_API_VERSION_1_0; 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; const char** re;
VkApplicationInfo ai = {0}; VkApplicationInfo ai = {0};
VkInstanceCreateInfo ici = {0}; VkInstanceCreateInfo ici = {0};
VkInstance instance; VkInstance instance;
VkPhysicalDevice* pd; VkPhysicalDevice* pd;
gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, NULL); gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, NULL);
if (vkEnumerateInstanceVersion) if (vkEnumerateInstanceVersion)
{ {
@ -832,20 +781,47 @@ int main(int argc, char** argv)
VK_VERSION_MAJOR(loader_version), VK_VERSION_MAJOR(loader_version),
VK_VERSION_MINOR(loader_version)); VK_VERSION_MINOR(loader_version));
re = glfwGetRequiredInstanceExtensions(&re_count); glfw_re = glfwGetRequiredInstanceExtensions(&glfw_re_count);
printf("Vulkan required instance extensions:"); re_count = glfw_re_count;
if (re) 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++) for (i = 0; i < glfw_re_count; i++)
printf(" %s", re[i]); {
putchar('\n'); printf(" %s\n", glfw_re[i]);
re[i] = glfw_re[i];
}
} }
else else
printf(" missing\n"); printf(" missing\n");
vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL);
VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep);
if (list_extensions) 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) if (list_layers)
list_vulkan_instance_layers(); list_vulkan_instance_layers();
@ -866,34 +842,27 @@ int main(int argc, char** argv)
ici.enabledExtensionCount = re_count; ici.enabledExtensionCount = re_count;
ici.ppEnabledExtensionNames = re; ici.ppEnabledExtensionNames = re;
if (portability_enumeration)
ici.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS) if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS)
{ {
glfwTerminate(); glfwTerminate();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, instance); free((void*) re);
if (vkEnumeratePhysicalDevices(instance, &pd_count, NULL) != VK_SUCCESS) gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, instance);
{
vkDestroyInstance(instance, NULL);
glfwTerminate();
exit(EXIT_FAILURE);
}
vkEnumeratePhysicalDevices(instance, &pd_count, NULL);
pd = calloc(pd_count, sizeof(VkPhysicalDevice)); pd = calloc(pd_count, sizeof(VkPhysicalDevice));
vkEnumeratePhysicalDevices(instance, &pd_count, pd);
if (vkEnumeratePhysicalDevices(instance, &pd_count, pd) != VK_SUCCESS)
{
free(pd);
vkDestroyInstance(instance, NULL);
glfwTerminate();
exit(EXIT_FAILURE);
}
for (i = 0; i < pd_count; i++) for (i = 0; i < pd_count; i++)
{ {
VkPhysicalDeviceProperties pdp; VkPhysicalDeviceProperties pdp;
uint32_t qfp_count, ep_count;
vkGetPhysicalDeviceProperties(pd[i], &pdp); vkGetPhysicalDeviceProperties(pd[i], &pdp);
@ -903,8 +872,62 @@ int main(int argc, char** argv)
VK_VERSION_MAJOR(pdp.apiVersion), VK_VERSION_MAJOR(pdp.apiVersion),
VK_VERSION_MINOR(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) 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) if (list_layers)
list_vulkan_device_layers(instance, pd[i]); list_vulkan_device_layers(instance, pd[i]);

View File

@ -65,11 +65,6 @@
exit(1); \ exit(1); \
} while (0) } while (0)
static GLADapiproc glad_vulkan_callback(const char* name, void* user)
{
return glfwGetInstanceProcAddress((VkInstance) user, name);
}
static const uint32_t fragShaderCode[] = { static const uint32_t fragShaderCode[] = {
0x07230203,0x00010000,0x00080007,0x00000014,0x00000000,0x00020011,0x00000001,0x0006000b, 0x07230203,0x00010000,0x00080007,0x00000014,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
@ -1251,7 +1246,7 @@ static void demo_prepare_pipeline(struct demo *demo) {
VkPipelineDepthStencilStateCreateInfo ds; VkPipelineDepthStencilStateCreateInfo ds;
VkPipelineViewportStateCreateInfo vp; VkPipelineViewportStateCreateInfo vp;
VkPipelineMultisampleStateCreateInfo ms; VkPipelineMultisampleStateCreateInfo ms;
VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE]; VkDynamicState dynamicStateEnables[2];
VkPipelineDynamicStateCreateInfo dynamicState; VkPipelineDynamicStateCreateInfo dynamicState;
VkResult U_ASSERT_ONLY err; 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) { static void demo_init_vk(struct demo *demo) {
VkResult err; VkResult err;
VkBool32 portability_enumeration = VK_FALSE;
uint32_t i = 0; uint32_t i = 0;
uint32_t required_extension_count = 0; uint32_t required_extension_count = 0;
uint32_t instance_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); 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); free(instance_extensions);
@ -1696,6 +1699,9 @@ static void demo_init_vk(struct demo *demo) {
.ppEnabledExtensionNames = (const char *const *)demo->extension_names, .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
}; };
if (portability_enumeration)
inst_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
uint32_t gpu_count; uint32_t gpu_count;
err = vkCreateInstance(&inst_info, NULL, &demo->inst); err = vkCreateInstance(&inst_info, NULL, &demo->inst);
@ -1715,7 +1721,7 @@ static void demo_init_vk(struct demo *demo) {
"vkCreateInstance Failure"); "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*/ /* Make initial call to query gpu_count, then second call for gpu info*/
err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL); err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
@ -1738,7 +1744,7 @@ static void demo_init_vk(struct demo *demo) {
"vkEnumeratePhysicalDevices Failure"); "vkEnumeratePhysicalDevices Failure");
} }
gladLoadVulkanUserPtr(demo->gpu, glad_vulkan_callback, demo->inst); gladLoadVulkanUserPtr(demo->gpu, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, demo->inst);
/* Look for device extensions */ /* Look for device extensions */
uint32_t device_extension_count = 0; uint32_t device_extension_count = 0;
@ -1966,7 +1972,7 @@ static void demo_init_connection(struct demo *demo) {
exit(1); 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[]) static void demo_init(struct demo *demo, const int argc, const char *argv[])