diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index 04896daafb8fa67f6135b0a166fc204d7916c503..5fff3f1511a125b3db76399e9c41ee72364f8dfa 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 678506fbb0e5e372455c03a75f003f82d579bf57..61af8df8b84885473255ffc937ecee173e6af38e 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 3670926c3edf5d49e4b528529d0349abb4878102..5d9826cd675666e315ab7786b12bf51b23c7a6e9 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 daf679b1759127b1f4bad10cce77199f7887b7bf..a91612e62b698e2d7bc6d5ac75ead4bf47e74f5b 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 c99ca66168e0cc8942947305ffb4a7b003eccd00..fe50d666abeff550cdf990f111b36345e3982abe 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 fb0af61eb582c4d0402a96af445aa421b742c8e4..92dcb7d2b3420fea59e10870f2687cf54a298e9d 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 8d69222e03c46f1a26a1eba97c0d84485891e81c..60d16dd52a24a8a014f819da81486f6562956d51 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);