From: Roderick Colenbrander thunderbird2k@gmail.com
The WSI APIs are meant for window system integration, so essentially the WGL of Vulkan. Implementation belongs in the graphics drivers as we need to hook into surface and swapchains.
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
Version 2: * Fix subject. * Use %u for unsigned integer. * Minor coding style fixes. * Use "static const" if possible.
--- dlls/winevulkan/make_vulkan | 114 +++++++++++++++++++++++++++++- dlls/winevulkan/vulkan.c | 153 ++++++++++++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_thunks.c | 12 ++++ dlls/winevulkan/vulkan_thunks.h | 34 +++++++++ dlls/winex11.drv/vulkan.c | 151 ++++++++++++++++++++++++++++++++++++--- include/wine/vulkan.h | 130 ++++++++++++++++++++++++++++++++++ include/wine/vulkan_driver.h | 14 +++- 7 files changed, 597 insertions(+), 11 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 04896daafb8f..5fff3f1511a1 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -68,10 +68,27 @@ WINE_VULKAN_DRIVER_H = "../../include/wine/vulkan_driver.h" WINE_VULKAN_THUNKS_C = "vulkan_thunks.c" WINE_VULKAN_THUNKS_H = "vulkan_thunks.h"
+# Extension enum values start at a certain offset (EXT_BASE). +# Relative to the offset each extension has a block (EXT_BLOCK_SIZE) +# of values. +# Start for a given extension is: +# EXT_BASE + (extension_number-1) * EXT_BLOCK_SIZE +EXT_BASE = 1000000000 +EXT_BLOCK_SIZE = 1000 + +# In general instance extensions can't be automatically generated +# and need custom wrappers due to e.g. win32 / X11 specific code. +# List of supported instance extensions. +SUPPORTED_EXTENSIONS = [ + "VK_KHR_surface", + "VK_KHR_win32_surface", + "VK_KHR_swapchain", +] + # Functions part of our winevulkan graphics driver interface. # DRIVER_VERSION should be bumped on any change to driver interface # in FUNCTION_OVERRIDES -DRIVER_VERSION = 2 +DRIVER_VERSION = 3
# Table of functions for which we have a special implementation. # This are regular device / instance functions for which we need @@ -96,6 +113,24 @@ FUNCTION_OVERRIDES = { # Device functions "vkDestroyDevice" : {"dispatch" : True, "driver" : False, "thunk" : False}, "vkGetDeviceProcAddr" : {"dispatch" : True, "driver" : True, "thunk" : False}, + + # VK_KHR_surface + "vkDestroySurfaceKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "vkGetPhysicalDeviceSurfaceSupportKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "vkGetPhysicalDeviceSurfaceCapabilitiesKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "vkGetPhysicalDeviceSurfaceFormatsKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "vkGetPhysicalDeviceSurfacePresentModesKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + + # VK_KHR_win32_surface + "vkCreateWin32SurfaceKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "vkGetPhysicalDeviceWin32PresentationSupportKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + + # VK_KHR_swapchain + "vkAcquireNextImageKHR": {"dispatch" : True, "driver" : True, "thunk" : False}, + "vkCreateSwapchainKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "vkDestroySwapchainKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "vkGetSwapchainImagesKHR": {"dispatch" : True, "driver" : True, "thunk" : False}, + "vkQueuePresentKHR": {"dispatch" : True, "driver" : True, "thunk" : False}, }
@@ -356,6 +391,11 @@ class VkFunction(object):
def needs_stub(self): """ Temporary function to limit script hacks until more code is implemented. """ + + # Temporary hack to pull in VkSwapChainCreateInfoKHR. + if self.name == "vkCreateSwapchainKHR": + return False + if self.params[0].type != "VkPhysicalDevice": return True
@@ -1997,6 +2037,7 @@ class VkRegistry(object):
# Pull in any required types and functions. self._parse_features(root) + self._parse_extensions(root)
def _mark_command_required(self, command): """ Helper function to mark a certain command and the datatypes it needs as required.""" @@ -2099,6 +2140,77 @@ class VkRegistry(object):
self.enums = OrderedDict(sorted(enums.items()))
+ def _parse_extensions(self, root): + """ Parse extensions section and pull in any types and commands for this extensioin. """ + extensions = [] + exts = root.findall("./extensions/extension") + for ext in exts: + ext_name = ext.attrib["name"] + + # Some extensions are not ready or have numbers reserved as a place holder. + if ext.attrib["supported"] == "disabled": + LOGGER.debug("Skipping disabled extension: {0}".format(ext_name)) + continue + + # We only support a handful of extensions for now through a whitelist. + if ext_name not in SUPPORTED_EXTENSIONS: + LOGGER.debug("Skipping blacklisted extension: {0}".format(ext_name)) + continue + + LOGGER.debug("Loading extension: {0}".format(ext_name)) + + # Extensions can add enum values to Core / extension enums, so add these. + enums = ext.findall("require/enum") + for enum_elem in enums: + if "bitpos" in enum_elem.keys(): + # We need to add an extra value to an existing enum type. + # E.g. VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG to VkFormatFeatureFlagBits. + type_name = enum_elem.attrib["extends"] + enum = self.types[type_name]["data"] + enum.add(VkEnumValue(enum_elem.attrib["name"], 1 << int(enum_elem.attrib["bitpos"]), hex=True)) + elif "offset" in enum_elem.keys(): + ext_number = int(ext.attrib["number"]) + offset = int(enum_elem.attrib["offset"]) + value = EXT_BASE + (ext_number - 1) * EXT_BLOCK_SIZE + offset + + # Deal with negative values. + direction = enum_elem.attrib.get("dir") + if direction is not None: + value = -value + + type_name = enum_elem.attrib["extends"] + enum = self.types[type_name]["data"] + enum.add(VkEnumValue(enum_elem.attrib["name"], value)) + + elif "value" in enum_elem.keys(): + # For now skip, it mostly contains extension name and version info. + continue + else: + # This seems to be used to pull in constants e.g. VK_MAX_DEVICE_GROUP_KHX + continue + + # Store a list with extensions. + ext_type = ext.attrib["type"] + ext_info = {"name" : ext_name, "type" : ext_type} + extensions.append(ext_info) + + commands = ext.findall("require/command") + if not commands: + continue + + # Pull in any commands we need. We infer types to pull in from the command + # as well. + for command in commands: + cmd_name = command.attrib["name"] + self._mark_command_required(cmd_name) + + # Set extension name on the function call as we were not aware of the + # name during initial parsing. + self.funcs[cmd_name].extension = ext_name + + # Sort in alphabetical order. + self.extensions = sorted(extensions, key=lambda ext: ext["name"]) + def _parse_features(self, root): """ Parse the feature section, which describes Core commands and types needed. """ requires = root.findall("./feature/require") diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 678506fbb0e5..61af8df8b848 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -162,6 +162,17 @@ static void wine_vk_instance_free(struct VkInstance_T *instance) heap_free(instance); }
+VkResult WINAPI wine_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, + uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *image_index) +{ + TRACE("%p, 0x%s, 0x%s, 0x%s, 0x%s, %p\n", device, wine_dbgstr_longlong(swapchain), + wine_dbgstr_longlong(timeout), wine_dbgstr_longlong(semaphore), + wine_dbgstr_longlong(fence), image_index); + + return vk_funcs->p_vkAcquireNextImageKHR(device->device, swapchain, timeout, + semaphore, fence, image_index); +} + VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev, const VkDeviceCreateInfo *create_info, const VkAllocationCallbacks *allocator, VkDevice *device) @@ -271,6 +282,72 @@ err: return res; }
+#if defined(USE_STRUCT_CONVERSION) +static inline void convert_VkSwapchainCreateInfoKHR_win_to_host(const VkSwapchainCreateInfoKHR *in, + VkSwapchainCreateInfoKHR_host *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->flags = in->flags; + out->surface = in->surface; + out->minImageCount = in->minImageCount; + out->imageFormat = in->imageFormat; + out->imageColorSpace = in->imageColorSpace; + out->imageExtent = in->imageExtent; + out->imageArrayLayers = in->imageArrayLayers; + out->imageUsage = in->imageUsage; + out->imageSharingMode = in->imageSharingMode; + out->queueFamilyIndexCount = in->queueFamilyIndexCount; + out->pQueueFamilyIndices = in->pQueueFamilyIndices; + out->preTransform = in->preTransform; + out->compositeAlpha = in->compositeAlpha; + out->presentMode = in->presentMode; + out->clipped = in->clipped; + out->oldSwapchain = in->oldSwapchain; +} +#endif + +VkResult WINAPI wine_vkCreateSwapchainKHR(VkDevice device, + const VkSwapchainCreateInfoKHR *create_info, + const VkAllocationCallbacks *allocator, VkSwapchainKHR *swapchain) +{ +#if defined(USE_STRUCT_CONVERSION) + VkSwapchainCreateInfoKHR_host create_info_host; + TRACE("%p %p %p %p\n", device, create_info, allocator, swapchain); + + if (allocator) + FIXME("Support allocation allocators\n"); + + convert_VkSwapchainCreateInfoKHR_win_to_host(create_info, &create_info_host); + + /* Wine graphics driver only uses structs in host format. */ + return vk_funcs->p_vkCreateSwapchainKHR(device->device, + (VkSwapchainCreateInfoKHR *)&create_info_host, allocator, swapchain); +#else + TRACE("%p %p %p %p\n", device, create_info, allocator, swapchain); + + if (allocator) + FIXME("Support allocation allocators\n"); + + return vk_funcs->p_vkCreateSwapchainKHR(device->device, create_info, allocator, swapchain); +#endif +} + +VkResult WINAPI wine_vkCreateWin32SurfaceKHR(VkInstance instance, + const VkWin32SurfaceCreateInfoKHR *create_info, + const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface) +{ + TRACE("%p %p %p %p\n", instance, create_info, allocator, surface); + + if (allocator) + FIXME("Support allocation allocators\n"); + + return vk_funcs->p_vkCreateWin32SurfaceKHR(instance->instance, create_info, + NULL /* allocator */, surface); +} + void WINAPI wine_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *allocator) { TRACE("%p %p\n", device, allocator); @@ -291,6 +368,28 @@ void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallba wine_vk_instance_free(instance); }
+void WINAPI wine_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, + const VkAllocationCallbacks *allocator) +{ + TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(surface), allocator); + + if (allocator) + FIXME("Support allocation allocators\n"); + + vk_funcs->p_vkDestroySurfaceKHR(instance->instance, surface, NULL /* allocator */); +} + +void WINAPI wine_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, + const VkAllocationCallbacks *allocator) +{ + TRACE("%p, 0x%s %p\n", device, wine_dbgstr_longlong(swapchain), allocator); + + if (allocator) + FIXME("Support allocation allocators\n"); + + vk_funcs->p_vkDestroySwapchainKHR(device->device, swapchain, NULL /* allocator */); +} + VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_dev, const char *layer_name, uint32_t *count, VkExtensionProperties *properties) { @@ -418,6 +517,60 @@ static PFN_vkVoidFunction WINAPI wine_vkGetInstanceProcAddr(VkInstance instance, return NULL; }
+VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *capabilities) +{ + TRACE("%p, 0x%s, %p\n", phys_dev, wine_dbgstr_longlong(surface), capabilities); + return vk_funcs->p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev->phys_dev, + surface, capabilities); +} + +VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, uint32_t *format_count, VkSurfaceFormatKHR *formats) +{ + TRACE("%p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), format_count, formats); + return vk_funcs->p_vkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev->phys_dev, + surface, format_count, formats); +} + +VkResult WINAPI wine_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, uint32_t *mode_count, VkPresentModeKHR *modes) +{ + TRACE("%p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), mode_count, modes); + return vk_funcs->p_vkGetPhysicalDeviceSurfacePresentModesKHR(phys_dev->phys_dev, + surface, mode_count, modes); +} + +VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice phys_dev, + uint32_t queue_family_index, VkSurfaceKHR surface, VkBool32 *supported) +{ + TRACE("%p, %u, 0x%s, %p\n", phys_dev, queue_family_index, wine_dbgstr_longlong(surface), supported); + return vk_funcs->p_vkGetPhysicalDeviceSurfaceSupportKHR(phys_dev->phys_dev, + queue_family_index, surface, supported); +} + +VkBool32 WINAPI wine_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev, + uint32_t queue_family_index) +{ + TRACE("%p %u\n", phys_dev, queue_family_index); + return vk_funcs->p_vkGetPhysicalDeviceWin32PresentationSupportKHR(phys_dev->phys_dev, + queue_family_index); +} + +VkResult WINAPI wine_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, + uint32_t *image_count, VkImage *images) +{ + TRACE("%p, 0x%s %p %p\n", device, wine_dbgstr_longlong(swapchain), image_count, images); + return vk_funcs->p_vkGetSwapchainImagesKHR(device->device, swapchain, + image_count, images); +} + +VkResult WINAPI wine_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *present_info) +{ + FIXME("stub: %p, %p\n", queue, present_info); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + void * WINAPI wine_vk_icdGetInstanceProcAddr(VkInstance instance, const char *name) { TRACE("%p %s\n", instance, debugstr_a(name)); diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 3670926c3edf..5d9826cd6756 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -895,6 +895,7 @@ static VkResult WINAPI wine_vkWaitForFences(VkDevice device, uint32_t fenceCount
static const struct vulkan_func vk_device_dispatch_table[] = { + {"vkAcquireNextImageKHR", &wine_vkAcquireNextImageKHR}, {"vkAllocateCommandBuffers", &wine_vkAllocateCommandBuffers}, {"vkAllocateDescriptorSets", &wine_vkAllocateDescriptorSets}, {"vkAllocateMemory", &wine_vkAllocateMemory}, @@ -964,6 +965,7 @@ static const struct vulkan_func vk_device_dispatch_table[] = {"vkCreateSampler", &wine_vkCreateSampler}, {"vkCreateSemaphore", &wine_vkCreateSemaphore}, {"vkCreateShaderModule", &wine_vkCreateShaderModule}, + {"vkCreateSwapchainKHR", &wine_vkCreateSwapchainKHR}, {"vkDestroyBuffer", &wine_vkDestroyBuffer}, {"vkDestroyBufferView", &wine_vkDestroyBufferView}, {"vkDestroyCommandPool", &wine_vkDestroyCommandPool}, @@ -983,6 +985,7 @@ static const struct vulkan_func vk_device_dispatch_table[] = {"vkDestroySampler", &wine_vkDestroySampler}, {"vkDestroySemaphore", &wine_vkDestroySemaphore}, {"vkDestroyShaderModule", &wine_vkDestroyShaderModule}, + {"vkDestroySwapchainKHR", &wine_vkDestroySwapchainKHR}, {"vkDeviceWaitIdle", &wine_vkDeviceWaitIdle}, {"vkEndCommandBuffer", &wine_vkEndCommandBuffer}, {"vkFlushMappedMemoryRanges", &wine_vkFlushMappedMemoryRanges}, @@ -1001,10 +1004,12 @@ static const struct vulkan_func vk_device_dispatch_table[] = {"vkGetPipelineCacheData", &wine_vkGetPipelineCacheData}, {"vkGetQueryPoolResults", &wine_vkGetQueryPoolResults}, {"vkGetRenderAreaGranularity", &wine_vkGetRenderAreaGranularity}, + {"vkGetSwapchainImagesKHR", &wine_vkGetSwapchainImagesKHR}, {"vkInvalidateMappedMemoryRanges", &wine_vkInvalidateMappedMemoryRanges}, {"vkMapMemory", &wine_vkMapMemory}, {"vkMergePipelineCaches", &wine_vkMergePipelineCaches}, {"vkQueueBindSparse", &wine_vkQueueBindSparse}, + {"vkQueuePresentKHR", &wine_vkQueuePresentKHR}, {"vkQueueSubmit", &wine_vkQueueSubmit}, {"vkQueueWaitIdle", &wine_vkQueueWaitIdle}, {"vkResetCommandBuffer", &wine_vkResetCommandBuffer}, @@ -1021,7 +1026,9 @@ static const struct vulkan_func vk_device_dispatch_table[] = static const struct vulkan_func vk_instance_dispatch_table[] = { {"vkCreateDevice", &wine_vkCreateDevice}, + {"vkCreateWin32SurfaceKHR", &wine_vkCreateWin32SurfaceKHR}, {"vkDestroyInstance", &wine_vkDestroyInstance}, + {"vkDestroySurfaceKHR", &wine_vkDestroySurfaceKHR}, {"vkEnumerateDeviceExtensionProperties", &wine_vkEnumerateDeviceExtensionProperties}, {"vkEnumerateDeviceLayerProperties", &wine_vkEnumerateDeviceLayerProperties}, {"vkEnumeratePhysicalDevices", &wine_vkEnumeratePhysicalDevices}, @@ -1032,6 +1039,11 @@ static const struct vulkan_func vk_instance_dispatch_table[] = {"vkGetPhysicalDeviceProperties", &wine_vkGetPhysicalDeviceProperties}, {"vkGetPhysicalDeviceQueueFamilyProperties", &wine_vkGetPhysicalDeviceQueueFamilyProperties}, {"vkGetPhysicalDeviceSparseImageFormatProperties", &wine_vkGetPhysicalDeviceSparseImageFormatProperties}, + {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", &wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR}, + {"vkGetPhysicalDeviceSurfaceFormatsKHR", &wine_vkGetPhysicalDeviceSurfaceFormatsKHR}, + {"vkGetPhysicalDeviceSurfacePresentModesKHR", &wine_vkGetPhysicalDeviceSurfacePresentModesKHR}, + {"vkGetPhysicalDeviceSurfaceSupportKHR", &wine_vkGetPhysicalDeviceSurfaceSupportKHR}, + {"vkGetPhysicalDeviceWin32PresentationSupportKHR", &wine_vkGetPhysicalDeviceWin32PresentationSupportKHR}, };
void *wine_vk_get_device_proc_addr(const char *name) diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index daf679b17591..a91612e62b69 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -13,12 +13,46 @@ void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN; void *wine_vk_get_instance_proc_addr(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; VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) DECLSPEC_HIDDEN; +VkResult WINAPI wine_vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) DECLSPEC_HIDDEN; +VkResult WINAPI wine_vkCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) DECLSPEC_HIDDEN; void WINAPI wine_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; +void WINAPI wine_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; +void WINAPI wine_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN; PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *pName) DECLSPEC_HIDDEN; +VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) DECLSPEC_HIDDEN; +VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) DECLSPEC_HIDDEN; +VkResult WINAPI wine_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) DECLSPEC_HIDDEN; +VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32 *pSupported) DECLSPEC_HIDDEN; +VkBool32 WINAPI wine_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) DECLSPEC_HIDDEN; +VkResult WINAPI wine_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) DECLSPEC_HIDDEN; +VkResult WINAPI wine_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) DECLSPEC_HIDDEN; + +typedef struct VkSwapchainCreateInfoKHR_host +{ + VkStructureType sType; + const void *pNext; + VkSwapchainCreateFlagsKHR flags; + VkSurfaceKHR surface; + uint32_t minImageCount; + VkFormat imageFormat; + VkColorSpaceKHR imageColorSpace; + VkExtent2D imageExtent; + uint32_t imageArrayLayers; + VkImageUsageFlags imageUsage; + VkSharingMode imageSharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t *pQueueFamilyIndices; + VkSurfaceTransformFlagBitsKHR preTransform; + VkCompositeAlphaFlagBitsKHR compositeAlpha; + VkPresentModeKHR presentMode; + VkBool32 clipped; + VkSwapchainKHR oldSwapchain; +} VkSwapchainCreateInfoKHR_host;
typedef struct VkImageFormatProperties_host { diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index c99ca66168e0..fe50d666abef 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -27,6 +27,10 @@
#include "wine/debug.h" #include "wine/library.h" + +/* We only want host compatible structures and don't need alignment. */ +#define WINE_VK_ALIGN(x) + #include "wine/vulkan.h" #include "wine/vulkan_driver.h"
@@ -34,11 +38,22 @@
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
+#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#endif + static VkResult (*pvkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); static void (*pvkDestroyInstance)(VkInstance, const VkAllocationCallbacks *); static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *); static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *);
+/* TODO: dynamically generate based on host driver capabilities. */ +static const struct VkExtensionProperties winex11_vk_instance_extensions[] = +{ + { "VK_KHR_surface", 1 }, + { "VK_KHR_win32_surface", 1}, +}; + static BOOL wine_vk_init(void) { static BOOL init_done = FALSE; @@ -59,6 +74,16 @@ LOAD_FUNCPTR(vkGetInstanceProcAddr) return TRUE; }
+static VkResult X11DRV_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, + uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *index) +{ + FIXME("stub: %p, 0x%s, 0x%s, 0x%s, 0x%s, %p\n", device, + wine_dbgstr_longlong(swapchain), wine_dbgstr_longlong(timeout), + wine_dbgstr_longlong(semaphore), wine_dbgstr_longlong(fence), index); + + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + static VkResult X11DRV_vkCreateInstance(const VkInstanceCreateInfo *create_info, const VkAllocationCallbacks *allocator, VkInstance *instance) { @@ -77,6 +102,22 @@ static VkResult X11DRV_vkCreateInstance(const VkInstanceCreateInfo *create_info, return pvkCreateInstance(create_info, NULL /* allocator */, instance); }
+static VkResult X11DRV_vkCreateSwapchainKHR(VkDevice device, + const VkSwapchainCreateInfoKHR *create_info, + const VkAllocationCallbacks *allocator, VkSwapchainKHR *swapchain) +{ + FIXME("stub: %p %p %p %p\n", device, create_info, allocator, swapchain); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance, + const VkWin32SurfaceCreateInfoKHR *create_info, + const VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) +{ + FIXME("stub: %p %p %p %p\n", instance, create_info, allocator, surface); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + static void X11DRV_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *allocator) { TRACE("%p %p\n", instance, allocator); @@ -87,10 +128,25 @@ static void X11DRV_vkDestroyInstance(VkInstance instance, const VkAllocationCall pvkDestroyInstance(instance, NULL /* allocator */); }
+static void X11DRV_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, + const VkAllocationCallbacks *allocator) +{ + FIXME("stub: %p 0x%s %p\n", instance, wine_dbgstr_longlong(surface), allocator); +} + +static void X11DRV_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, + const VkAllocationCallbacks *allocator) +{ + FIXME("stub: %p, 0x%s %p\n", device, wine_dbgstr_longlong(swapchain), allocator); +} + static VkResult X11DRV_vkEnumerateInstanceExtensionProperties(const char *layer_name, uint32_t *count, VkExtensionProperties* properties) { - TRACE("layer_name %s, count %p, properties %p\n", debugstr_a(layer_name), count, properties); + VkResult res; + unsigned int i, num_copies; + + TRACE("layer_name %p, count %p, properties %p\n", debugstr_a(layer_name), count, properties);
/* This shouldn't get called with layer_name set, the ICD loader prevents it. */ if (layer_name) @@ -106,16 +162,32 @@ 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 = 0; + *count = ARRAY_SIZE(winex11_vk_instance_extensions); return VK_SUCCESS; }
- /* When properties is not NULL, we copy the extensions over and set count - * to the number of copied extensions. For now we don't have much to do as - * we don't support any extensions yet. - */ - *count = 0; - return VK_SUCCESS; + if (*count < ARRAY_SIZE(winex11_vk_instance_extensions)) + { + /* Incomplete is a type of success used to signal the application + * that not all devices got copied. + */ + num_copies = *count; + res = VK_INCOMPLETE; + } + else + { + num_copies = ARRAY_SIZE(winex11_vk_instance_extensions); + res = VK_SUCCESS; + } + + for (i = 0; i < num_copies; i++) + { + memcpy(&properties[i], &winex11_vk_instance_extensions[i], sizeof(winex11_vk_instance_extensions[i])); + } + *count = num_copies; + + TRACE("Result %d, extensions copied %u\n", res, num_copies); + return res; }
static void * X11DRV_vkGetDeviceProcAddr(VkDevice device, const char *name) @@ -130,13 +202,74 @@ static void * X11DRV_vkGetInstanceProcAddr(VkInstance instance, const char *name return pvkGetInstanceProcAddr(instance, name); }
+static VkResult X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *capabilities) +{ + FIXME("stub: %p, 0x%s, %p\n", phys_dev, wine_dbgstr_longlong(surface), capabilities); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult X11DRV_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, uint32_t *count, VkSurfaceFormatKHR *formats) +{ + FIXME("stub: %p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), count, formats); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult X11DRV_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, uint32_t *count, VkPresentModeKHR *modes) +{ + FIXME("stub: %p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), count, modes); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult X11DRV_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice phys_dev, + uint32_t index, VkSurfaceKHR surface, VkBool32 *supported) +{ + FIXME("stub: %p, %u, 0x%s, %p\n", phys_dev, index, wine_dbgstr_longlong(surface), supported); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkBool32 X11DRV_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev, + uint32_t index) +{ + FIXME("stub %p %u\n", phys_dev, index); + return VK_FALSE; +} + +static VkResult X11DRV_vkGetSwapchainImagesKHR(VkDevice device, + VkSwapchainKHR swapchain, uint32_t *count, VkImage *images) +{ + FIXME("stub: %p, 0x%s %p %p\n", device, wine_dbgstr_longlong(swapchain), count, images); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult X11DRV_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *present_info) +{ + FIXME("stub: %p, %p\n", queue, present_info); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + + static const struct vulkan_funcs vulkan_funcs = { + X11DRV_vkAcquireNextImageKHR, X11DRV_vkCreateInstance, + X11DRV_vkCreateSwapchainKHR, + X11DRV_vkCreateWin32SurfaceKHR, X11DRV_vkDestroyInstance, + X11DRV_vkDestroySurfaceKHR, + X11DRV_vkDestroySwapchainKHR, X11DRV_vkEnumerateInstanceExtensionProperties, X11DRV_vkGetDeviceProcAddr, - X11DRV_vkGetInstanceProcAddr + X11DRV_vkGetInstanceProcAddr, + X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR, + X11DRV_vkGetPhysicalDeviceSurfaceFormatsKHR, + X11DRV_vkGetPhysicalDeviceSurfacePresentModesKHR, + X11DRV_vkGetPhysicalDeviceSurfaceSupportKHR, + X11DRV_vkGetPhysicalDeviceWin32PresentationSupportKHR, + X11DRV_vkGetSwapchainImagesKHR, + X11DRV_vkQueuePresentKHR };
const struct vulkan_funcs *get_vulkan_driver(UINT version) diff --git a/include/wine/vulkan.h b/include/wine/vulkan.h index fb0af61eb582..92dcb7d2b342 100644 --- a/include/wine/vulkan.h +++ b/include/wine/vulkan.h @@ -75,6 +75,8 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR)
typedef uint32_t VkBool32; typedef uint64_t VkDeviceSize; @@ -291,6 +293,12 @@ typedef enum VkColorComponentFlagBits VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7fffffff, } VkColorComponentFlagBits;
+typedef enum VkColorSpaceKHR +{ + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, + VK_COLOR_SPACE_KHR_MAX_ENUM = 0x7fffffff, +} VkColorSpaceKHR; + typedef enum VkCommandBufferLevel { VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, @@ -338,6 +346,15 @@ typedef enum VkComponentSwizzle VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7fffffff, } VkComponentSwizzle;
+typedef enum VkCompositeAlphaFlagBitsKHR +{ + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008, + VK_COMPOSITE_ALPHA_FLAG_BITS_KHR_MAX_ENUM = 0x7fffffff, +} VkCompositeAlphaFlagBitsKHR; + typedef enum VkCullModeFlagBits { VK_CULL_MODE_NONE = 0, @@ -652,6 +669,7 @@ typedef enum VkImageLayout VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, VK_IMAGE_LAYOUT_PREINITIALIZED = 8, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, VK_IMAGE_LAYOUT_MAX_ENUM = 0x7fffffff, } VkImageLayout;
@@ -773,6 +791,8 @@ typedef enum VkObjectType VK_OBJECT_TYPE_DESCRIPTOR_SET = 23, VK_OBJECT_TYPE_FRAMEBUFFER = 24, VK_OBJECT_TYPE_COMMAND_POOL = 25, + VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, + VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, VK_OBJECT_TYPE_MAX_ENUM = 0x7fffffff, } VkObjectType;
@@ -837,6 +857,15 @@ typedef enum VkPolygonMode VK_POLYGON_MODE_MAX_ENUM = 0x7fffffff, } VkPolygonMode;
+typedef enum VkPresentModeKHR +{ + VK_PRESENT_MODE_IMMEDIATE_KHR = 0, + VK_PRESENT_MODE_MAILBOX_KHR = 1, + VK_PRESENT_MODE_FIFO_KHR = 2, + VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, + VK_PRESENT_MODE_KHR_MAX_ENUM = 0x7fffffff, +} VkPresentModeKHR; + typedef enum VkPrimitiveTopology { VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0, @@ -894,6 +923,9 @@ typedef enum VkQueueFlagBits
typedef enum VkResult { + VK_ERROR_OUT_OF_DATE_KHR = -1000001004, + VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, + VK_ERROR_SURFACE_LOST_KHR = -1000000000, VK_ERROR_FRAGMENTED_POOL = -12, VK_ERROR_FORMAT_NOT_SUPPORTED = -11, VK_ERROR_TOO_MANY_OBJECTS = -10, @@ -912,6 +944,7 @@ typedef enum VkResult VK_EVENT_SET = 3, VK_EVENT_RESET = 4, VK_INCOMPLETE = 5, + VK_SUBOPTIMAL_KHR = 1000001003, VK_RESULT_MAX_ENUM = 0x7fffffff, } VkResult;
@@ -1041,6 +1074,9 @@ typedef enum VkStructureType VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46, VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47, VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48, + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7fffffff, } VkStructureType;
@@ -1056,6 +1092,25 @@ typedef enum VkSubpassDescriptionFlagBits VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7fffffff, } VkSubpassDescriptionFlagBits;
+typedef enum VkSurfaceTransformFlagBitsKHR +{ + VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001, + VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002, + VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004, + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080, + VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, + VK_SURFACE_TRANSFORM_FLAG_BITS_KHR_MAX_ENUM = 0x7fffffff, +} VkSurfaceTransformFlagBitsKHR; + +typedef enum VkSwapchainCreateFlagBitsKHR +{ + VK_SWAPCHAIN_CREATE_FLAG_BITS_KHR_MAX_ENUM = 0x7fffffff, +} VkSwapchainCreateFlagBitsKHR; + typedef enum VkSystemAllocationScope { VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0, @@ -1439,6 +1494,18 @@ typedef struct VkPipelineTessellationStateCreateInfo uint32_t patchControlPoints; } VkPipelineTessellationStateCreateInfo;
+typedef struct VkPresentInfoKHR +{ + VkStructureType sType; + const void *pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore *pWaitSemaphores; + uint32_t swapchainCount; + const VkSwapchainKHR *pSwapchains; + const uint32_t *pImageIndices; + VkResult *pResults; +} VkPresentInfoKHR; + typedef struct VkQueryPoolCreateInfo { VkStructureType sType; @@ -1745,6 +1812,12 @@ typedef struct VkSubpassDependency VkDependencyFlags dependencyFlags; } VkSubpassDependency;
+typedef struct VkSurfaceFormatKHR +{ + VkFormat format; + VkColorSpaceKHR colorSpace; +} VkSurfaceFormatKHR; + typedef struct VkViewport { float x; @@ -1901,6 +1974,28 @@ typedef struct VkSubpassDescription const uint32_t *pPreserveAttachments; } VkSubpassDescription;
+typedef struct VkSwapchainCreateInfoKHR +{ + VkStructureType sType; + const void *pNext; + VkSwapchainCreateFlagsKHR flags; + VkSurfaceKHR WINE_VK_ALIGN(8) surface; + uint32_t minImageCount; + VkFormat imageFormat; + VkColorSpaceKHR imageColorSpace; + VkExtent2D imageExtent; + uint32_t imageArrayLayers; + VkImageUsageFlags imageUsage; + VkSharingMode imageSharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t *pQueueFamilyIndices; + VkSurfaceTransformFlagBitsKHR preTransform; + VkCompositeAlphaFlagBitsKHR compositeAlpha; + VkPresentModeKHR presentMode; + VkBool32 clipped; + VkSwapchainKHR WINE_VK_ALIGN(8) oldSwapchain; +} VkSwapchainCreateInfoKHR; + typedef struct VkClearAttachment { VkImageAspectFlags aspectMask; @@ -1987,6 +2082,29 @@ typedef struct VkRenderPassBeginInfo const VkClearValue *pClearValues; } VkRenderPassBeginInfo;
+typedef struct VkSurfaceCapabilitiesKHR +{ + uint32_t minImageCount; + uint32_t maxImageCount; + VkExtent2D currentExtent; + VkExtent2D minImageExtent; + VkExtent2D maxImageExtent; + uint32_t maxImageArrayLayers; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkSurfaceTransformFlagBitsKHR currentTransform; + VkCompositeAlphaFlagsKHR supportedCompositeAlpha; + VkImageUsageFlags supportedUsageFlags; +} VkSurfaceCapabilitiesKHR; + +typedef struct VkWin32SurfaceCreateInfoKHR +{ + VkStructureType sType; + const void *pNext; + VkWin32SurfaceCreateFlagsKHR flags; + HINSTANCE hinstance; + HWND hwnd; +} VkWin32SurfaceCreateInfoKHR; + typedef struct VkBindSparseInfo { VkStructureType sType; @@ -2282,6 +2400,7 @@ typedef struct VkGraphicsPipelineCreateInfo int32_t basePipelineIndex; } VkGraphicsPipelineCreateInfo;
+VkResult VKAPI_CALL vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex); VkResult VKAPI_CALL vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers); VkResult VKAPI_CALL vkAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets); VkResult VKAPI_CALL vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory); @@ -2353,6 +2472,8 @@ VkResult VKAPI_CALL vkCreateRenderPass(VkDevice device, const VkRenderPassCreate VkResult VKAPI_CALL vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSampler *pSampler); VkResult VKAPI_CALL vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore); VkResult VKAPI_CALL vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule); +VkResult VKAPI_CALL vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain); +VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface); void VKAPI_CALL vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator); void VKAPI_CALL vkDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator); void VKAPI_CALL vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator); @@ -2373,6 +2494,8 @@ void VKAPI_CALL vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, co void VKAPI_CALL vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator); void VKAPI_CALL vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator); void VKAPI_CALL vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks *pAllocator); +void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator); +void VKAPI_CALL vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator); VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device); VkResult VKAPI_CALL vkEndCommandBuffer(VkCommandBuffer commandBuffer); VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties); @@ -2401,13 +2524,20 @@ void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDev void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties); void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties); void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t *pPropertyCount, VkSparseImageFormatProperties *pProperties); +VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities); +VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats); +VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes); +VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32 *pSupported); +VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); VkResult VKAPI_CALL vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, void *pData); VkResult VKAPI_CALL vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags); void VKAPI_CALL vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D *pGranularity); +VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages); VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges); VkResult VKAPI_CALL vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData); VkResult VKAPI_CALL vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches); VkResult VKAPI_CALL vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence); +VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo); VkResult VKAPI_CALL vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence); VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue); VkResult VKAPI_CALL vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index 8d69222e03c4..60d16dd52a24 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -4,7 +4,7 @@ #define __WINE_VULKAN_DRIVER_H
/* Wine internal vulkan driver version, needs to be bumped upon vulkan_funcs changes. */ -#define WINE_VULKAN_DRIVER_VERSION 2 +#define WINE_VULKAN_DRIVER_VERSION 3
struct vulkan_funcs { @@ -12,11 +12,23 @@ struct vulkan_funcs * needs to provide. Other function calls will be provided indirectly by dispatch * tables part of dispatchable Vulkan objects such as VkInstance or vkDevice. */ + VkResult (*p_vkAcquireNextImageKHR)(VkDevice, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t *); VkResult (*p_vkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); + VkResult (*p_vkCreateSwapchainKHR)(VkDevice, const VkSwapchainCreateInfoKHR *, const VkAllocationCallbacks *, VkSwapchainKHR *); + VkResult (*p_vkCreateWin32SurfaceKHR)(VkInstance, const VkWin32SurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *); void (*p_vkDestroyInstance)(VkInstance, const VkAllocationCallbacks *); + void (*p_vkDestroySurfaceKHR)(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks *); + void (*p_vkDestroySwapchainKHR)(VkDevice, VkSwapchainKHR, const VkAllocationCallbacks *); VkResult (*p_vkEnumerateInstanceExtensionProperties)(const char *, uint32_t *, VkExtensionProperties *); void * (*p_vkGetDeviceProcAddr)(VkDevice, const char *); void * (*p_vkGetInstanceProcAddr)(VkInstance, const char *); + VkResult (*p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *); + VkResult (*p_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *); + VkResult (*p_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *); + VkResult (*p_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *); + VkBool32 (*p_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice, uint32_t); + VkResult (*p_vkGetSwapchainImagesKHR)(VkDevice, VkSwapchainKHR, uint32_t *, VkImage *); + VkResult (*p_vkQueuePresentKHR)(VkQueue, const VkPresentInfoKHR *); };
extern const struct vulkan_funcs * CDECL __wine_get_vulkan_driver(HDC hdc, UINT version);
From: Roderick Colenbrander thunderbird2k@gmail.com
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
Version 2: Fix subject.
--- dlls/winevulkan/vulkan.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 61af8df8b848..fe1f85121fc3 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -38,6 +38,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan); */ #define WINE_VULKAN_ICD_VERSION 4
+/* All Vulkan structures use this structure for the first elements. */ +struct wine_vk_structure_header +{ + VkStructureType sType; + const void *pNext; +}; + static void *wine_vk_get_global_proc_addr(const char *name);
static const struct vulkan_funcs *vk_funcs = NULL; @@ -74,6 +81,58 @@ static BOOL wine_vk_init(void) return TRUE; }
+/* Helper function for converting between win32 and host compatible VkInstanceCreateInfo. + * This function takes care of extensions handled at winevulkan layer, a Wine graphics + * driver is responsible for handling e.g. surface extensions. + */ +static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, + VkInstanceCreateInfo *dst) +{ + dst->sType = src->sType; + dst->flags = src->flags; + dst->pApplicationInfo = src->pApplicationInfo; + + /* Application and loader can pass in a chain of extensions through pNext. + * We can't blindy pass these through as often these contain callbacks or + * they can even be pass structures for loader / ICD internal use. For now + * we ignore everything in pNext chain, but we print FIXMEs. + */ + if (src->pNext) + { + const struct wine_vk_structure_header *header; + + for (header = src->pNext; header; header = header->pNext) + { + switch (header->sType) + { + case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO: + /* Can be used to register new dispatchable object types + * to the loader. We should ignore it as it will confuse the + * host its loader. + */ + break; + + default: + FIXME("Application requested a linked structure of type %d\n", header->sType); + } + } + } + /* For now don't support anything. */ + dst->pNext = NULL; + + /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader + * filter this data out as well. + */ + dst->enabledLayerCount = 0; + dst->ppEnabledLayerNames = NULL; + + /* TODO: convert non-WSI win32 extensions here to host specific ones. */ + dst->ppEnabledExtensionNames = src->ppEnabledExtensionNames; + dst->enabledExtensionCount = src->enabledExtensionCount; + + return VK_SUCCESS; +} + /* Helper function which stores wrapped physical devices in the instance object. */ static VkResult wine_vk_instance_load_physical_devices(struct VkInstance_T *instance) { @@ -229,6 +288,7 @@ static VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_ const VkAllocationCallbacks *allocator, VkInstance *instance) { struct VkInstance_T *object = NULL; + VkInstanceCreateInfo create_info_host; VkResult res;
TRACE("create_info %p, allocator %p, instance %p\n", create_info, allocator, instance); @@ -245,7 +305,14 @@ static VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_ } object->base.loader_magic = VULKAN_ICD_MAGIC_VALUE;
- res = vk_funcs->p_vkCreateInstance(create_info, NULL /* allocator */, &object->instance); + res = wine_vk_instance_convert_create_info(create_info, &create_info_host); + if (res != VK_SUCCESS) + { + ERR("Failed to convert instance create info, res=%d\n", res); + goto err; + } + + res = vk_funcs->p_vkCreateInstance(&create_info_host, NULL /* allocator */, &object->instance); if (res != VK_SUCCESS) { ERR("Failed to create instance, res=%d\n", res);
From: Roderick Colenbrander thunderbird2k@gmail.com
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
Version 2: Remove redundant cast.
--- dlls/winex11.drv/vulkan.c | 68 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-)
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index fe50d666abef..11d9f61b91f0 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -26,6 +26,7 @@ #include "winbase.h"
#include "wine/debug.h" +#include "wine/heap.h" #include "wine/library.h"
/* We only want host compatible structures and don't need alignment. */ @@ -74,6 +75,54 @@ LOAD_FUNCPTR(vkGetInstanceProcAddr) return TRUE; }
+/* Helper function for converting between win32 and X11 compatible VkInstanceCreateInfo. + * Caller is responsible for allocation and cleanup of 'dst'. + */ +static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, + VkInstanceCreateInfo *dst) +{ + unsigned int i; + const char **enabled_extensions = NULL; + + dst->sType = src->sType; + dst->flags = src->flags; + dst->pApplicationInfo = src->pApplicationInfo; + dst->pNext = src->pNext; + dst->enabledLayerCount = 0; + dst->ppEnabledLayerNames = NULL; + dst->enabledExtensionCount = 0; + dst->ppEnabledExtensionNames = NULL; + + if (src->enabledExtensionCount > 0) + { + enabled_extensions = heap_calloc(src->enabledExtensionCount, sizeof(*src->ppEnabledExtensionNames)); + if (!enabled_extensions) + { + ERR("Failed to allocate memory for enabled extensions\n"); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + for (i = 0; i < src->enabledExtensionCount; i++) + { + /* Substitute extension with X11 ones else copy. Long-term, when we + * support more extensions, we should store these in a list. + */ + if (!strcmp(src->ppEnabledExtensionNames[i], "VK_KHR_win32_surface")) + { + enabled_extensions[i] = "VK_KHR_xlib_surface"; + } + else + { + enabled_extensions[i] = src->ppEnabledExtensionNames[i]; + } + } + dst->ppEnabledExtensionNames = enabled_extensions; + dst->enabledExtensionCount = src->enabledExtensionCount; + } + + return VK_SUCCESS; +} + static VkResult X11DRV_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *index) { @@ -87,19 +136,28 @@ static VkResult X11DRV_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swa static VkResult X11DRV_vkCreateInstance(const VkInstanceCreateInfo *create_info, const VkAllocationCallbacks *allocator, VkInstance *instance) { + VkInstanceCreateInfo create_info_host; + VkResult res; TRACE("create_info %p, allocator %p, instance %p\n", create_info, allocator, instance);
if (allocator) FIXME("Support for allocation callbacks not implemented yet\n");
- /* TODO: convert win32 to x11 extensions here. */ - if (create_info->enabledExtensionCount > 0) + /* Perform a second pass on converting VkInstanceCreateInfo. Winevulkan + * performed a first pass in which it handles everything except for WSI + * functionality such as VK_KHR_win32_surface. Handle this now. + */ + res = wine_vk_instance_convert_create_info(create_info, &create_info_host); + if (res != VK_SUCCESS) { - FIXME("Extensions are not supported yet, aborting!\n"); - return VK_ERROR_INCOMPATIBLE_DRIVER; + ERR("Failed to convert instance create info, res=%d\n", res); + return res; }
- return pvkCreateInstance(create_info, NULL /* allocator */, instance); + res = pvkCreateInstance(&create_info_host, NULL /* allocator */, instance); + + heap_free((void *)create_info_host.ppEnabledExtensionNames); + return res; }
static VkResult X11DRV_vkCreateSwapchainKHR(VkDevice device,