diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index ab1693ba..5f4d86e9 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -18,6 +18,22 @@ #include "vkd3d_private.h" +static const char * const required_device_extensions[] = +{ + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_KHR_MAINTENANCE1_EXTENSION_NAME, +}; + +static const struct +{ + const char *extension_name; + ptrdiff_t vulkan_info_offset; +} +optional_device_extensions[] = +{ + {VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, offsetof(struct vkd3d_vulkan_info, KHR_push_descriptor)}, +}; + static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance) { static const char * const extensions[] = @@ -306,6 +322,71 @@ static void vkd3d_trace_physical_device(VkPhysicalDevice device, TRACE(" inheritedQueries: %#x.\n", features.inheritedQueries); } +static bool has_extension(const VkExtensionProperties *vk_extensions, + unsigned int count, const char *extension_name) +{ + unsigned int i; + + for (i = 0; i < count; ++i) + { + if (!strcmp(vk_extensions[i].extensionName, extension_name)) + return true; + } + return false; +} + +static void vkd3d_init_device_caps(struct vkd3d_instance *instance, + VkPhysicalDevice physical_device, struct vkd3d_vulkan_info *vulkan_info) +{ + const struct vkd3d_vk_instance_procs *vk_procs = &instance->vk_procs; + VkExtensionProperties *vk_extensions; + unsigned int i; + uint32_t count; + VkResult vr; + + memset(vulkan_info, 0, sizeof(*vulkan_info)); + + if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, + &count, NULL))) < 0) + { + ERR("Failed to enumerate device extensions, vr %d.\n", vr); + return; + } + if (!count) + return; + + if (!(vk_extensions = vkd3d_calloc(count, sizeof(*vk_extensions)))) + return; + + TRACE("Enumerating %u device extensions.\n", count); + if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, + &count, vk_extensions))) < 0) + { + ERR("Failed to enumerate device extensions, vr %d.\n", vr); + vkd3d_free(vk_extensions); + return; + } + + for (i = 0; i < ARRAY_SIZE(required_device_extensions); ++i) + { + if (!has_extension(vk_extensions, count, required_device_extensions[i])) + ERR("Required device extension %s is not supported.\n", + debugstr_a(required_device_extensions[i])); + } + + for (i = 0; i < ARRAY_SIZE(optional_device_extensions); ++i) + { + const char *extension_name = optional_device_extensions[i].extension_name; + ptrdiff_t offset = optional_device_extensions[i].vulkan_info_offset; + bool *supported = (void *)((uintptr_t)vulkan_info + offset); + + if ((*supported = has_extension(vk_extensions, count, extension_name))) + TRACE("Found %s extension.\n", debugstr_a(extension_name)); + } + + vkd3d_free(vk_extensions); +} + static HRESULT vkd3d_select_physical_device(struct vkd3d_instance *instance, VkPhysicalDevice *selected_device) { @@ -353,12 +434,7 @@ static HRESULT vkd3d_select_physical_device(struct vkd3d_instance *instance, static HRESULT vkd3d_create_vk_device(struct d3d12_device *device) { - static const char * const extensions[] = - { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, - VK_KHR_MAINTENANCE1_EXTENSION_NAME, - }; - + const char *extensions[ARRAY_SIZE(required_device_extensions) + ARRAY_SIZE(optional_device_extensions)]; unsigned int direct_queue_family_index, copy_queue_family_index, compute_queue_family_index; const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance.vk_procs; VkQueueFamilyProperties *queue_properties; @@ -368,7 +444,7 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device) VkDeviceCreateInfo device_info; uint32_t queue_family_count; VkDevice vk_device; - unsigned int i; + unsigned int i, j; VkResult vr; HRESULT hr; @@ -443,9 +519,24 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device) VK_CALL(vkGetPhysicalDeviceMemoryProperties(physical_device, &device->memory_properties)); + vkd3d_init_device_caps(&device->vkd3d_instance, physical_device, &device->vk_info); + /* Create device */ VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &device_features)); + for (i = 0; i < ARRAY_SIZE(required_device_extensions); ++i) + { + extensions[i] = required_device_extensions[i]; + } + for (j = 0; j < ARRAY_SIZE(optional_device_extensions); ++j) + { + ptrdiff_t offset = optional_device_extensions[j].vulkan_info_offset; + bool *supported = (void *)((uintptr_t)&device->vk_info + offset); + + if (*supported) + extensions[i++] = optional_device_extensions[j].extension_name; + } + device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_info.pNext = NULL; device_info.flags = 0; @@ -453,7 +544,7 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device) device_info.pQueueCreateInfos = queue_info; device_info.enabledLayerCount = 0; device_info.ppEnabledLayerNames = NULL; - device_info.enabledExtensionCount = ARRAY_SIZE(extensions); + device_info.enabledExtensionCount = i; device_info.ppEnabledExtensionNames = extensions; device_info.pEnabledFeatures = &device_features; diff --git a/libs/vkd3d/utils.c b/libs/vkd3d/utils.c index 7c5a9add..ae1e204c 100644 --- a/libs/vkd3d/utils.c +++ b/libs/vkd3d/utils.c @@ -286,14 +286,17 @@ HRESULT vkd3d_load_vk_instance_procs(struct vkd3d_vk_instance_procs *procs, ERR("Could not get device proc addr for '" #name "'.\n"); \ return E_FAIL; \ } +#define LOAD_DEVICE_OPTIONAL_PFN(name) \ + procs->name = (void *)procs->vkGetDeviceProcAddr(device, #name); HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs, const struct vkd3d_vk_instance_procs *parent_procs, VkDevice device) { memset(procs, 0, sizeof(*procs)); -#define VK_INSTANCE_PFN COPY_PARENT_PFN -#define VK_DEVICE_PFN LOAD_DEVICE_PFN +#define VK_INSTANCE_PFN COPY_PARENT_PFN +#define VK_DEVICE_PFN LOAD_DEVICE_PFN +#define VK_DEVICE_EXT_PFN LOAD_DEVICE_OPTIONAL_PFN #include "vulkan_procs.h" TRACE("Loaded procs for VkDevice %p.\n", device); diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index d14d5ed6..1e41abd4 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -56,8 +56,9 @@ struct vkd3d_vk_instance_procs struct vkd3d_vk_device_procs { -#define VK_INSTANCE_PFN DECLARE_VK_PFN -#define VK_DEVICE_PFN DECLARE_VK_PFN +#define VK_INSTANCE_PFN DECLARE_VK_PFN +#define VK_DEVICE_PFN DECLARE_VK_PFN +#define VK_DEVICE_EXT_PFN DECLARE_VK_PFN #include "vulkan_procs.h" }; #undef DECLARE_VK_PFN @@ -488,6 +489,11 @@ struct d3d12_command_signature HRESULT d3d12_command_signature_create(struct d3d12_device *device, struct d3d12_command_signature **signature) DECLSPEC_HIDDEN; +struct vkd3d_vulkan_info +{ + bool KHR_push_descriptor; +}; + /* ID3D12Device */ struct d3d12_device { @@ -507,6 +513,8 @@ struct d3d12_device unsigned int compute_queue_family_index; VkPhysicalDeviceMemoryProperties memory_properties; + struct vkd3d_vulkan_info vk_info; + struct vkd3d_instance vkd3d_instance; }; diff --git a/libs/vkd3d/vulkan_procs.h b/libs/vkd3d/vulkan_procs.h index 211bebee..8875cb24 100644 --- a/libs/vkd3d/vulkan_procs.h +++ b/libs/vkd3d/vulkan_procs.h @@ -24,6 +24,10 @@ # define VK_DEVICE_PFN(x) #endif +#ifndef VK_DEVICE_EXT_PFN +# define VK_DEVICE_EXT_PFN(x) +#endif + /* Instance functions (obtained by vkGetInstanceProcAddr). */ VK_INSTANCE_PFN(vkCreateDevice) VK_INSTANCE_PFN(vkDestroyInstance) @@ -160,6 +164,9 @@ VK_DEVICE_PFN(vkSetEvent) VK_DEVICE_PFN(vkUnmapMemory) VK_DEVICE_PFN(vkUpdateDescriptorSets) VK_DEVICE_PFN(vkWaitForFences) +/* VK_KHR_push_descriptor */ +VK_DEVICE_EXT_PFN(vkCmdPushDescriptorSetKHR) #undef VK_INSTANCE_PFN #undef VK_DEVICE_PFN +#undef VK_DEVICE_EXT_PFN