[PATCH 4/7] winevulkan: Filter graphics driver reported instance extensions.
Roderick Colenbrander
thunderbird2k at gmail.com
Thu Mar 15 01:39:37 CDT 2018
Signed-off-by: Roderick Colenbrander <thunderbird2k at gmail.com>
---
dlls/winevulkan/make_vulkan | 23 +++++++++++++-
dlls/winevulkan/vulkan.c | 67 ++++++++++++++++++++++++++++++++++++++++-
dlls/winevulkan/vulkan_thunks.c | 17 +++++++++++
dlls/winevulkan/vulkan_thunks.h | 1 +
dlls/winex11.drv/vulkan.c | 60 ++++++++++++++++++++++++++++--------
5 files changed, 153 insertions(+), 15 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index c835b997fc..a1d71f9aa0 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -1796,6 +1796,15 @@ class VkGenerator(object):
f.write(" \"{0}\",\n".format(ext["name"]))
f.write("};\n\n")
+ # Create array of instance extensions.
+ f.write("static const char *vk_instance_extensions[] =\n{\n")
+ for ext in self.registry.extensions:
+ if ext["type"] != "instance":
+ continue
+
+ f.write(" \"{0}\",\n".format(ext["name"]))
+ f.write("};\n\n")
+
f.write("BOOL wine_vk_device_extension_supported(const char *name)\n")
f.write("{\n")
f.write(" unsigned int i;\n")
@@ -1805,6 +1814,17 @@ class VkGenerator(object):
f.write(" return TRUE;\n")
f.write(" }\n")
f.write(" return FALSE;\n")
+ f.write("}\n\n")
+
+ f.write("BOOL wine_vk_instance_extension_supported(const char *name)\n")
+ f.write("{\n")
+ f.write(" unsigned int i;\n")
+ f.write(" for (i = 0; i < ARRAY_SIZE(vk_instance_extensions); i++)\n")
+ f.write(" {\n")
+ f.write(" if (strcmp(vk_instance_extensions[i], name) == 0)\n")
+ f.write(" return TRUE;\n")
+ f.write(" }\n")
+ f.write(" return FALSE;\n")
f.write("}\n")
def generate_thunks_h(self, f, prefix):
@@ -1822,7 +1842,8 @@ class VkGenerator(object):
f.write("void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN;\n")
f.write("void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;\n\n")
- f.write("BOOL wine_vk_device_extension_supported(const char *name) DECLSPEC_HIDDEN;\n\n")
+ f.write("BOOL wine_vk_device_extension_supported(const char *name) DECLSPEC_HIDDEN;\n")
+ f.write("BOOL wine_vk_instance_extension_supported(const char *name) DECLSPEC_HIDDEN;\n\n")
# Generate prototypes for device and instance functions requiring a custom implementation.
f.write("/* Functions for which we have custom implementations outside of the thunks. */\n")
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index 8547531247..c0fc810a14 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -769,8 +769,73 @@ VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_
static VkResult WINAPI wine_vkEnumerateInstanceExtensionProperties(const char *layer_name,
uint32_t *count, VkExtensionProperties *properties)
{
+ VkResult res;
+ uint32_t num_properties = 0, num_host_properties = 0;
+ VkExtensionProperties *host_properties = NULL;
+ unsigned int i, j;
+
TRACE("%p %p %p\n", layer_name, count, properties);
- return vk_funcs->p_vkEnumerateInstanceExtensionProperties(layer_name, count, properties);
+
+ /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
+ if (layer_name)
+ {
+ ERR("Layer enumeration not supported from ICD.\n");
+ return VK_ERROR_LAYER_NOT_PRESENT;
+ }
+
+ res = vk_funcs->p_vkEnumerateInstanceExtensionProperties(NULL, &num_host_properties, NULL);
+ if (res != VK_SUCCESS)
+ return res;
+
+ host_properties = heap_calloc(num_host_properties, sizeof(*host_properties));
+ if (!host_properties)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ res = vk_funcs->p_vkEnumerateInstanceExtensionProperties(NULL, &num_host_properties, host_properties);
+ if (res != VK_SUCCESS)
+ {
+ ERR("Failed to retrieve host properties, res=%d\n", res);
+ heap_free(host_properties);
+ return res;
+ }
+
+ /* The Wine graphics driver provides us with all extensions supported by the host side
+ * including extension fixup (e.g. VK_KHR_xlib_surface -> VK_KHR_win32_surface). It is
+ * up to us here to filter the list down to extensions for which we have thunks.
+ */
+ for (i = 0; i < num_host_properties; i++)
+ {
+ if (wine_vk_instance_extension_supported(host_properties[i].extensionName))
+ num_properties++;
+ }
+
+ /* We only have to count. */
+ if (!properties)
+ {
+ TRACE("Returning %u extensions\n", num_properties);
+ *count = num_properties;
+ heap_free(host_properties);
+ return VK_SUCCESS;
+ }
+
+ for (i = 0, j = 0; i < num_host_properties && j < *count; i++)
+ {
+ if (wine_vk_instance_extension_supported(host_properties[i].extensionName))
+ {
+ TRACE("Enabling extension '%s'\n", host_properties[i].extensionName);
+ memcpy(&properties[j], &host_properties[i], sizeof(*properties));
+ j++;
+ }
+ }
+
+ /* Return incomplete if the buffer is smaller than the number of supported extensions. */
+ if (*count < num_properties)
+ res = VK_INCOMPLETE;
+ else
+ res = VK_SUCCESS;
+
+ heap_free(host_properties);
+ return res;
}
VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *device_count,
diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c
index 4b635c2645..0e7b299b27 100644
--- a/dlls/winevulkan/vulkan_thunks.c
+++ b/dlls/winevulkan/vulkan_thunks.c
@@ -2102,6 +2102,12 @@ static const char * const vk_device_extensions[] =
"VK_KHR_swapchain",
};
+static const char *vk_instance_extensions[] =
+{
+ "VK_KHR_surface",
+ "VK_KHR_win32_surface",
+};
+
BOOL wine_vk_device_extension_supported(const char *name)
{
unsigned int i;
@@ -2112,3 +2118,14 @@ BOOL wine_vk_device_extension_supported(const char *name)
}
return FALSE;
}
+
+BOOL wine_vk_instance_extension_supported(const char *name)
+{
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(vk_instance_extensions); i++)
+ {
+ if (strcmp(vk_instance_extensions[i], name) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h
index 7ca4122268..9fb5670762 100644
--- a/dlls/winevulkan/vulkan_thunks.h
+++ b/dlls/winevulkan/vulkan_thunks.h
@@ -13,6 +13,7 @@ void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN;
void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
BOOL wine_vk_device_extension_supported(const char *name) DECLSPEC_HIDDEN;
+BOOL wine_vk_instance_extension_supported(const char *name) DECLSPEC_HIDDEN;
/* Functions for which we have custom implementations outside of the thunks. */
VkResult WINAPI wine_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c
index 1d9bc606eb..0586096254 100644
--- a/dlls/winex11.drv/vulkan.c
+++ b/dlls/winex11.drv/vulkan.c
@@ -21,6 +21,7 @@
#include "wine/port.h"
#include <stdarg.h>
+#include <stdio.h>
#include "windef.h"
#include "winbase.h"
@@ -40,10 +41,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
-#endif
-
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
#define VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR 1000004000
@@ -69,6 +66,7 @@ static VkResult (*pvkCreateXlibSurfaceKHR)(VkInstance, const VkXlibSurfaceCreate
static void (*pvkDestroyInstance)(VkInstance, const VkAllocationCallbacks *);
static void (*pvkDestroySurfaceKHR)(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks *);
static void (*pvkDestroySwapchainKHR)(VkDevice, VkSwapchainKHR, const VkAllocationCallbacks *);
+static VkResult (*pvkEnumerateInstanceExtensionProperties)(const char *, uint32_t *, VkExtensionProperties *);
static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *);
static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *);
static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *);
@@ -79,12 +77,45 @@ static VkBool32 (*pvkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevi
static VkResult (*pvkGetSwapchainImagesKHR)(VkDevice, VkSwapchainKHR, uint32_t *, VkImage *);
static VkResult (*pvkQueuePresentKHR)(VkQueue, const VkPresentInfoKHR *);
-/* TODO: dynamically generate based on host driver capabilities. */
-static const struct VkExtensionProperties winex11_vk_instance_extensions[] =
+static struct VkExtensionProperties *winex11_vk_instance_extensions = NULL;
+static unsigned int winex11_vk_instance_extensions_count = 0;
+
+static void wine_vk_load_instance_extensions(void)
{
- { "VK_KHR_surface", 1 },
- { "VK_KHR_win32_surface", 1},
-};
+ uint32_t num_properties;
+ VkExtensionProperties *properties;
+ unsigned int i;
+
+ pvkEnumerateInstanceExtensionProperties(NULL, &num_properties, NULL);
+
+ properties = heap_calloc(num_properties, sizeof(*properties));
+ if (!properties)
+ return;
+
+ /* We will return the same number of instance extensions reported by the host back to
+ * winevulkan. Along the way we may replace xlib extensions with their win32 equivalents.
+ * Winevulkan will perform more detailed filtering as it knows whether it has thunks
+ * for a particular extension.
+ */
+ pvkEnumerateInstanceExtensionProperties(NULL, &num_properties, properties);
+ for (i = 0; i < num_properties; i++)
+ {
+ /* For now the only x11 extension we need to fixup. Long-term we may need an array. */
+ if (!strcmp(properties[i].extensionName, "VK_KHR_xlib_surface"))
+ {
+ TRACE("Substituting VK_KHR_xlib_surface for VK_KHR_win32_surface\n");
+
+ memset(properties[i].extensionName, 0, sizeof(properties[i].extensionName));
+ snprintf(properties[i].extensionName, sizeof(properties[i].extensionName), "VK_KHR_win32_surface");
+ properties[i].specVersion = 6; /* Revision as of 4/24/2017 */
+ }
+
+ TRACE("Loaded extension: %s\n", properties[i].extensionName);
+ }
+
+ winex11_vk_instance_extensions = properties;
+ winex11_vk_instance_extensions_count = num_properties;
+}
/* Helper function to convert VkSurfaceKHR (uint64_t) to a surface pointer. */
static inline struct wine_vk_surface * surface_from_handle(VkSurfaceKHR handle)
@@ -110,6 +141,7 @@ LOAD_FUNCPTR(vkCreateXlibSurfaceKHR)
LOAD_FUNCPTR(vkDestroyInstance)
LOAD_FUNCPTR(vkDestroySurfaceKHR)
LOAD_FUNCPTR(vkDestroySwapchainKHR)
+LOAD_FUNCPTR(vkEnumerateInstanceExtensionProperties)
LOAD_FUNCPTR(vkGetDeviceProcAddr)
LOAD_FUNCPTR(vkGetInstanceProcAddr)
LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR)
@@ -121,6 +153,8 @@ LOAD_FUNCPTR(vkGetSwapchainImagesKHR)
LOAD_FUNCPTR(vkQueuePresentKHR)
#undef LOAD_FUNCPTR
+ wine_vk_load_instance_extensions();
+
return TRUE;
}
@@ -353,11 +387,11 @@ static VkResult X11DRV_vkEnumerateInstanceExtensionProperties(const char *layer_
* VK_KHR_win32_surface. Long-term this needs to be an intersection
* between what the native library supports and what thunks we have.
*/
- *count = ARRAY_SIZE(winex11_vk_instance_extensions);
+ *count = winex11_vk_instance_extensions_count;
return VK_SUCCESS;
}
- if (*count < ARRAY_SIZE(winex11_vk_instance_extensions))
+ if (*count < winex11_vk_instance_extensions_count)
{
/* Incomplete is a type of success used to signal the application
* that not all devices got copied.
@@ -367,13 +401,13 @@ static VkResult X11DRV_vkEnumerateInstanceExtensionProperties(const char *layer_
}
else
{
- num_copies = ARRAY_SIZE(winex11_vk_instance_extensions);
+ num_copies = winex11_vk_instance_extensions_count;
res = VK_SUCCESS;
}
for (i = 0; i < num_copies; i++)
{
- memcpy(&properties[i], &winex11_vk_instance_extensions[i], sizeof(winex11_vk_instance_extensions[i]));
+ memcpy(&properties[i], &winex11_vk_instance_extensions[i], sizeof(*properties));
}
*count = num_copies;
--
2.14.3
More information about the wine-devel
mailing list