For D3DKMT usage and timeline semaphore rewinding / shared fences.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 194 +++++++++++++++++++++++ dlls/winevulkan/loader.c | 10 +- dlls/winevulkan/loader_thunks.h | 1 - dlls/winevulkan/make_vulkan | 12 +- dlls/winevulkan/vulkan.c | 264 +------------------------------ dlls/winevulkan/vulkan_private.h | 18 --- dlls/winevulkan/vulkan_thunks.c | 17 +- dlls/winevulkan/vulkan_thunks.h | 4 - include/wine/vulkan_driver.h | 42 +++-- 9 files changed, 245 insertions(+), 317 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index f4310089f70..80a7eae4855 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -307,6 +307,196 @@ static HANDLE open_shared_resource_from_name( const WCHAR *name ) return open_name.hNtHandle; }
+static VkResult convert_device_create_info( struct vulkan_physical_device *physical_device, VkDeviceCreateInfo *info, + struct mempool *pool, struct vulkan_device *device ) +{ + struct vulkan_instance *instance = physical_device->instance; + const char **extensions; + uint32_t count = 0; + + /* Should be filtered out by loader as ICDs don't support layers. */ + info->enabledLayerCount = 0; + info->ppEnabledLayerNames = NULL; + + if (device->extensions.has_VK_KHR_win32_keyed_mutex) + device->extensions.has_VK_KHR_timeline_semaphore = 1; + + driver_funcs->p_map_device_extensions( &device->extensions ); + device->extensions.has_VK_KHR_win32_keyed_mutex = 0; + device->extensions.has_VK_KHR_external_memory_win32 = 0; + device->extensions.has_VK_KHR_external_fence_win32 = 0; + device->extensions.has_VK_KHR_external_semaphore_win32 = 0; + + if (device->extensions.has_VK_EXT_external_memory_dma_buf) + device->extensions.has_VK_KHR_external_memory_fd = 1; + + if (physical_device->map_placed_align) + { + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *map_placed_features; + + if (!(map_placed_features = mem_alloc( pool, sizeof(*map_placed_features) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; + map_placed_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT; + map_placed_features->pNext = (void *)info->pNext; + map_placed_features->memoryMapPlaced = VK_TRUE; + map_placed_features->memoryMapRangePlaced = VK_FALSE; + map_placed_features->memoryUnmapReserve = VK_TRUE; + info->pNext = map_placed_features; + + device->extensions.has_VK_EXT_map_memory_placed = 1; + device->extensions.has_VK_KHR_map_memory2 = 1; + } + else if (physical_device->external_memory_align) + { + device->extensions.has_VK_KHR_external_memory = 1; + device->extensions.has_VK_EXT_external_memory_host = 1; + } + + /* win32u uses VkSwapchainPresentScalingCreateInfoEXT if available. */ + if (device->extensions.has_VK_KHR_swapchain && instance->extensions.has_VK_EXT_surface_maintenance1 && + physical_device->extensions.has_VK_EXT_swapchain_maintenance1) + device->extensions.has_VK_EXT_swapchain_maintenance1 = 1; + + if (!(extensions = mem_alloc( pool, sizeof(device->extensions) * 8 * sizeof(*extensions) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; +#define USE_VK_EXT(x) if (device->extensions.has_ ## x) extensions[count++] = #x; + ALL_VK_DEVICE_EXTS +#undef USE_VK_EXT + + TRACE( "Enabling %u host device extensions\n", count ); + for (const char **extension = extensions, **end = extension + count; extension < end; extension++) + TRACE( " - %s\n", debugstr_a(*extension) ); + + info->ppEnabledExtensionNames = extensions; + info->enabledExtensionCount = count; + return VK_SUCCESS; +} + +static void init_device_queues( struct vulkan_device *device, const VkDeviceQueueCreateInfo *create_info, VkDevice client_device ) +{ + VkDeviceQueueInfo2 info = {.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2}; + VkQueue client_queues = client_device->queues + device->queue_count; + struct vulkan_queue *queues = device->queues + device->queue_count; + + TRACE( "Queue family index %u, queue count %u.\n", create_info->queueFamilyIndex, create_info->queueCount ); + + info.flags = create_info->flags; + info.queueFamilyIndex = create_info->queueFamilyIndex; + for (info.queueIndex = 0; info.queueIndex < create_info->queueCount; info.queueIndex++) + { + VkQueue host_queue, client_queue = client_queues + info.queueIndex; + struct vulkan_queue *queue = queues + info.queueIndex; + + if (info.flags && device->p_vkGetDeviceQueue2) device->p_vkGetDeviceQueue2( device->host.device, &info, &host_queue ); + else device->p_vkGetDeviceQueue( device->host.device, info.queueFamilyIndex, info.queueIndex, &host_queue ); + vulkan_object_init_ptr( &queue->obj, (UINT_PTR)host_queue, &client_queue->obj ); + queue->device = device; + queue->info = info; + + TRACE( "Got device %p queue %p, host_queue %p.\n", device, queue, queue->host.queue ); + } + + device->queue_count += create_info->queueCount; +} + +static VkResult win32u_vkCreateDevice( VkPhysicalDevice client_physical_device, const VkDeviceCreateInfo *client_create_info, + const VkAllocationCallbacks *allocator, VkDevice *client_device_ptr ) +{ + VkDeviceCreateInfo *create_info = (VkDeviceCreateInfo *)client_create_info; /* cast away const, chain has been copied in the thunks */ + struct vulkan_physical_device *physical_device = vulkan_physical_device_from_handle( client_physical_device ); + struct vulkan_instance *instance = physical_device->instance; + VkDevice host_device, client_device = *client_device_ptr; + struct vulkan_device *device; + unsigned int queue_count, i; + struct mempool pool = {0}; + VkResult res; + + if (TRACE_ON(vulkan)) + { + VkPhysicalDeviceProperties properties = {0}; + instance->p_vkGetPhysicalDeviceProperties( physical_device->host.physical_device, &properties ); + TRACE( "Device name: %s.\n", debugstr_a(properties.deviceName) ); + TRACE( "Vendor ID: %#x, Device ID: %#x.\n", properties.vendorID, properties.deviceID ); + TRACE( "Driver version: %#x.\n", properties.driverVersion ); + } + + /* We need to cache all queues within the device as each requires wrapping since queues are dispatchable objects. */ + for (queue_count = 0, i = 0; i < create_info->queueCreateInfoCount; i++) queue_count += create_info->pQueueCreateInfos[i].queueCount; + + if (!(device = calloc( 1, offsetof(struct vulkan_device, queues[queue_count]) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; + device->extensions = client_device->extensions; + + if ((res = convert_device_create_info( physical_device, create_info, &pool, device ))) goto failed; + if ((res = instance->p_vkCreateDevice( physical_device->host.physical_device, create_info, NULL /* allocator */, &host_device ))) goto failed; + + vulkan_object_init_ptr( &device->obj, (UINT_PTR)host_device, &client_device->obj ); + device->physical_device = physical_device; + +#define USE_VK_FUNC( name ) \ + device->p_##name = (void *)p_vkGetDeviceProcAddr( device->host.device, #name ); \ + if (!device->p_##name) TRACE( "Device proc %s not found.\n", #name ); + ALL_VK_DEVICE_FUNCS +#undef USE_VK_FUNC + + for (i = 0; i < create_info->queueCreateInfoCount; i++) init_device_queues( device, create_info->pQueueCreateInfos + i, client_device ); + + TRACE( "Created device %p, host_device %p.\n", device, device->host.device ); + for (struct vulkan_queue *queue = device->queues; queue < device->queues + device->queue_count; queue++) + instance->p_insert_object( instance, &queue->obj ); + instance->p_insert_object( instance, &device->obj ); + +failed: + if (res) + { + WARN( "Failed to create device, res %d\n", res ); + free( device ); + } + mem_free( &pool ); + return res; +} + +static void win32u_vkDestroyDevice( VkDevice client_device, const VkAllocationCallbacks *allocator ) +{ + struct vulkan_device *device = vulkan_device_from_handle( client_device ); + struct vulkan_instance *instance = device->physical_device->instance; + unsigned int i; + + if (!device) return; + + device->p_vkDestroyDevice( device->host.device, NULL /* pAllocator */ ); + for (i = 0; i < device->queue_count; i++) + instance->p_remove_object( instance, &device->queues[i].obj ); + instance->p_remove_object( instance, &device->obj ); + + free( device ); +} + +static VkQueue device_find_queue( VkDevice client_device, const VkDeviceQueueInfo2 *info ) +{ + struct vulkan_device *device = vulkan_device_from_handle( client_device ); + + for (struct vulkan_queue *queue = device->queues; queue < device->queues + device->queue_count; queue++) + if (!memcmp( &queue->info, info, sizeof(*info) )) return queue->client.queue; + + return VK_NULL_HANDLE; +} + +static void win32u_vkGetDeviceQueue( VkDevice client_device, uint32_t family_index, uint32_t queue_index, VkQueue *client_queue ) +{ + VkDeviceQueueInfo2 info = {.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2}; + info.queueFamilyIndex = family_index; + info.queueIndex = queue_index; + + *client_queue = device_find_queue( client_device, &info ); +} + +static void win32u_vkGetDeviceQueue2( VkDevice client_device, const VkDeviceQueueInfo2 *client_info, VkQueue *client_queue ) +{ + VkDeviceQueueInfo2 info = *client_info; + if (info.pNext) FIXME( "pNext not implemented\n" ); + info.pNext = NULL; + + *client_queue = device_find_queue( client_device, &info ); +} + static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryAllocateInfo *client_alloc_info, const VkAllocationCallbacks *allocator, VkDeviceMemory *ret ) { @@ -2279,11 +2469,13 @@ static struct vulkan_funcs vulkan_funcs = .p_vkAcquireNextImageKHR = win32u_vkAcquireNextImageKHR, .p_vkAllocateMemory = win32u_vkAllocateMemory, .p_vkCreateBuffer = win32u_vkCreateBuffer, + .p_vkCreateDevice = win32u_vkCreateDevice, .p_vkCreateFence = win32u_vkCreateFence, .p_vkCreateImage = win32u_vkCreateImage, .p_vkCreateSemaphore = win32u_vkCreateSemaphore, .p_vkCreateSwapchainKHR = win32u_vkCreateSwapchainKHR, .p_vkCreateWin32SurfaceKHR = win32u_vkCreateWin32SurfaceKHR, + .p_vkDestroyDevice = win32u_vkDestroyDevice, .p_vkDestroyFence = win32u_vkDestroyFence, .p_vkDestroySemaphore = win32u_vkDestroySemaphore, .p_vkDestroySurfaceKHR = win32u_vkDestroySurfaceKHR, @@ -2292,6 +2484,8 @@ static struct vulkan_funcs vulkan_funcs = .p_vkGetDeviceBufferMemoryRequirements = win32u_vkGetDeviceBufferMemoryRequirements, .p_vkGetDeviceBufferMemoryRequirementsKHR = win32u_vkGetDeviceBufferMemoryRequirements, .p_vkGetDeviceImageMemoryRequirements = win32u_vkGetDeviceImageMemoryRequirements, + .p_vkGetDeviceQueue = win32u_vkGetDeviceQueue, + .p_vkGetDeviceQueue2 = win32u_vkGetDeviceQueue2, .p_vkGetFenceWin32HandleKHR = win32u_vkGetFenceWin32HandleKHR, .p_vkGetMemoryWin32HandleKHR = win32u_vkGetMemoryWin32HandleKHR, .p_vkGetMemoryWin32HandlePropertiesKHR = win32u_vkGetMemoryWin32HandlePropertiesKHR, diff --git a/dlls/winevulkan/loader.c b/dlls/winevulkan/loader.c index 730a2f09647..3e377acd153 100644 --- a/dlls/winevulkan/loader.c +++ b/dlls/winevulkan/loader.c @@ -615,19 +615,23 @@ VkResult WINAPI vkCreateDevice(VkPhysicalDevice physical_device, const VkDeviceC queue_count += create_info->pQueueCreateInfos[i].queueCount; if (!(device = vulkan_client_object_create(FIELD_OFFSET(struct VkDevice_T, queues[queue_count])))) return VK_ERROR_OUT_OF_HOST_MEMORY; - for (i = 0; i < queue_count; i++) - device->queues[i].obj.loader_magic = VULKAN_ICD_MAGIC_VALUE; + for (VkQueue queue = device->queues, end = queue + queue_count; queue < end; queue++) + queue->obj.loader_magic = VULKAN_ICD_MAGIC_VALUE; device->extensions = extensions; + *ret = device;
params.physicalDevice = physical_device; params.pCreateInfo = create_info; params.pAllocator = allocator; params.pDevice = ret; - params.client_ptr = device; + status = UNIX_CALL(vkCreateDevice, ¶ms); assert(!status); if (params.result) + { free(device); + *ret = NULL; + } return params.result; }
diff --git a/dlls/winevulkan/loader_thunks.h b/dlls/winevulkan/loader_thunks.h index 4d14559de9d..a249cd70870 100644 --- a/dlls/winevulkan/loader_thunks.h +++ b/dlls/winevulkan/loader_thunks.h @@ -3203,7 +3203,6 @@ struct vkCreateDevice_params const VkDeviceCreateInfo *pCreateInfo; const VkAllocationCallbacks *pAllocator; VkDevice *pDevice; - void *client_ptr; VkResult result; };
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 577b674f95d..8cb927adece 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -178,10 +178,6 @@ PERF_CRITICAL_FUNCTIONS = [ FUNCTION_OVERRIDES = { # Global functions "vkCreateInstance" : {"extra_param" : "client_ptr"}, - - # Instance functions - "vkCreateDevice" : {"extra_param" : "client_ptr"}, - # Device functions "vkCreateCommandPool" : {"extra_param" : "client_ptr"}, "vkGetDeviceProcAddr" : {"dispatch" : False}, @@ -193,11 +189,13 @@ USER_DRIVER_FUNCS = { "vkAcquireNextImageKHR", "vkAllocateMemory", "vkCreateBuffer", + "vkCreateDevice", "vkCreateFence", "vkCreateImage", "vkCreateSemaphore", "vkCreateSwapchainKHR", "vkCreateWin32SurfaceKHR", + "vkDestroyDevice", "vkDestroyFence", "vkDestroySemaphore", "vkDestroySurfaceKHR", @@ -207,6 +205,8 @@ USER_DRIVER_FUNCS = { "vkGetDeviceBufferMemoryRequirementsKHR", "vkGetDeviceImageMemoryRequirements", "vkGetDeviceProcAddr", + "vkGetDeviceQueue", + "vkGetDeviceQueue2", "vkGetFenceWin32HandleKHR", "vkGetInstanceProcAddr", "vkGetMemoryWin32HandleKHR", @@ -247,13 +247,11 @@ MANUAL_UNIX_THUNKS = { "vkCreateDebugReportCallbackEXT", "vkCreateDebugUtilsMessengerEXT", "vkCreateDeferredOperationKHR", - "vkCreateDevice", "vkCreateInstance", "vkDestroyCommandPool", "vkDestroyDebugReportCallbackEXT", "vkDestroyDebugUtilsMessengerEXT", "vkDestroyDeferredOperationKHR", - "vkDestroyDevice", "vkDestroyInstance", "vkEnumerateDeviceLayerProperties", "vkEnumerateInstanceExtensionProperties", @@ -266,8 +264,6 @@ MANUAL_UNIX_THUNKS = { "vkGetCalibratedTimestampsEXT", "vkGetCalibratedTimestampsKHR", "vkGetDeviceProcAddr", - "vkGetDeviceQueue", - "vkGetDeviceQueue2", "vkGetInstanceProcAddr", "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT", "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR", diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index dd13d38de06..2c47cae3058 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -43,19 +43,6 @@ static struct wine_instance *wine_instance_from_handle(VkInstance handle) return CONTAINING_RECORD(object, struct wine_instance, obj); }
-static struct wine_device *wine_device_from_handle(VkDevice handle) -{ - struct vulkan_device *object = vulkan_device_from_handle(handle); - return CONTAINING_RECORD(object, struct wine_device, obj); -} - -static void vulkan_object_init_ptr( struct vulkan_object *obj, UINT64 host_handle, struct vulkan_client_object *client ) -{ - obj->host_handle = host_handle; - obj->client_handle = (UINT_PTR)client; - client->unix_handle = (UINT_PTR)obj; -} - static BOOL is_wow64(void) { return sizeof(void *) == sizeof(UINT64) && NtCurrentTeb()->WowTebOffset; @@ -443,116 +430,6 @@ static void wine_vk_free_command_buffers(struct vulkan_device *device, } }
-static void wine_vk_device_init_queues(struct wine_device *object, const VkDeviceQueueCreateInfo *info) -{ - struct wine_queue *queues = object->queues + object->queue_count; - struct vulkan_device *device = &object->obj; - VkQueue client_queues = device->client.device->queues + object->queue_count; - VkDeviceQueueInfo2 queue_info; - UINT i; - - TRACE("Queue family index %u, queue count %u.\n", info->queueFamilyIndex, info->queueCount); - - for (i = 0; i < info->queueCount; i++) - { - struct wine_queue *queue = queues + i; - VkQueue host_queue, client_queue = client_queues + i; - - /* The Vulkan spec says: - * - * "vkGetDeviceQueue must only be used to get queues that were created - * with the flags parameter of VkDeviceQueueCreateInfo set to zero." - */ - if (info->flags && device->p_vkGetDeviceQueue2) - { - queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2; - queue_info.pNext = NULL; - queue_info.flags = info->flags; - queue_info.queueFamilyIndex = info->queueFamilyIndex; - queue_info.queueIndex = i; - device->p_vkGetDeviceQueue2(device->host.device, &queue_info, &host_queue); - } - else - { - device->p_vkGetDeviceQueue(device->host.device, info->queueFamilyIndex, i, &host_queue); - } - - vulkan_object_init_ptr(&queue->obj.obj, (UINT_PTR)host_queue, &client_queue->obj); - queue->obj.device = device; - queue->family_index = info->queueFamilyIndex; - queue->queue_index = i; - queue->flags = info->flags; - - TRACE("Got device %p queue %p, host_queue %p.\n", device, queue, queue->obj.host.queue); - } - - object->queue_count += info->queueCount; -} - -static VkResult wine_vk_device_convert_create_info(struct vulkan_physical_device *physical_device, struct conversion_context *ctx, - const VkDeviceCreateInfo *src, VkDeviceCreateInfo *dst, struct wine_device *device) -{ - struct vulkan_instance *instance = physical_device->instance; - const char **extensions; - uint32_t count = 0; - - *dst = *src; - - /* Should be filtered out by loader as ICDs don't support layers. */ - dst->enabledLayerCount = 0; - dst->ppEnabledLayerNames = NULL; - - if (device->obj.extensions.has_VK_KHR_win32_keyed_mutex) - device->obj.extensions.has_VK_KHR_timeline_semaphore = 1; - - vk_funcs->p_map_device_extensions(&device->obj.extensions); - device->obj.extensions.has_VK_KHR_win32_keyed_mutex = 0; - device->obj.extensions.has_VK_KHR_external_memory_win32 = 0; - device->obj.extensions.has_VK_KHR_external_fence_win32 = 0; - device->obj.extensions.has_VK_KHR_external_semaphore_win32 = 0; - - if (device->obj.extensions.has_VK_EXT_external_memory_dma_buf) - device->obj.extensions.has_VK_KHR_external_memory_fd = 1; - - if (physical_device->map_placed_align) - { - VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *map_placed_features; - map_placed_features = conversion_context_alloc(ctx, sizeof(*map_placed_features)); - map_placed_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT; - map_placed_features->pNext = (void *)dst->pNext; - map_placed_features->memoryMapPlaced = VK_TRUE; - map_placed_features->memoryMapRangePlaced = VK_FALSE; - map_placed_features->memoryUnmapReserve = VK_TRUE; - dst->pNext = map_placed_features; - - device->obj.extensions.has_VK_EXT_map_memory_placed = 1; - device->obj.extensions.has_VK_KHR_map_memory2 = 1; - } - else if (physical_device->external_memory_align) - { - device->obj.extensions.has_VK_KHR_external_memory = 1; - device->obj.extensions.has_VK_EXT_external_memory_host = 1; - } - - /* win32u uses VkSwapchainPresentScalingCreateInfoEXT if available. */ - if (device->obj.extensions.has_VK_KHR_swapchain && instance->extensions.has_VK_EXT_surface_maintenance1 && - physical_device->extensions.has_VK_EXT_swapchain_maintenance1) - device->obj.extensions.has_VK_EXT_swapchain_maintenance1 = 1; - - extensions = conversion_context_alloc(ctx, sizeof(device->obj.extensions) * 8 * sizeof(*extensions)); -#define USE_VK_EXT(x) if (device->obj.extensions.has_ ## x) extensions[count++] = #x; - ALL_VK_DEVICE_EXTS -#undef USE_VK_EXT - - TRACE("Enabling %u host device extensions\n", count); - for (const char **extension = extensions, **end = extension + count; extension < end; extension++) - TRACE(" - %s\n", debugstr_a(*extension)); - - dst->ppEnabledExtensionNames = extensions; - dst->enabledExtensionCount = count; - return VK_SUCCESS; -} - NTSTATUS init_vulkan(void *arg) { struct vulkan_instance_extensions extensions = {0}; @@ -832,81 +709,6 @@ VkResult wine_vkAllocateCommandBuffers(VkDevice client_device, const VkCommandBu return res; }
-VkResult wine_vkCreateDevice(VkPhysicalDevice client_physical_device, const VkDeviceCreateInfo *create_info, - const VkAllocationCallbacks *allocator, VkDevice *ret, void *client_ptr) -{ - struct vulkan_physical_device *physical_device = vulkan_physical_device_from_handle(client_physical_device); - struct vulkan_instance *instance = physical_device->instance; - VkDevice host_device, client_device = client_ptr; - VkDeviceCreateInfo create_info_host; - struct conversion_context ctx; - struct wine_device *device; - unsigned int queue_count, i; - VkResult res; - - if (allocator) - FIXME("Support for allocation callbacks not implemented yet\n"); - - if (TRACE_ON(vulkan)) - { - VkPhysicalDeviceProperties properties; - - instance->p_vkGetPhysicalDeviceProperties(physical_device->host.physical_device, &properties); - - TRACE("Device name: %s.\n", debugstr_a(properties.deviceName)); - TRACE("Vendor ID: %#x, Device ID: %#x.\n", properties.vendorID, properties.deviceID); - TRACE("Driver version: %#x.\n", properties.driverVersion); - } - - /* We need to cache all queues within the device as each requires wrapping since queues are dispatchable objects. */ - for (queue_count = 0, i = 0; i < create_info->queueCreateInfoCount; i++) - queue_count += create_info->pQueueCreateInfos[i].queueCount; - - if (!(device = calloc(1, offsetof(struct wine_device, queues[queue_count])))) - return VK_ERROR_OUT_OF_HOST_MEMORY; - device->obj.extensions = client_device->extensions; - - init_conversion_context(&ctx); - res = wine_vk_device_convert_create_info(physical_device, &ctx, create_info, &create_info_host, device); - if (res == VK_SUCCESS) - res = instance->p_vkCreateDevice(physical_device->host.physical_device, &create_info_host, - NULL /* allocator */, &host_device); - free_conversion_context(&ctx); - if (res != VK_SUCCESS) - { - WARN("Failed to create device, res=%d.\n", res); - free(device); - return res; - } - - vulkan_object_init_ptr(&device->obj.obj, (UINT_PTR)host_device, &client_device->obj); - device->obj.physical_device = physical_device; - - /* Just load all function pointers we are aware off. The loader takes care of filtering. - * We use vkGetDeviceProcAddr as opposed to vkGetInstanceProcAddr for efficiency reasons - * as functions pass through fewer dispatch tables within the loader. - */ -#define USE_VK_FUNC(name) \ - device->obj.p_##name = (void *)vk_funcs->p_vkGetDeviceProcAddr(device->obj.host.device, #name); \ - if (device->obj.p_##name == NULL) TRACE("Not found '%s'.\n", #name); - ALL_VK_DEVICE_FUNCS -#undef USE_VK_FUNC - - for (i = 0; i < create_info_host.queueCreateInfoCount; i++) - wine_vk_device_init_queues(device, create_info_host.pQueueCreateInfos + i); - - TRACE("Created device %p, host_device %p.\n", device, device->obj.host.device); - for (i = 0; i < device->queue_count; i++) - { - struct wine_queue *queue = device->queues + i; - vulkan_instance_insert_object(instance, &queue->obj.obj); - } - vulkan_instance_insert_object(instance, &device->obj.obj); - - *ret = client_device; - return VK_SUCCESS; -} - VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, const VkAllocationCallbacks *allocator, VkInstance *ret, void *client_ptr) @@ -984,25 +786,6 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, return VK_SUCCESS; }
-void wine_vkDestroyDevice(VkDevice client_device, const VkAllocationCallbacks *allocator) -{ - struct wine_device *device = wine_device_from_handle(client_device); - struct vulkan_instance *instance = device->obj.physical_device->instance; - unsigned int i; - - if (allocator) - FIXME("Support for allocation callbacks not implemented yet\n"); - if (!device) - return; - - device->obj.p_vkDestroyDevice(device->obj.host.device, NULL /* pAllocator */); - for (i = 0; i < device->queue_count; i++) - vulkan_instance_remove_object(instance, &device->queues[i].obj.obj); - vulkan_instance_remove_object(instance, &device->obj.obj); - - free(device); -} - void wine_vkDestroyInstance(VkInstance client_instance, const VkAllocationCallbacks *allocator) { struct wine_instance *instance = wine_instance_from_handle(client_instance); @@ -1086,49 +869,6 @@ void wine_vkFreeCommandBuffers(VkDevice client_device, VkCommandPool command_poo wine_vk_free_command_buffers(device, pool, count, buffers); }
-static VkQueue wine_vk_device_find_queue(VkDevice client_device, const VkDeviceQueueInfo2 *info) -{ - struct wine_device *device = wine_device_from_handle(client_device); - struct wine_queue *queue; - uint32_t i; - - for (i = 0; i < device->queue_count; i++) - { - queue = &device->queues[i]; - if (queue->family_index == info->queueFamilyIndex - && queue->queue_index == info->queueIndex - && queue->flags == info->flags) - { - return queue->obj.client.queue; - } - } - - return VK_NULL_HANDLE; -} - -void wine_vkGetDeviceQueue(VkDevice client_device, uint32_t family_index, uint32_t queue_index, VkQueue *client_queue) -{ - VkDeviceQueueInfo2 queue_info; - - queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2; - queue_info.pNext = NULL; - queue_info.flags = 0; - queue_info.queueFamilyIndex = family_index; - queue_info.queueIndex = queue_index; - - *client_queue = wine_vk_device_find_queue(client_device, &queue_info); -} - -void wine_vkGetDeviceQueue2(VkDevice client_device, const VkDeviceQueueInfo2 *info, VkQueue *client_queue) -{ - const VkBaseInStructure *chain; - - if ((chain = info->pNext)) - FIXME("Ignoring a linked structure of type %u.\n", chain->sType); - - *client_queue = wine_vk_device_find_queue(client_device, info); -} - VkResult wine_vkCreateCommandPool(VkDevice client_device, const VkCommandPoolCreateInfo *info, const VkAllocationCallbacks *allocator, VkCommandPool *command_pool, void *client_ptr) @@ -1630,8 +1370,8 @@ static NTSTATUS is_available_instance_function(VkInstance handle, const char *na
static NTSTATUS is_available_device_function(VkDevice handle, const char *name) { - struct wine_device *device = wine_device_from_handle(handle); - return !!vk_funcs->p_vkGetDeviceProcAddr(device->obj.host.device, name); + struct vulkan_device *device = vulkan_device_from_handle(handle); + return !!vk_funcs->p_vkGetDeviceProcAddr(device->host.device, name); }
#ifdef _WIN64 diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index ad42681af97..235714e20e1 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -29,24 +29,6 @@
extern const struct vulkan_funcs *vk_funcs;
-struct wine_queue -{ - struct vulkan_queue obj; - - uint32_t family_index; - uint32_t queue_index; - VkDeviceQueueCreateFlags flags; -}; - -struct wine_device -{ - struct vulkan_device obj; - uint64_t queue_count; - struct wine_queue queues[]; -}; - -C_ASSERT(sizeof(struct wine_device) == offsetof(struct wine_device, queues[0])); - struct wine_debug_utils_messenger;
struct wine_debug_report_callback diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index a41be846a52..952b4b222cd 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -50992,7 +50992,7 @@ static NTSTATUS thunk64_vkCreateDevice(void *args)
init_conversion_context(ctx); convert_VkDeviceCreateInfo_win64_to_host(ctx, params->pCreateInfo, &pCreateInfo_host); - params->result = wine_vkCreateDevice(params->physicalDevice, &pCreateInfo_host, params->pAllocator, params->pDevice, params->client_ptr); + params->result = vk_funcs->p_vkCreateDevice(params->physicalDevice, &pCreateInfo_host, params->pAllocator, params->pDevice); free_conversion_context(ctx); return STATUS_SUCCESS; } @@ -51006,7 +51006,6 @@ static NTSTATUS thunk32_vkCreateDevice(void *args) PTR32 pCreateInfo; PTR32 pAllocator; PTR32 pDevice; - PTR32 client_ptr; VkResult result; } *params = args; VkDeviceCreateInfo pCreateInfo_host; @@ -51019,7 +51018,7 @@ static NTSTATUS thunk32_vkCreateDevice(void *args) init_conversion_context(ctx); convert_VkDeviceCreateInfo_win32_to_host(ctx, (const VkDeviceCreateInfo32 *)UlongToPtr(params->pCreateInfo), &pCreateInfo_host); pDevice_host = UlongToPtr(*(PTR32 *)UlongToPtr(params->pDevice)); - params->result = wine_vkCreateDevice((VkPhysicalDevice)UlongToPtr(params->physicalDevice), &pCreateInfo_host, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator), &pDevice_host, UlongToPtr(params->client_ptr)); + params->result = vk_funcs->p_vkCreateDevice((VkPhysicalDevice)UlongToPtr(params->physicalDevice), &pCreateInfo_host, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator), &pDevice_host); *(PTR32 *)UlongToPtr(params->pDevice) = PtrToUlong(pDevice_host); free_conversion_context(ctx); return STATUS_SUCCESS; @@ -52856,7 +52855,7 @@ static NTSTATUS thunk64_vkDestroyDevice(void *args) if (!params->device) return STATUS_SUCCESS;
- wine_vkDestroyDevice(params->device, params->pAllocator); + vk_funcs->p_vkDestroyDevice(params->device, params->pAllocator); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -52874,7 +52873,7 @@ static NTSTATUS thunk32_vkDestroyDevice(void *args) if (!params->device) return STATUS_SUCCESS;
- wine_vkDestroyDevice((VkDevice)UlongToPtr(params->device), (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator)); + vk_funcs->p_vkDestroyDevice((VkDevice)UlongToPtr(params->device), (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator)); return STATUS_SUCCESS; }
@@ -55831,7 +55830,7 @@ static NTSTATUS thunk64_vkGetDeviceQueue(void *args)
TRACE("%p, %u, %u, %p\n", params->device, params->queueFamilyIndex, params->queueIndex, params->pQueue);
- wine_vkGetDeviceQueue(params->device, params->queueFamilyIndex, params->queueIndex, params->pQueue); + vk_funcs->p_vkGetDeviceQueue(params->device, params->queueFamilyIndex, params->queueIndex, params->pQueue); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -55850,7 +55849,7 @@ static NTSTATUS thunk32_vkGetDeviceQueue(void *args) TRACE("%#x, %u, %u, %#x\n", params->device, params->queueFamilyIndex, params->queueIndex, params->pQueue);
pQueue_host = UlongToPtr(*(PTR32 *)UlongToPtr(params->pQueue)); - wine_vkGetDeviceQueue((VkDevice)UlongToPtr(params->device), params->queueFamilyIndex, params->queueIndex, &pQueue_host); + vk_funcs->p_vkGetDeviceQueue((VkDevice)UlongToPtr(params->device), params->queueFamilyIndex, params->queueIndex, &pQueue_host); *(PTR32 *)UlongToPtr(params->pQueue) = PtrToUlong(pQueue_host); return STATUS_SUCCESS; } @@ -55862,7 +55861,7 @@ static NTSTATUS thunk64_vkGetDeviceQueue2(void *args)
TRACE("%p, %p, %p\n", params->device, params->pQueueInfo, params->pQueue);
- wine_vkGetDeviceQueue2(params->device, params->pQueueInfo, params->pQueue); + vk_funcs->p_vkGetDeviceQueue2(params->device, params->pQueueInfo, params->pQueue); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -55882,7 +55881,7 @@ static NTSTATUS thunk32_vkGetDeviceQueue2(void *args)
convert_VkDeviceQueueInfo2_win32_to_host((const VkDeviceQueueInfo232 *)UlongToPtr(params->pQueueInfo), &pQueueInfo_host); pQueue_host = UlongToPtr(*(PTR32 *)UlongToPtr(params->pQueue)); - wine_vkGetDeviceQueue2((VkDevice)UlongToPtr(params->device), &pQueueInfo_host, &pQueue_host); + vk_funcs->p_vkGetDeviceQueue2((VkDevice)UlongToPtr(params->device), &pQueueInfo_host, &pQueue_host); *(PTR32 *)UlongToPtr(params->pQueue) = PtrToUlong(pQueue_host); return STATUS_SUCCESS; } diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index be4da99db06..fccc2cc3923 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -26,13 +26,11 @@ VkResult wine_vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo VkResult wine_vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback); VkResult wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger); VkResult wine_vkCreateDeferredOperationKHR(VkDevice device, const VkAllocationCallbacks *pAllocator, VkDeferredOperationKHR *pDeferredOperation); -VkResult wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, void *client_ptr); VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance, void *client_ptr); void wine_vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyDeferredOperationKHR(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks *pAllocator); -void wine_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator); VkResult wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkLayerProperties *pProperties); VkResult wine_vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties); @@ -43,8 +41,6 @@ VkResult wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysica void wine_vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers); VkResult wine_vkGetCalibratedTimestampsEXT(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoKHR *pTimestampInfos, uint64_t *pTimestamps, uint64_t *pMaxDeviation); VkResult wine_vkGetCalibratedTimestampsKHR(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoKHR *pTimestampInfos, uint64_t *pTimestamps, uint64_t *pMaxDeviation); -void wine_vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue); -void wine_vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2 *pQueueInfo, VkQueue *pQueue); VkResult wine_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(VkPhysicalDevice physicalDevice, uint32_t *pTimeDomainCount, VkTimeDomainKHR *pTimeDomains); VkResult wine_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR(VkPhysicalDevice physicalDevice, uint32_t *pTimeDomainCount, VkTimeDomainKHR *pTimeDomains); void wine_vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo, VkExternalFenceProperties *pExternalFenceProperties); diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index fd1d0ec64c4..9a7eaa76b37 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -112,6 +112,13 @@ static inline void vulkan_object_init( struct vulkan_object *obj, UINT64 host_ha obj->client_handle = (UINT_PTR)obj; }
+static inline void vulkan_object_init_ptr( struct vulkan_object *obj, UINT64 host_handle, struct vulkan_client_object *client ) +{ + obj->host_handle = host_handle; + obj->client_handle = (UINT_PTR)client; + client->unix_handle = (UINT_PTR)obj; +} + struct vulkan_instance { VULKAN_OBJECT_HEADER( VkInstance, instance ); @@ -150,6 +157,20 @@ static inline struct vulkan_physical_device *vulkan_physical_device_from_handle( return (struct vulkan_physical_device *)(UINT_PTR)client->unix_handle; }
+struct vulkan_device; +struct vulkan_queue +{ + VULKAN_OBJECT_HEADER( VkQueue, queue ); + struct vulkan_device *device; + VkDeviceQueueInfo2 info; +}; + +static inline struct vulkan_queue *vulkan_queue_from_handle( VkQueue handle ) +{ + struct vulkan_client_object *client = (struct vulkan_client_object *)handle; + return (struct vulkan_queue *)(UINT_PTR)client->unix_handle; +} + struct vulkan_device { VULKAN_OBJECT_HEADER( VkDevice, device ); @@ -158,26 +179,19 @@ struct vulkan_device #define USE_VK_FUNC(x) PFN_ ## x p_ ## x; ALL_VK_DEVICE_FUNCS #undef USE_VK_FUNC + + uint64_t queue_count; + struct vulkan_queue queues[]; };
+C_ASSERT( sizeof(struct vulkan_device) == offsetof(struct vulkan_device, queues[0]) ); + static inline struct vulkan_device *vulkan_device_from_handle( VkDevice handle ) { struct vulkan_client_object *client = (struct vulkan_client_object *)handle; return (struct vulkan_device *)(UINT_PTR)client->unix_handle; }
-struct vulkan_queue -{ - VULKAN_OBJECT_HEADER( VkQueue, queue ); - struct vulkan_device *device; -}; - -static inline struct vulkan_queue *vulkan_queue_from_handle( VkQueue handle ) -{ - struct vulkan_client_object *client = (struct vulkan_client_object *)handle; - return (struct vulkan_queue *)(UINT_PTR)client->unix_handle; -} - struct vulkan_command_buffer { VULKAN_OBJECT_HEADER( VkCommandBuffer, command_buffer ); @@ -251,11 +265,13 @@ struct vulkan_funcs PFN_vkAcquireNextImageKHR p_vkAcquireNextImageKHR; PFN_vkAllocateMemory p_vkAllocateMemory; PFN_vkCreateBuffer p_vkCreateBuffer; + PFN_vkCreateDevice p_vkCreateDevice; PFN_vkCreateFence p_vkCreateFence; PFN_vkCreateImage p_vkCreateImage; PFN_vkCreateSemaphore p_vkCreateSemaphore; PFN_vkCreateSwapchainKHR p_vkCreateSwapchainKHR; PFN_vkCreateWin32SurfaceKHR p_vkCreateWin32SurfaceKHR; + PFN_vkDestroyDevice p_vkDestroyDevice; PFN_vkDestroyFence p_vkDestroyFence; PFN_vkDestroySemaphore p_vkDestroySemaphore; PFN_vkDestroySurfaceKHR p_vkDestroySurfaceKHR; @@ -265,6 +281,8 @@ struct vulkan_funcs PFN_vkGetDeviceBufferMemoryRequirementsKHR p_vkGetDeviceBufferMemoryRequirementsKHR; PFN_vkGetDeviceImageMemoryRequirements p_vkGetDeviceImageMemoryRequirements; PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr; + PFN_vkGetDeviceQueue p_vkGetDeviceQueue; + PFN_vkGetDeviceQueue2 p_vkGetDeviceQueue2; PFN_vkGetFenceWin32HandleKHR p_vkGetFenceWin32HandleKHR; PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr; PFN_vkGetMemoryWin32HandleKHR p_vkGetMemoryWin32HandleKHR;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/make_vulkan | 4 +- dlls/winevulkan/vulkan.c | 139 +++++++++++++++++++------------ dlls/winevulkan/vulkan_private.h | 40 +-------- dlls/winevulkan/vulkan_thunks.c | 4 +- include/wine/vulkan_driver.h | 31 +++++++ 5 files changed, 124 insertions(+), 94 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 8cb927adece..906220922d3 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -1097,9 +1097,9 @@ class VkHandle(object): if self.name == "VkCommandPool": return "wine_cmd_pool_from_handle({0})->host.command_pool".format(name) if self.name == "VkDebugUtilsMessengerEXT": - return "wine_debug_utils_messenger_from_handle({0})->host.debug_messenger".format(name) + return "vulkan_debug_utils_messenger_from_handle({0})->host.debug_messenger".format(name) if self.name == "VkDebugReportCallbackEXT": - return "wine_debug_report_callback_from_handle({0})->host.debug_callback".format(name) + return "vulkan_debug_report_callback_from_handle({0})->host.debug_callback".format(name) if self.name == "VkDeferredOperationKHR": return "wine_deferred_operation_from_handle({0})->host.deferred_operation".format(name) if self.name == "VkDevice": diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 2c47cae3058..c05ab552961 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -55,21 +55,6 @@ static BOOL use_external_memory(void)
static ULONG_PTR zero_bits = 0;
-#define wine_vk_count_struct(s, t) wine_vk_count_struct_((void *)s, VK_STRUCTURE_TYPE_##t) -static uint32_t wine_vk_count_struct_(void *s, VkStructureType t) -{ - const VkBaseInStructure *header; - uint32_t result = 0; - - for (header = s; header; header = header->pNext) - { - if (header->sType == t) - result++; - } - - return result; -} - const struct vulkan_funcs *vk_funcs;
static int vulkan_object_compare(const void *key, const struct rb_entry *entry) @@ -154,7 +139,7 @@ static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagB { const VkDeviceAddressBindingCallbackDataEXT *address = NULL; struct wine_vk_debug_utils_params *params; - struct wine_debug_utils_messenger *object; + struct vulkan_debug_utils_messenger *object; struct debug_utils_object dummy_object, *objects; struct debug_utils_label dummy_label, *labels; UINT size, strings_len; @@ -261,7 +246,7 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk uint64_t object_handle, size_t location, int32_t code, const char *layer_prefix, const char *message, void *user_data) { struct wine_vk_debug_report_params *params; - struct wine_debug_report_callback *object; + struct vulkan_debug_report_callback *object; UINT strings_len; ULONG ret_len; void *ret_ptr; @@ -499,6 +484,28 @@ failed: return res ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS; }
+static void free_debug_utils_messengers(struct list *messengers) +{ + struct vulkan_debug_utils_messenger *messenger, *next; + + LIST_FOR_EACH_ENTRY_SAFE(messenger, next, messengers, struct vulkan_debug_utils_messenger, entry) + { + list_remove(&messenger->entry); + free(messenger); + } +} + +static void free_debug_report_callbacks(struct list *callbacks) +{ + struct vulkan_debug_report_callback *callback, *next; + + LIST_FOR_EACH_ENTRY_SAFE(callback, next, callbacks, struct vulkan_debug_report_callback, entry) + { + list_remove(&callback->entry); + free(callback); + } +} + /* 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. @@ -506,42 +513,30 @@ failed: static VkResult wine_vk_instance_convert_create_info(struct conversion_context *ctx, const VkInstanceCreateInfo *src, VkInstanceCreateInfo *dst, struct wine_instance *instance) { - VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger; VkDebugReportCallbackCreateInfoEXT *debug_report_callback; - VkBaseInStructure *header; + VkBaseInStructure *header = (VkBaseInStructure *)dst; const char **extensions; uint32_t count = 0; - unsigned int i;
*dst = *src;
- instance->utils_messenger_count = wine_vk_count_struct(dst, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT); - instance->utils_messengers = calloc(instance->utils_messenger_count, sizeof(*instance->utils_messengers)); - header = (VkBaseInStructure *) dst; - for (i = 0; i < instance->utils_messenger_count; i++) + while ((header = find_next_struct(header->pNext, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT))) { - header = find_next_struct(header->pNext, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT); - debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *) header; + VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *)header; + struct vulkan_debug_utils_messenger *messenger = debug_utils_messenger->pUserData;
- instance->utils_messengers[i].instance = &instance->obj; - instance->utils_messengers[i].host.debug_messenger = VK_NULL_HANDLE; - instance->utils_messengers[i].user_callback = (UINT_PTR)debug_utils_messenger->pfnUserCallback; - instance->utils_messengers[i].user_data = (UINT_PTR)debug_utils_messenger->pUserData; - - /* convert_VkInstanceCreateInfo_* already copied the chain, so we can modify it in-place. */ - debug_utils_messenger->pfnUserCallback = (void *) &debug_utils_callback_conversion; - debug_utils_messenger->pUserData = &instance->utils_messengers[i]; + list_remove(&messenger->entry); + list_add_tail(&instance->utils_messengers, &messenger->entry); + messenger->instance = &instance->obj; }
if ((debug_report_callback = find_next_struct(dst->pNext, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT))) { - instance->default_callback.instance = &instance->obj; - instance->default_callback.host.debug_callback = VK_NULL_HANDLE; - instance->default_callback.user_callback = (UINT_PTR)debug_report_callback->pfnCallback; - instance->default_callback.user_data = (UINT_PTR)debug_report_callback->pUserData; + struct vulkan_debug_report_callback *callback = debug_report_callback->pUserData;
- debug_report_callback->pfnCallback = (void *) &debug_report_callback_conversion; - debug_report_callback->pUserData = &instance->default_callback; + list_remove(&callback->entry); + list_add_tail(&instance->report_callbacks, &callback->entry); + callback->instance = &instance->obj; }
/* ICDs don't support any layers, so nothing to copy. Modern versions of the loader @@ -709,10 +704,14 @@ VkResult wine_vkAllocateCommandBuffers(VkDevice client_device, const VkCommandBu return res; }
-VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, +VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *client_create_info, const VkAllocationCallbacks *allocator, VkInstance *ret, void *client_ptr) { + VkInstanceCreateInfo *create_info = (VkInstanceCreateInfo *)client_create_info; /* cast away const, chain has been copied in the thunks */ + struct list utils_messengers = LIST_INIT(utils_messengers), report_callbacks = LIST_INIT(report_callbacks); + VkBaseInStructure *header = (VkBaseInStructure *)create_info; + VkDebugReportCallbackCreateInfoEXT *debug_report_callback; VkInstanceCreateInfo create_info_host; struct conversion_context ctx; struct wine_instance *instance; @@ -721,8 +720,34 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, unsigned int i; VkResult res;
- if (allocator) - FIXME("Support for allocation callbacks not implemented yet\n"); + while ((header = find_next_struct(header->pNext, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT))) + { + VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *)header; + struct vulkan_debug_utils_messenger *utils_messenger; + + if (!(utils_messenger = calloc(1, sizeof(*utils_messenger)))) goto failed; + utils_messenger->host.debug_messenger = VK_NULL_HANDLE; + utils_messenger->user_callback = (UINT_PTR)debug_utils_messenger->pfnUserCallback; + utils_messenger->user_data = (UINT_PTR)debug_utils_messenger->pUserData; + + debug_utils_messenger->pfnUserCallback = (void *)&debug_utils_callback_conversion; + debug_utils_messenger->pUserData = utils_messenger; + list_add_tail(&utils_messengers, &utils_messenger->entry); + } + + if ((debug_report_callback = find_next_struct(create_info->pNext, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT))) + { + struct vulkan_debug_report_callback *report_callback; + + if (!(report_callback = calloc(1, sizeof(*report_callback)))) goto failed; + report_callback->host.debug_callback = VK_NULL_HANDLE; + report_callback->user_callback = (UINT_PTR)debug_report_callback->pfnCallback; + report_callback->user_data = (UINT_PTR)debug_report_callback->pUserData; + + debug_report_callback->pfnCallback = (void *)&debug_report_callback_conversion; + debug_report_callback->pUserData = report_callback; + list_add_tail(&report_callbacks, &report_callback->entry); + }
if (!(instance = calloc(1, sizeof(*instance) + sizeof(*physical_devices) * client_instance->phys_dev_count))) { @@ -731,6 +756,8 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, } physical_devices = (struct vulkan_physical_device *)(instance + 1); instance->obj.extensions = client_instance->extensions; + list_init(&instance->utils_messengers); + list_init(&instance->report_callbacks);
init_conversion_context(&ctx); res = wine_vk_instance_convert_create_info(&ctx, create_info, &create_info_host, instance); @@ -740,7 +767,8 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, if (res != VK_SUCCESS) { ERR("Failed to create instance, res=%d\n", res); - free(instance->utils_messengers); + free_debug_utils_messengers(&instance->utils_messengers); + free_debug_report_callbacks(&instance->report_callbacks); free(instance); return res; } @@ -768,7 +796,8 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, { ERR("Failed to load physical devices, res=%d\n", res); instance->obj.p_vkDestroyInstance(instance->obj.host.instance, NULL /* allocator */); - free(instance->utils_messengers); + free_debug_utils_messengers(&instance->utils_messengers); + free_debug_report_callbacks(&instance->report_callbacks); free(instance); return res; } @@ -784,6 +813,11 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info,
*ret = client_instance; return VK_SUCCESS; + +failed: + free_debug_utils_messengers(&utils_messengers); + free_debug_report_callbacks(&report_callbacks); + return VK_ERROR_OUT_OF_HOST_MEMORY; }
void wine_vkDestroyInstance(VkInstance client_instance, const VkAllocationCallbacks *allocator) @@ -802,7 +836,8 @@ void wine_vkDestroyInstance(VkInstance client_instance, const VkAllocationCallba vulkan_instance_remove_object(&instance->obj, &instance->obj.obj);
if (instance->objects.compare) pthread_rwlock_destroy(&instance->objects_lock); - free(instance->utils_messengers); + free_debug_utils_messengers(&instance->utils_messengers); + free_debug_report_callbacks(&instance->report_callbacks); free(instance); }
@@ -1207,7 +1242,7 @@ VkResult wine_vkCreateDebugUtilsMessengerEXT(VkInstance client_instance, struct vulkan_instance *instance = vulkan_instance_from_handle(client_instance); VkDebugUtilsMessengerCreateInfoEXT wine_create_info; VkDebugUtilsMessengerEXT host_debug_messenger; - struct wine_debug_utils_messenger *object; + struct vulkan_debug_utils_messenger *object; VkResult res;
if (allocator) @@ -1242,9 +1277,9 @@ void wine_vkDestroyDebugUtilsMessengerEXT(VkInstance client_instance, VkDebugUti const VkAllocationCallbacks *allocator) { struct vulkan_instance *instance = vulkan_instance_from_handle(client_instance); - struct wine_debug_utils_messenger *object; + struct vulkan_debug_utils_messenger *object;
- object = wine_debug_utils_messenger_from_handle(messenger); + object = vulkan_debug_utils_messenger_from_handle(messenger);
if (!object) return; @@ -1263,7 +1298,7 @@ VkResult wine_vkCreateDebugReportCallbackEXT(VkInstance client_instance, struct vulkan_instance *instance = vulkan_instance_from_handle(client_instance); VkDebugReportCallbackCreateInfoEXT wine_create_info; VkDebugReportCallbackEXT host_debug_callback; - struct wine_debug_report_callback *object; + struct vulkan_debug_report_callback *object; VkResult res;
if (allocator) @@ -1298,9 +1333,9 @@ void wine_vkDestroyDebugReportCallbackEXT(VkInstance client_instance, VkDebugRep const VkAllocationCallbacks *allocator) { struct vulkan_instance *instance = vulkan_instance_from_handle(client_instance); - struct wine_debug_report_callback *object; + struct vulkan_debug_report_callback *object;
- object = wine_debug_report_callback_from_handle(callback); + object = vulkan_debug_report_callback_from_handle(callback);
if (!object) return; diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 235714e20e1..bc8fe305a84 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -29,27 +29,12 @@
extern const struct vulkan_funcs *vk_funcs;
-struct wine_debug_utils_messenger; - -struct wine_debug_report_callback -{ - VULKAN_OBJECT_HEADER( VkDebugReportCallbackEXT, debug_callback ); - struct vulkan_instance *instance; - - UINT64 user_callback; /* client pointer */ - UINT64 user_data; /* client pointer */ -}; - -struct wine_debug_report_callback; - struct wine_instance { struct vulkan_instance obj;
- struct wine_debug_utils_messenger *utils_messengers; - uint32_t utils_messenger_count; - - struct wine_debug_report_callback default_callback; + struct list utils_messengers; + struct list report_callbacks;
struct rb_tree objects; pthread_rwlock_t objects_lock; @@ -66,27 +51,6 @@ static inline struct wine_cmd_pool *wine_cmd_pool_from_handle(VkCommandPool hand return (struct wine_cmd_pool *)(UINT_PTR)client->unix_handle; }
-struct wine_debug_utils_messenger -{ - VULKAN_OBJECT_HEADER( VkDebugUtilsMessengerEXT, debug_messenger ); - struct vulkan_instance *instance; - - UINT64 user_callback; /* client pointer */ - UINT64 user_data; /* client pointer */ -}; - -static inline struct wine_debug_utils_messenger *wine_debug_utils_messenger_from_handle( - VkDebugUtilsMessengerEXT handle) -{ - return (struct wine_debug_utils_messenger *)(uintptr_t)handle; -} - -static inline struct wine_debug_report_callback *wine_debug_report_callback_from_handle( - VkDebugReportCallbackEXT handle) -{ - return (struct wine_debug_report_callback *)(uintptr_t)handle; -} - BOOL wine_vk_is_type_wrapped(VkObjectType type);
NTSTATUS init_vulkan(void *args); diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 952b4b222cd..2419c8554bd 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -9848,9 +9848,9 @@ static uint64_t wine_vk_unwrap_handle(uint32_t type, uint64_t handle) case VK_OBJECT_TYPE_COMMAND_POOL: return (uint64_t) wine_cmd_pool_from_handle(handle)->host.command_pool; case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: - return (uint64_t) wine_debug_report_callback_from_handle(handle)->host.debug_callback; + return (uint64_t) vulkan_debug_report_callback_from_handle(handle)->host.debug_callback; case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: - return (uint64_t) wine_debug_utils_messenger_from_handle(handle)->host.debug_messenger; + return (uint64_t) vulkan_debug_utils_messenger_from_handle(handle)->host.debug_messenger; case VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR: return (uint64_t) wine_deferred_operation_from_handle(handle)->host.deferred_operation; case VK_OBJECT_TYPE_DEVICE: diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index 9a7eaa76b37..614a450a9ee 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -86,6 +86,7 @@ struct VkDevice_T #ifdef WINE_UNIX_LIB
#include "wine/rbtree.h" +#include "wine/list.h"
/* Wine internal vulkan driver version, needs to be bumped upon vulkan_funcs changes. */ #define WINE_VULKAN_DRIVER_VERSION 47 @@ -119,6 +120,36 @@ static inline void vulkan_object_init_ptr( struct vulkan_object *obj, UINT64 hos client->unix_handle = (UINT_PTR)obj; }
+struct vulkan_debug_utils_messenger +{ + VULKAN_OBJECT_HEADER( VkDebugUtilsMessengerEXT, debug_messenger ); + struct vulkan_instance *instance; + struct list entry; /* entry in instance list if static */ + + UINT64 user_callback; /* client pointer */ + UINT64 user_data; /* client pointer */ +}; + +static inline struct vulkan_debug_utils_messenger *vulkan_debug_utils_messenger_from_handle( VkDebugUtilsMessengerEXT handle ) +{ + return (struct vulkan_debug_utils_messenger *)(UINT_PTR)handle; +} + +struct vulkan_debug_report_callback +{ + VULKAN_OBJECT_HEADER( VkDebugReportCallbackEXT, debug_callback ); + struct vulkan_instance *instance; + struct list entry; /* entry in instance list if static */ + + UINT64 user_callback; /* client pointer */ + UINT64 user_data; /* client pointer */ +}; + +static inline struct vulkan_debug_report_callback *vulkan_debug_report_callback_from_handle( VkDebugReportCallbackEXT handle ) +{ + return (struct vulkan_debug_report_callback *)(UINT_PTR)handle; +} + struct vulkan_instance { VULKAN_OBJECT_HEADER( VkInstance, instance );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 423 ++++++++++++++++++++++++++++- dlls/winevulkan/loader.c | 20 +- dlls/winevulkan/loader_thunks.h | 1 - dlls/winevulkan/make_vulkan | 5 +- dlls/winevulkan/vulkan.c | 453 ++------------------------------ dlls/winevulkan/vulkan_thunks.c | 9 +- dlls/winevulkan/vulkan_thunks.h | 3 +- include/wine/vulkan_driver.h | 14 +- 8 files changed, 455 insertions(+), 473 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 80a7eae4855..9d5dcdd8683 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -37,6 +37,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr = NULL; PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr = NULL; +static PFN_vkCreateInstance p_vkCreateInstance; +static PFN_vkEnumerateInstanceExtensionProperties p_vkEnumerateInstanceExtensionProperties;
static void *vulkan_handle; static struct vulkan_funcs vulkan_funcs; @@ -61,6 +63,16 @@ static const UINT EXTERNAL_FENCE_WIN32_BITS = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQ
#define ROUND_SIZE(size, mask) ((((SIZE_T)(size) + (mask)) & ~(SIZE_T)(mask)))
+static BOOL is_wow64(void) +{ + return sizeof(void *) == sizeof(UINT64) && NtCurrentTeb()->WowTebOffset; +} + +static BOOL use_external_memory(void) +{ + return is_wow64(); +} + struct mempool { struct mempool *next; @@ -93,6 +105,24 @@ static void *mem_alloc( struct mempool *pool, size_t size ) return next->mem; }
+struct instance +{ + struct vulkan_instance obj; + BOOL enable_win32_surface; + + struct list utils_messengers; + struct list report_callbacks; + + struct rb_tree objects; + pthread_rwlock_t objects_lock; +}; + +static struct instance *instance_from_handle( VkInstance handle ) +{ + struct vulkan_instance *object = vulkan_instance_from_handle( handle ); + return CONTAINING_RECORD( object, struct instance, obj ); +} + struct device_memory { struct vulkan_device_memory obj; @@ -307,6 +337,338 @@ static HANDLE open_shared_resource_from_name( const WCHAR *name ) return open_name.hNtHandle; }
+static const void *find_next_struct( const VkBaseInStructure *header, VkStructureType type ) +{ + for (; header; header = header->pNext) if (header->sType == type) return header; + return NULL; +} + +static int vulkan_object_compare( const void *key, const struct rb_entry *entry ) +{ + struct vulkan_object *object = RB_ENTRY_VALUE( entry, struct vulkan_object, entry ); + const uint64_t *host_handle = key; + if (*host_handle < object->host_handle) return -1; + if (*host_handle > object->host_handle) return 1; + return 0; +} + +static uint64_t vulkan_instance_client_handle_from_host( struct vulkan_instance *instance, uint64_t host_handle ) +{ + struct instance *impl = CONTAINING_RECORD( instance, struct instance, obj ); + struct rb_entry *entry; + uint64_t result = 0; + + pthread_rwlock_rdlock( &impl->objects_lock ); + if ((entry = rb_get( &impl->objects, &host_handle ))) + { + struct vulkan_object *object = RB_ENTRY_VALUE( entry, struct vulkan_object, entry ); + result = object->client_handle; + } + pthread_rwlock_unlock( &impl->objects_lock ); + return result; +} + +static void vulkan_instance_insert_object( struct vulkan_instance *instance, struct vulkan_object *obj ) +{ + struct instance *impl = CONTAINING_RECORD( instance, struct instance, obj ); + if (impl->objects.compare) + { + pthread_rwlock_wrlock( &impl->objects_lock ); + rb_put( &impl->objects, &obj->host_handle, &obj->entry ); + pthread_rwlock_unlock( &impl->objects_lock ); + } +} + +static void vulkan_instance_remove_object( struct vulkan_instance *instance, struct vulkan_object *obj ) +{ + struct instance *impl = CONTAINING_RECORD( instance, struct instance, obj ); + if (impl->objects.compare) + { + pthread_rwlock_wrlock( &impl->objects_lock ); + rb_remove( &impl->objects, &obj->entry ); + pthread_rwlock_unlock( &impl->objects_lock ); + } +} + +static void free_debug_utils_messengers( struct list *messengers ) +{ + struct vulkan_debug_utils_messenger *messenger, *next; + + LIST_FOR_EACH_ENTRY_SAFE( messenger, next, messengers, struct vulkan_debug_utils_messenger, entry ) + { + list_remove( &messenger->entry ); + free( messenger ); + } +} + +static void free_debug_report_callbacks( struct list *callbacks ) +{ + struct vulkan_debug_report_callback *callback, *next; + + LIST_FOR_EACH_ENTRY_SAFE( callback, next, callbacks, struct vulkan_debug_report_callback, entry ) + { + list_remove( &callback->entry ); + free( callback ); + } +} + +static VkResult convert_instance_create_info( struct mempool *pool, VkInstanceCreateInfo *info, struct instance *instance ) +{ + const VkBaseInStructure *header = (const VkBaseInStructure *)info; + const VkDebugReportCallbackCreateInfoEXT *debug_report_callback; + const char **extensions; + uint32_t count = 0; + + while ((header = find_next_struct( header->pNext, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT ))) + { + const VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger = (const VkDebugUtilsMessengerCreateInfoEXT *)header; + struct vulkan_debug_utils_messenger *messenger = debug_utils_messenger->pUserData; + + list_remove( &messenger->entry ); + list_add_tail( &instance->utils_messengers, &messenger->entry ); + messenger->instance = &instance->obj; + } + + if ((debug_report_callback = find_next_struct( info->pNext, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT ))) + { + struct vulkan_debug_report_callback *callback = debug_report_callback->pUserData; + + list_remove( &callback->entry ); + list_add_tail( &instance->report_callbacks, &callback->entry ); + callback->instance = &instance->obj; + } + + if (info->enabledLayerCount) + { + FIXME( "Loading explicit layers is not supported!\n" ); + return VK_ERROR_LAYER_NOT_PRESENT; + } + + driver_funcs->p_map_instance_extensions( &instance->obj.extensions ); + instance->obj.extensions.has_VK_KHR_win32_surface = 0; + + if (instance->obj.extensions.has_VK_EXT_debug_utils || instance->obj.extensions.has_VK_EXT_debug_report) + { + rb_init( &instance->objects, vulkan_object_compare ); + pthread_rwlock_init( &instance->objects_lock, NULL ); + } + + if (instance->obj.extensions.has_VK_KHR_win32_surface && vulkan_funcs.host_extensions.has_VK_EXT_surface_maintenance1) + instance->obj.extensions.has_VK_EXT_surface_maintenance1 = 1; + if (use_external_memory()) + { + instance->obj.extensions.has_VK_KHR_get_physical_device_properties2 = 1; + instance->obj.extensions.has_VK_KHR_external_memory_capabilities = 1; + } + + if (!(extensions = mem_alloc( pool, sizeof(instance->obj.extensions) * 8 * sizeof(*extensions) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; +#define USE_VK_EXT(x) if (instance->obj.extensions.has_ ## x) extensions[count++] = #x; + ALL_VK_INSTANCE_EXTS +#undef USE_VK_EXT + + TRACE( "Enabling %u host instance extensions\n", count ); + for (const char **extension = extensions, **end = extension + count; extension < end; extension++) + TRACE( " - %s\n", debugstr_a(*extension) ); + + info->ppEnabledExtensionNames = extensions; + info->enabledExtensionCount = count; + return VK_SUCCESS; +} + +static VkResult init_physical_device( struct vulkan_physical_device *physical_device, VkPhysicalDevice host_physical_device, + VkPhysicalDevice client_physical_device, struct vulkan_instance *instance ) +{ + struct vulkan_device_extensions extensions = {0}; + VkExtensionProperties *properties; + uint32_t count; + VkResult res; + + vulkan_object_init_ptr( &physical_device->obj, (UINT_PTR)host_physical_device, &client_physical_device->obj ); + physical_device->instance = instance; + + instance->p_vkGetPhysicalDeviceMemoryProperties( host_physical_device, &physical_device->memory_properties ); + + if ((res = instance->p_vkEnumerateDeviceExtensionProperties( host_physical_device, NULL, &count, NULL ))) return res; + if (!(properties = calloc( count, sizeof(*properties) ))) return res; + if ((res = instance->p_vkEnumerateDeviceExtensionProperties( host_physical_device, NULL, &count, properties ))) goto done; + + TRACE( "Host physical device extensions:\n" ); + for (uint32_t i = 0; i < count; i++) + { + const char *extension = properties[i].extensionName; +#define USE_VK_EXT(x) \ + if (!strcmp( extension, #x )) \ + { \ + extensions.has_ ## x = 1; \ + TRACE( " - %s\n", extension ); \ + } else + ALL_VK_DEVICE_EXTS +#undef USE_VK_EXT + WARN( "Extension %s is not supported.\n", debugstr_a(extension) ); + } + physical_device->extensions = extensions; + + if (zero_bits && physical_device->extensions.has_VK_EXT_map_memory_placed && physical_device->extensions.has_VK_KHR_map_memory2) + { + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT map_placed_feature = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT}; + VkPhysicalDeviceFeatures2 features = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, .pNext = &map_placed_feature}; + + instance->p_vkGetPhysicalDeviceFeatures2KHR( host_physical_device, &features ); + if (map_placed_feature.memoryMapPlaced && map_placed_feature.memoryUnmapReserve) + { + VkPhysicalDeviceMapMemoryPlacedPropertiesEXT map_placed_props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT}; + VkPhysicalDeviceProperties2 props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,.pNext = &map_placed_props}; + + instance->p_vkGetPhysicalDeviceProperties2( host_physical_device, &props ); + physical_device->map_placed_align = map_placed_props.minPlacedMemoryMapAlignment; + TRACE( "Using placed map with alignment %u\n", physical_device->map_placed_align ); + } + } + + if (zero_bits && physical_device->extensions.has_VK_EXT_external_memory_host && !physical_device->map_placed_align) + { + VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_mem_props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT}; + VkPhysicalDeviceProperties2 props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .pNext = &host_mem_props}; + + instance->p_vkGetPhysicalDeviceProperties2KHR( host_physical_device, &props ); + physical_device->external_memory_align = host_mem_props.minImportedHostPointerAlignment; + if (physical_device->external_memory_align) WARN( "Not using VK_EXT_external_memory_host for memory mapping\n" ); + else TRACE( "Using VK_EXT_external_memory_host for memory mapping with alignment: %u\n", physical_device->external_memory_align ); + } + + driver_funcs->p_map_device_extensions( &extensions ); + if (extensions.has_VK_KHR_external_memory_win32 && zero_bits && !physical_device->map_placed_align) + { + WARN( "Cannot export WOW64 memory without VK_EXT_map_memory_placed\n" ); + extensions.has_VK_KHR_external_memory_win32 = 0; + } + extensions.has_VK_KHR_win32_keyed_mutex = extensions.has_VK_KHR_timeline_semaphore; + + /* filter out unsupported client device extensions */ +#define USE_VK_EXT(x) client_physical_device->extensions.has_ ## x = extensions.has_ ## x; + ALL_VK_CLIENT_DEVICE_EXTS +#undef USE_VK_EXT + +done: + free( properties ); + return res; +} + +/* Helper function which stores wrapped physical devices in the instance object. */ +static VkResult init_physical_devices( struct vulkan_instance *instance, struct vulkan_physical_device *physical_devices ) +{ + VkInstance client_instance = instance->client.instance; + VkPhysicalDevice *host_physical_devices; + uint32_t physical_device_count; + unsigned int i; + VkResult res; + + if ((res = instance->p_vkEnumeratePhysicalDevices( instance->host.instance, &physical_device_count, NULL ))) + { + ERR( "Failed to enumerate physical devices, res %d\n", res ); + return res; + } + if (!physical_device_count) return res; + + if (physical_device_count > client_instance->physical_device_count) + { + client_instance->physical_device_count = physical_device_count; + return VK_ERROR_OUT_OF_POOL_MEMORY; + } + client_instance->physical_device_count = physical_device_count; + + if (!(host_physical_devices = calloc( physical_device_count, sizeof(*host_physical_devices) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; + if ((res = instance->p_vkEnumeratePhysicalDevices( instance->host.instance, &physical_device_count, host_physical_devices ))) goto failed; + + /* Wrap each host physical device handle into a dispatchable object for the ICD loader. */ + for (i = 0; i < physical_device_count; i++) + { + VkPhysicalDevice client_physical_device = &client_instance->physical_device[i]; + struct vulkan_physical_device *physical_device = physical_devices + i; + if ((res = init_physical_device( physical_device, host_physical_devices[i], client_physical_device, instance ))) goto failed; + } + instance->physical_device_count = physical_device_count; + instance->physical_devices = physical_devices; + +failed: + free( host_physical_devices ); + return res; +} + +static VkResult win32u_vkCreateInstance( const VkInstanceCreateInfo *client_create_info, const VkAllocationCallbacks *allocator, + VkInstance *client_instance_ptr ) +{ + VkInstanceCreateInfo *create_info = (VkInstanceCreateInfo *)client_create_info; /* cast away const, chain has been copied in the thunks */ + VkInstance host_instance, client_instance = *client_instance_ptr; + struct vulkan_physical_device *physical_devices; + struct mempool pool = {0}; + struct instance *instance; + unsigned int i; + VkResult res; + + if (!(instance = calloc( 1, sizeof(*instance) + sizeof(*physical_devices) * client_instance->physical_device_count) )) return VK_ERROR_OUT_OF_HOST_MEMORY; + physical_devices = (struct vulkan_physical_device *)(instance + 1); + instance->obj.extensions = client_instance->extensions; + list_init( &instance->utils_messengers ); + list_init( &instance->report_callbacks ); + + if ((res = convert_instance_create_info( &pool, create_info, instance ))) goto failed; + if ((res = p_vkCreateInstance( create_info, NULL /* allocator */, &host_instance ))) goto failed; + + vulkan_object_init_ptr( &instance->obj.obj, (UINT_PTR)host_instance, &client_instance->obj ); + instance->obj.p_insert_object = vulkan_instance_insert_object; + instance->obj.p_remove_object = vulkan_instance_remove_object; + instance->obj.p_client_handle_from_host = vulkan_instance_client_handle_from_host; + +#define USE_VK_FUNC( name ) \ + instance->obj.p_##name = (void *)p_vkGetInstanceProcAddr( instance->obj.host.instance, #name ); \ + if (!instance->obj.p_##name) TRACE( "Instance proc %s not found.\n", #name ); + ALL_VK_INSTANCE_FUNCS +#undef USE_VK_FUNC + + /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as each vkPhysicalDevice is a dispatchable + * object, which means we need to wrap the host physical devices and present those to the application. + */ + if ((res = init_physical_devices( &instance->obj, physical_devices ))) goto failed; + + TRACE( "Created instance %p, host_instance %p.\n", instance, instance->obj.host.instance ); + for (i = 0; i < instance->obj.physical_device_count; i++) + { + struct vulkan_physical_device *physical_device = &instance->obj.physical_devices[i]; + vulkan_instance_insert_object( &instance->obj, &physical_device->obj ); + } + vulkan_instance_insert_object( &instance->obj, &instance->obj.obj ); + +failed: + if (res) + { + ERR( "Failed to create vulkan instance, res %d\n", res ); + if (host_instance) instance->obj.p_vkDestroyInstance( host_instance, NULL /* allocator */ ); + free_debug_utils_messengers( &instance->utils_messengers ); + free_debug_report_callbacks( &instance->report_callbacks ); + free( instance ); + } + mem_free( &pool ); + return res; +} + +static void win32u_vkDestroyInstance( VkInstance client_instance, const VkAllocationCallbacks *allocator ) +{ + struct instance *instance = instance_from_handle( client_instance ); + + if (!instance) return; + + instance->obj.p_vkDestroyInstance( instance->obj.host.instance, NULL /* allocator */ ); + for (int i = 0; i < instance->obj.physical_device_count; i++) + vulkan_instance_remove_object( &instance->obj, &instance->obj.physical_devices[i].obj ); + vulkan_instance_remove_object( &instance->obj, &instance->obj.obj ); + + if (instance->objects.compare) pthread_rwlock_destroy( &instance->objects_lock ); + free_debug_utils_messengers( &instance->utils_messengers ); + free_debug_report_callbacks( &instance->report_callbacks ); + free( instance ); +} + static VkResult convert_device_create_info( struct vulkan_physical_device *physical_device, VkDeviceCreateInfo *info, struct mempool *pool, struct vulkan_device *device ) { @@ -2453,16 +2815,6 @@ static void win32u_vkGetPhysicalDeviceExternalFencePropertiesKHR( VkPhysicalDevi get_physical_device_external_fence_properties( physical_device, fence_info, fence_properties, instance->p_vkGetPhysicalDeviceExternalFencePropertiesKHR ); }
-static void win32u_map_instance_extensions( struct vulkan_instance_extensions *extensions ) -{ - return driver_funcs->p_map_instance_extensions( extensions ); -} - -static void win32u_map_device_extensions( struct vulkan_device_extensions *extensions ) -{ - return driver_funcs->p_map_device_extensions( extensions ); -} - static struct vulkan_funcs vulkan_funcs = { .p_vkAcquireNextImage2KHR = win32u_vkAcquireNextImage2KHR, @@ -2472,11 +2824,13 @@ static struct vulkan_funcs vulkan_funcs = .p_vkCreateDevice = win32u_vkCreateDevice, .p_vkCreateFence = win32u_vkCreateFence, .p_vkCreateImage = win32u_vkCreateImage, + .p_vkCreateInstance = win32u_vkCreateInstance, .p_vkCreateSemaphore = win32u_vkCreateSemaphore, .p_vkCreateSwapchainKHR = win32u_vkCreateSwapchainKHR, .p_vkCreateWin32SurfaceKHR = win32u_vkCreateWin32SurfaceKHR, .p_vkDestroyDevice = win32u_vkDestroyDevice, .p_vkDestroyFence = win32u_vkDestroyFence, + .p_vkDestroyInstance = win32u_vkDestroyInstance, .p_vkDestroySemaphore = win32u_vkDestroySemaphore, .p_vkDestroySurfaceKHR = win32u_vkDestroySurfaceKHR, .p_vkDestroySwapchainKHR = win32u_vkDestroySwapchainKHR, @@ -2516,8 +2870,6 @@ static struct vulkan_funcs vulkan_funcs = .p_vkQueueSubmit2KHR = win32u_vkQueueSubmit2KHR, .p_vkUnmapMemory = win32u_vkUnmapMemory, .p_vkUnmapMemory2KHR = win32u_vkUnmapMemory2KHR, - .p_map_instance_extensions = win32u_map_instance_extensions, - .p_map_device_extensions = win32u_map_device_extensions, };
static VkResult nulldrv_vulkan_surface_create( HWND hwnd, const struct vulkan_instance *instance, VkSurfaceKHR *surface, @@ -2620,6 +2972,11 @@ static const struct vulkan_driver_funcs lazydrv_funcs =
static void vulkan_init_once(void) { + struct vulkan_instance_extensions extensions = {0}; + VkExtensionProperties *properties = NULL; + uint32_t count = 0; + VkResult res; + if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW ))) { ERR( "Failed to load %s\n", SONAME_LIBVULKAN ); @@ -2642,6 +2999,48 @@ static void vulkan_init_once(void) driver_funcs = &lazydrv_funcs; vulkan_funcs.p_vkGetInstanceProcAddr = p_vkGetInstanceProcAddr; vulkan_funcs.p_vkGetDeviceProcAddr = p_vkGetDeviceProcAddr; + +#define LOAD_FUNCPTR( f ) p_##f = (PFN_##f)p_vkGetInstanceProcAddr( NULL, #f ); + LOAD_FUNCPTR( vkCreateInstance ); + LOAD_FUNCPTR( vkEnumerateInstanceExtensionProperties ); +#undef LOAD_FUNCPTR + + do + { + free( properties ); + properties = NULL; + if ((res = p_vkEnumerateInstanceExtensionProperties( NULL, &count, NULL ))) goto failed; + if (!count || !(properties = malloc( count * sizeof(*properties) ))) goto failed; + } while ((res = p_vkEnumerateInstanceExtensionProperties( NULL, &count, properties ) == VK_INCOMPLETE)); + if (res) goto failed; + + TRACE( "Host instance extensions:\n" ); + for (uint32_t i = 0; i < count; i++) + { + const char *extension = properties[i].extensionName; +#define USE_VK_EXT(x) \ + if (!strcmp( extension, #x )) \ + { \ + extensions.has_ ## x = 1; \ + TRACE( " - %s\n", extension ); \ + } else + ALL_VK_INSTANCE_EXTS +#undef USE_VK_EXT + WARN( "Extension %s is not supported.\n", debugstr_a(extension) ); + } + vulkan_funcs.host_extensions = extensions; + + /* map host instance extensions for VK_KHR_win32_surface */ + driver_funcs->p_map_instance_extensions( &extensions ); + + /* filter out unsupported client instance extensions */ +#define USE_VK_EXT(x) vulkan_funcs.client_extensions.has_ ## x = extensions.has_ ## x; + ALL_VK_CLIENT_INSTANCE_EXTS +#undef USE_VK_EXT + +failed: + if (res) ERR( "Failed to initialize instance extensions, res %d\n", res ); + free( properties ); }
#else /* SONAME_LIBVULKAN */ diff --git a/dlls/winevulkan/loader.c b/dlls/winevulkan/loader.c index 3e377acd153..d9250c2f831 100644 --- a/dlls/winevulkan/loader.c +++ b/dlls/winevulkan/loader.c @@ -380,7 +380,7 @@ VkResult WINAPI vkCreateInstance(const VkInstanceCreateInfo *create_info, struct vkCreateInstance_params params; const VkApplicationInfo *app_info; struct VkInstance_T *instance; - uint32_t phys_dev_count = 8, i; + uint32_t device_count = 8, i; NTSTATUS status;
TRACE("create_info %p, allocator %p, instance %p\n", create_info, allocator, ret); @@ -409,27 +409,31 @@ VkResult WINAPI vkCreateInstance(const VkInstanceCreateInfo *create_info,
for (;;) { - if (!(instance = vulkan_client_object_create(FIELD_OFFSET(struct VkInstance_T, phys_devs[phys_dev_count])))) + if (!(instance = vulkan_client_object_create(FIELD_OFFSET(struct VkInstance_T, physical_device[device_count])))) return VK_ERROR_OUT_OF_HOST_MEMORY; - instance->phys_dev_count = phys_dev_count; - for (i = 0; i < phys_dev_count; i++) - instance->phys_devs[i].obj.loader_magic = VULKAN_ICD_MAGIC_VALUE; + instance->physical_device_count = device_count; + for (i = 0; i < device_count; i++) + instance->physical_device[i].obj.loader_magic = VULKAN_ICD_MAGIC_VALUE; instance->extensions = extensions; + *ret = instance;
params.pCreateInfo = create_info; params.pAllocator = allocator; params.pInstance = ret; - params.client_ptr = instance; status = UNIX_CALL(vkCreateInstance, ¶ms); assert(!status); - if (instance->phys_dev_count <= phys_dev_count) + if (instance->physical_device_count <= device_count) break; - phys_dev_count = instance->phys_dev_count; + device_count = instance->physical_device_count; free(instance); + *ret = NULL; }
if (params.result) + { free(instance); + *ret = NULL; + } return params.result; }
diff --git a/dlls/winevulkan/loader_thunks.h b/dlls/winevulkan/loader_thunks.h index a249cd70870..e07b48101df 100644 --- a/dlls/winevulkan/loader_thunks.h +++ b/dlls/winevulkan/loader_thunks.h @@ -3294,7 +3294,6 @@ struct vkCreateInstance_params const VkInstanceCreateInfo *pCreateInfo; const VkAllocationCallbacks *pAllocator; VkInstance *pInstance; - void *client_ptr; VkResult result; };
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 906220922d3..ba8e8695fd1 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -176,8 +176,6 @@ PERF_CRITICAL_FUNCTIONS = [ # part of the driver interface. # - dispatch (default: True): set whether we need a function pointer in the device / instance dispatch table. FUNCTION_OVERRIDES = { - # Global functions - "vkCreateInstance" : {"extra_param" : "client_ptr"}, # Device functions "vkCreateCommandPool" : {"extra_param" : "client_ptr"}, "vkGetDeviceProcAddr" : {"dispatch" : False}, @@ -192,11 +190,13 @@ USER_DRIVER_FUNCS = { "vkCreateDevice", "vkCreateFence", "vkCreateImage", + "vkCreateInstance", "vkCreateSemaphore", "vkCreateSwapchainKHR", "vkCreateWin32SurfaceKHR", "vkDestroyDevice", "vkDestroyFence", + "vkDestroyInstance", "vkDestroySemaphore", "vkDestroySurfaceKHR", "vkDestroySwapchainKHR", @@ -252,7 +252,6 @@ MANUAL_UNIX_THUNKS = { "vkDestroyDebugReportCallbackEXT", "vkDestroyDebugUtilsMessengerEXT", "vkDestroyDeferredOperationKHR", - "vkDestroyInstance", "vkEnumerateDeviceLayerProperties", "vkEnumerateInstanceExtensionProperties", "vkEnumerateInstanceLayerProperties", diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index c05ab552961..4601d3bb3b6 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -35,75 +35,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan); static PFN_vkCreateInstance p_vkCreateInstance; static PFN_vkEnumerateInstanceVersion p_vkEnumerateInstanceVersion; static PFN_vkEnumerateInstanceExtensionProperties p_vkEnumerateInstanceExtensionProperties; -static struct vulkan_instance_extensions instance_extensions; /* supported host instance extensions */ - -static struct wine_instance *wine_instance_from_handle(VkInstance handle) -{ - struct vulkan_instance *object = vulkan_instance_from_handle(handle); - return CONTAINING_RECORD(object, struct wine_instance, obj); -}
static BOOL is_wow64(void) { return sizeof(void *) == sizeof(UINT64) && NtCurrentTeb()->WowTebOffset; }
-static BOOL use_external_memory(void) -{ - return is_wow64(); -} - static ULONG_PTR zero_bits = 0;
const struct vulkan_funcs *vk_funcs;
-static int vulkan_object_compare(const void *key, const struct rb_entry *entry) -{ - struct vulkan_object *object = RB_ENTRY_VALUE(entry, struct vulkan_object, entry); - const uint64_t *host_handle = key; - if (*host_handle < object->host_handle) return -1; - if (*host_handle > object->host_handle) return 1; - return 0; -} - -static void vulkan_instance_insert_object( struct vulkan_instance *instance, struct vulkan_object *obj ) -{ - struct wine_instance *impl = CONTAINING_RECORD(instance, struct wine_instance, obj); - if (impl->objects.compare) - { - pthread_rwlock_wrlock( &impl->objects_lock ); - rb_put( &impl->objects, &obj->host_handle, &obj->entry ); - pthread_rwlock_unlock( &impl->objects_lock ); - } -} - -static void vulkan_instance_remove_object( struct vulkan_instance *instance, struct vulkan_object *obj ) -{ - struct wine_instance *impl = CONTAINING_RECORD(instance, struct wine_instance, obj); - if (impl->objects.compare) - { - pthread_rwlock_wrlock( &impl->objects_lock ); - rb_remove( &impl->objects, &obj->entry ); - pthread_rwlock_unlock( &impl->objects_lock ); - } -} - -static uint64_t client_handle_from_host(struct vulkan_instance *obj, uint64_t host_handle) -{ - struct wine_instance *instance = CONTAINING_RECORD(obj, struct wine_instance, obj); - struct rb_entry *entry; - uint64_t result = 0; - - pthread_rwlock_rdlock(&instance->objects_lock); - if ((entry = rb_get(&instance->objects, &host_handle))) - { - struct vulkan_object *object = RB_ENTRY_VALUE(entry, struct vulkan_object, entry); - result = object->client_handle; - } - pthread_rwlock_unlock(&instance->objects_lock); - return result; -} - static UINT64 call_vulkan_debug_report_callback; static UINT64 call_vulkan_debug_utils_callback;
@@ -213,7 +154,7 @@ static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagB
if (wine_vk_is_type_wrapped(objects[i].object_type)) { - objects[i].object_handle = client_handle_from_host(object->instance, objects[i].object_handle); + objects[i].object_handle = object->instance->p_client_handle_from_host(object->instance, objects[i].object_handle); if (!objects[i].object_handle) { WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle)); @@ -277,7 +218,7 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk params->object_type = object_type; params->location = location; params->code = code; - params->object_handle = client_handle_from_host(object->instance, object_handle); + params->object_handle = object->instance->p_client_handle_from_host(object->instance, object_handle); if (!params->object_handle) params->object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
strings_len = 0; @@ -291,107 +232,6 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk return VK_FALSE; }
-static VkResult vulkan_physical_device_init(struct vulkan_physical_device *physical_device, - VkPhysicalDevice host_physical_device, VkPhysicalDevice client_physical_device, - struct vulkan_instance *instance) -{ - struct vulkan_device_extensions extensions = {0}; - VkExtensionProperties *properties; - uint32_t count; - VkResult res; - - vulkan_object_init_ptr(&physical_device->obj, (UINT_PTR)host_physical_device, &client_physical_device->obj); - physical_device->instance = instance; - - instance->p_vkGetPhysicalDeviceMemoryProperties(host_physical_device, &physical_device->memory_properties); - - if ((res = instance->p_vkEnumerateDeviceExtensionProperties(host_physical_device, NULL, &count, NULL))) return res; - if (!(properties = calloc(count, sizeof(*properties)))) return res; - if ((res = instance->p_vkEnumerateDeviceExtensionProperties(host_physical_device, NULL, &count, properties))) goto done; - - TRACE("Host physical device extensions:\n"); - for (uint32_t i = 0; i < count; i++) - { - const char *extension = properties[i].extensionName; -#define USE_VK_EXT(x) \ - if (!strcmp(extension, #x)) \ - { \ - extensions.has_ ## x = 1; \ - TRACE(" - %s\n", extension); \ - } else - ALL_VK_DEVICE_EXTS -#undef USE_VK_EXT - WARN("Extension %s is not supported.\n", debugstr_a(extension)); - } - physical_device->extensions = extensions; - - if (zero_bits && physical_device->extensions.has_VK_EXT_map_memory_placed && physical_device->extensions.has_VK_KHR_map_memory2) - { - VkPhysicalDeviceMapMemoryPlacedFeaturesEXT map_placed_feature = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT, - }; - VkPhysicalDeviceFeatures2 features = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, - .pNext = &map_placed_feature, - }; - - instance->p_vkGetPhysicalDeviceFeatures2KHR(host_physical_device, &features); - if (map_placed_feature.memoryMapPlaced && map_placed_feature.memoryUnmapReserve) - { - VkPhysicalDeviceMapMemoryPlacedPropertiesEXT map_placed_props = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT, - }; - VkPhysicalDeviceProperties2 props = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, - .pNext = &map_placed_props, - }; - - instance->p_vkGetPhysicalDeviceProperties2(host_physical_device, &props); - physical_device->map_placed_align = map_placed_props.minPlacedMemoryMapAlignment; - TRACE( "Using placed map with alignment %u\n", physical_device->map_placed_align ); - } - } - - if (zero_bits && physical_device->extensions.has_VK_EXT_external_memory_host && !physical_device->map_placed_align) - { - VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_mem_props = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT, - }; - VkPhysicalDeviceProperties2 props = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, - .pNext = &host_mem_props, - }; - instance->p_vkGetPhysicalDeviceProperties2KHR(host_physical_device, &props); - physical_device->external_memory_align = host_mem_props.minImportedHostPointerAlignment; - if (physical_device->external_memory_align) - TRACE("Using VK_EXT_external_memory_host for memory mapping with alignment: %u\n", - physical_device->external_memory_align); - } - - vk_funcs->p_map_device_extensions(&extensions); - if (extensions.has_VK_KHR_external_memory_win32 && zero_bits && !physical_device->map_placed_align) - { - WARN("Cannot export WOW64 memory without VK_EXT_map_memory_placed\n"); - extensions.has_VK_KHR_external_memory_win32 = 0; - } - extensions.has_VK_KHR_win32_keyed_mutex = extensions.has_VK_KHR_timeline_semaphore; - - /* filter out unsupported client device extensions */ -#define USE_VK_EXT(x) client_physical_device->extensions.has_ ## x = extensions.has_ ## x; - ALL_VK_CLIENT_DEVICE_EXTS -#undef USE_VK_EXT - -done: - free(properties); - return res; -} - static void wine_vk_free_command_buffers(struct vulkan_device *device, struct wine_cmd_pool *pool, uint32_t count, const VkCommandBuffer *buffers) { @@ -409,7 +249,7 @@ static void wine_vk_free_command_buffers(struct vulkan_device *device,
device->p_vkFreeCommandBuffers(device->host.device, pool->host.command_pool, 1, &buffer->host.command_buffer); - vulkan_instance_remove_object(instance, &buffer->obj); + instance->p_remove_object(instance, &buffer->obj); buffer->client.command_buffer->obj.unix_handle = 0; free(buffer); } @@ -417,11 +257,7 @@ static void wine_vk_free_command_buffers(struct vulkan_device *device,
NTSTATUS init_vulkan(void *arg) { - struct vulkan_instance_extensions extensions = {0}; - VkExtensionProperties *properties = NULL; const struct init_params *params = arg; - uint32_t count = 0; - VkResult res;
vk_funcs = __wine_get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION); if (!vk_funcs) @@ -445,43 +281,8 @@ NTSTATUS init_vulkan(void *arg) zero_bits = (ULONG_PTR)info.HighestUserAddress | 0x7fffffff; }
- do - { - free(properties); - properties = NULL; - if ((res = p_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL))) goto failed; - if (!count || !(properties = malloc(count * sizeof(*properties)))) return STATUS_UNSUCCESSFUL; - } while ((res = p_vkEnumerateInstanceExtensionProperties(NULL, &count, properties) == VK_INCOMPLETE)); - if (res) goto failed; - - TRACE("Host instance extensions:\n"); - for (uint32_t i = 0; i < count; i++) - { - const char *extension = properties[i].extensionName; -#define USE_VK_EXT(x) \ - if (!strcmp(extension, #x)) \ - { \ - extensions.has_ ## x = 1; \ - TRACE(" - %s\n", extension); \ - } else - ALL_VK_INSTANCE_EXTS -#undef USE_VK_EXT - WARN("Extension %s is not supported.\n", debugstr_a(extension)); - } - instance_extensions = extensions; - - /* map host instance extensions for VK_KHR_win32_surface */ - vk_funcs->p_map_instance_extensions(&extensions); - - /* filter out unsupported client instance extensions */ -#define USE_VK_EXT(x) params->extensions->has_ ## x = extensions.has_ ## x; - ALL_VK_CLIENT_INSTANCE_EXTS -#undef USE_VK_EXT - -failed: - free(properties); - if (res) ERR("Failed to initialize Vulkan, res %d\n", res); - return res ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS; + *params->extensions = vk_funcs->client_extensions; + return STATUS_SUCCESS; }
static void free_debug_utils_messengers(struct list *messengers) @@ -506,134 +307,6 @@ static void free_debug_report_callbacks(struct list *callbacks) } }
-/* 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(struct conversion_context *ctx, - const VkInstanceCreateInfo *src, VkInstanceCreateInfo *dst, struct wine_instance *instance) -{ - VkDebugReportCallbackCreateInfoEXT *debug_report_callback; - VkBaseInStructure *header = (VkBaseInStructure *)dst; - const char **extensions; - uint32_t count = 0; - - *dst = *src; - - while ((header = find_next_struct(header->pNext, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT))) - { - VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *)header; - struct vulkan_debug_utils_messenger *messenger = debug_utils_messenger->pUserData; - - list_remove(&messenger->entry); - list_add_tail(&instance->utils_messengers, &messenger->entry); - messenger->instance = &instance->obj; - } - - if ((debug_report_callback = find_next_struct(dst->pNext, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT))) - { - struct vulkan_debug_report_callback *callback = debug_report_callback->pUserData; - - list_remove(&callback->entry); - list_add_tail(&instance->report_callbacks, &callback->entry); - callback->instance = &instance->obj; - } - - /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader - * filter this data out as well. - */ - if (dst->enabledLayerCount) - { - FIXME("Loading explicit layers is not supported by winevulkan!\n"); - return VK_ERROR_LAYER_NOT_PRESENT; - } - - vk_funcs->p_map_instance_extensions(&instance->obj.extensions); - instance->obj.extensions.has_VK_KHR_win32_surface = 0; - - if (instance->obj.extensions.has_VK_EXT_debug_utils || instance->obj.extensions.has_VK_EXT_debug_report) - { - rb_init(&instance->objects, vulkan_object_compare); - pthread_rwlock_init(&instance->objects_lock, NULL); - } - - if (instance->obj.extensions.has_VK_KHR_win32_surface && instance_extensions.has_VK_EXT_surface_maintenance1) - instance->obj.extensions.has_VK_EXT_surface_maintenance1 = 1; - if (use_external_memory()) - { - instance->obj.extensions.has_VK_KHR_get_physical_device_properties2 = 1; - instance->obj.extensions.has_VK_KHR_external_memory_capabilities = 1; - } - - extensions = conversion_context_alloc(ctx, sizeof(instance->obj.extensions) * 8 * sizeof(*extensions)); -#define USE_VK_EXT(x) if (instance->obj.extensions.has_ ## x) extensions[count++] = #x; - ALL_VK_INSTANCE_EXTS -#undef USE_VK_EXT - - TRACE("Enabling %u host instance extensions\n", count); - for (const char **extension = extensions, **end = extension + count; extension < end; extension++) - TRACE(" - %s\n", debugstr_a(*extension)); - - dst->ppEnabledExtensionNames = extensions; - dst->enabledExtensionCount = count; - return VK_SUCCESS; -} - -/* Helper function which stores wrapped physical devices in the instance object. */ -static VkResult wine_vk_instance_init_physical_devices(struct vulkan_instance *instance, - struct vulkan_physical_device *physical_devices) -{ - VkInstance client_instance = instance->client.instance; - VkPhysicalDevice *host_physical_devices; - uint32_t phys_dev_count; - unsigned int i; - VkResult res; - - res = instance->p_vkEnumeratePhysicalDevices(instance->host.instance, &phys_dev_count, NULL); - if (res != VK_SUCCESS) - { - ERR("Failed to enumerate physical devices, res=%d\n", res); - return res; - } - if (!phys_dev_count) - return res; - - if (phys_dev_count > client_instance->phys_dev_count) - { - client_instance->phys_dev_count = phys_dev_count; - return VK_ERROR_OUT_OF_POOL_MEMORY; - } - client_instance->phys_dev_count = phys_dev_count; - - if (!(host_physical_devices = calloc(phys_dev_count, sizeof(*host_physical_devices)))) - return VK_ERROR_OUT_OF_HOST_MEMORY; - - res = instance->p_vkEnumeratePhysicalDevices(instance->host.instance, &phys_dev_count, host_physical_devices); - if (res != VK_SUCCESS) - { - free(host_physical_devices); - return res; - } - - /* Wrap each host physical device handle into a dispatchable object for the ICD loader. */ - for (i = 0; i < phys_dev_count; i++) - { - struct vulkan_physical_device *physical_device = physical_devices + i; - res = vulkan_physical_device_init(physical_device, host_physical_devices[i], &client_instance->phys_devs[i], instance); - if (res != VK_SUCCESS) - goto err; - } - instance->physical_device_count = phys_dev_count; - instance->physical_devices = physical_devices; - - free(host_physical_devices); - return VK_SUCCESS; - -err: - free(host_physical_devices); - return res; -} - static struct vulkan_physical_device *vulkan_instance_get_physical_device(struct vulkan_instance *instance, VkPhysicalDevice host_physical_device) { @@ -695,7 +368,7 @@ VkResult wine_vkAllocateCommandBuffers(VkDevice client_device, const VkCommandBu
vulkan_object_init_ptr(&buffer->obj, (UINT_PTR)host_command_buffer, &client_command_buffer->obj); buffer->device = device; - vulkan_instance_insert_object(instance, &buffer->obj); + instance->p_insert_object(instance, &buffer->obj); }
if (res != VK_SUCCESS) @@ -704,21 +377,13 @@ VkResult wine_vkAllocateCommandBuffers(VkDevice client_device, const VkCommandBu return res; }
-VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *client_create_info, - const VkAllocationCallbacks *allocator, VkInstance *ret, - void *client_ptr) +VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *client_create_info, const VkAllocationCallbacks *allocator, + VkInstance *client_instance_ptr) { VkInstanceCreateInfo *create_info = (VkInstanceCreateInfo *)client_create_info; /* cast away const, chain has been copied in the thunks */ struct list utils_messengers = LIST_INIT(utils_messengers), report_callbacks = LIST_INIT(report_callbacks); VkBaseInStructure *header = (VkBaseInStructure *)create_info; VkDebugReportCallbackCreateInfoEXT *debug_report_callback; - VkInstanceCreateInfo create_info_host; - struct conversion_context ctx; - struct wine_instance *instance; - VkInstance host_instance, client_instance = client_ptr; - struct vulkan_physical_device *physical_devices; - unsigned int i; - VkResult res;
while ((header = find_next_struct(header->pNext, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT))) { @@ -749,70 +414,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *client_create_info, list_add_tail(&report_callbacks, &report_callback->entry); }
- if (!(instance = calloc(1, sizeof(*instance) + sizeof(*physical_devices) * client_instance->phys_dev_count))) - { - ERR("Failed to allocate memory for instance\n"); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - physical_devices = (struct vulkan_physical_device *)(instance + 1); - instance->obj.extensions = client_instance->extensions; - list_init(&instance->utils_messengers); - list_init(&instance->report_callbacks); - - init_conversion_context(&ctx); - res = wine_vk_instance_convert_create_info(&ctx, create_info, &create_info_host, instance); - if (res == VK_SUCCESS) - res = p_vkCreateInstance(&create_info_host, NULL /* allocator */, &host_instance); - free_conversion_context(&ctx); - if (res != VK_SUCCESS) - { - ERR("Failed to create instance, res=%d\n", res); - free_debug_utils_messengers(&instance->utils_messengers); - free_debug_report_callbacks(&instance->report_callbacks); - free(instance); - return res; - } - - vulkan_object_init_ptr(&instance->obj.obj, (UINT_PTR)host_instance, &client_instance->obj); - instance->obj.p_insert_object = vulkan_instance_insert_object; - instance->obj.p_remove_object = vulkan_instance_remove_object; - - /* Load all instance functions we are aware of. Note the loader takes care - * of any filtering for extensions which were not requested, but which the - * ICD may support. - */ -#define USE_VK_FUNC(name) \ - instance->obj.p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr(instance->obj.host.instance, #name); - ALL_VK_INSTANCE_FUNCS -#undef USE_VK_FUNC - - /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as - * each vkPhysicalDevice is a dispatchable object, which means we need to wrap - * the host physical devices and present those to the application. - * Cleanup happens as part of wine_vkDestroyInstance. - */ - res = wine_vk_instance_init_physical_devices(&instance->obj, physical_devices); - if (res != VK_SUCCESS) - { - ERR("Failed to load physical devices, res=%d\n", res); - instance->obj.p_vkDestroyInstance(instance->obj.host.instance, NULL /* allocator */); - free_debug_utils_messengers(&instance->utils_messengers); - free_debug_report_callbacks(&instance->report_callbacks); - free(instance); - return res; - } - - TRACE("Created instance %p, host_instance %p.\n", instance, instance->obj.host.instance); - - for (i = 0; i < instance->obj.physical_device_count; i++) - { - struct vulkan_physical_device *physical_device = &instance->obj.physical_devices[i]; - vulkan_instance_insert_object(&instance->obj, &physical_device->obj); - } - vulkan_instance_insert_object(&instance->obj, &instance->obj.obj); - - *ret = client_instance; - return VK_SUCCESS; + return vk_funcs->p_vkCreateInstance(create_info, NULL /* allocator */, client_instance_ptr);
failed: free_debug_utils_messengers(&utils_messengers); @@ -820,27 +422,6 @@ failed: return VK_ERROR_OUT_OF_HOST_MEMORY; }
-void wine_vkDestroyInstance(VkInstance client_instance, const VkAllocationCallbacks *allocator) -{ - struct wine_instance *instance = wine_instance_from_handle(client_instance); - unsigned int i; - - if (allocator) - FIXME("Support allocation allocators\n"); - if (!instance) - return; - - instance->obj.p_vkDestroyInstance(instance->obj.host.instance, NULL /* allocator */); - for (i = 0; i < instance->obj.physical_device_count; i++) - vulkan_instance_remove_object(&instance->obj, &instance->obj.physical_devices[i].obj); - vulkan_instance_remove_object(&instance->obj, &instance->obj.obj); - - if (instance->objects.compare) pthread_rwlock_destroy(&instance->objects_lock); - free_debug_utils_messengers(&instance->utils_messengers); - free_debug_report_callbacks(&instance->report_callbacks); - free(instance); -} - VkResult wine_vkEnumerateInstanceExtensionProperties(const char *name, uint32_t *count, VkExtensionProperties *properties) { @@ -929,7 +510,7 @@ VkResult wine_vkCreateCommandPool(VkDevice client_device, const VkCommandPoolCre }
vulkan_object_init_ptr(&object->obj, host_command_pool, &client_command_pool->obj); - vulkan_instance_insert_object(instance, &object->obj); + instance->p_insert_object(instance, &object->obj);
*command_pool = object->client.command_pool; return VK_SUCCESS; @@ -946,7 +527,7 @@ void wine_vkDestroyCommandPool(VkDevice client_device, VkCommandPool handle, FIXME("Support for allocation callbacks not implemented yet\n");
device->p_vkDestroyCommandPool(device->host.device, pool->host.command_pool, NULL); - vulkan_instance_remove_object(instance, &pool->obj); + instance->p_remove_object(instance, &pool->obj); free(pool); }
@@ -1267,7 +848,7 @@ VkResult wine_vkCreateDebugUtilsMessengerEXT(VkInstance client_instance, object->instance = instance; object->user_callback = (UINT_PTR)create_info->pfnUserCallback; object->user_data = (UINT_PTR)create_info->pUserData; - vulkan_instance_insert_object(instance, &object->obj); + instance->p_insert_object(instance, &object->obj);
*messenger = object->client.debug_messenger; return VK_SUCCESS; @@ -1285,7 +866,7 @@ void wine_vkDestroyDebugUtilsMessengerEXT(VkInstance client_instance, VkDebugUti return;
instance->p_vkDestroyDebugUtilsMessengerEXT(instance->host.instance, object->host.debug_messenger, NULL); - vulkan_instance_remove_object(instance, &object->obj); + instance->p_remove_object(instance, &object->obj);
free(object); } @@ -1323,7 +904,7 @@ VkResult wine_vkCreateDebugReportCallbackEXT(VkInstance client_instance, object->instance = instance; object->user_callback = (UINT_PTR)create_info->pfnCallback; object->user_data = (UINT_PTR)create_info->pUserData; - vulkan_instance_insert_object(instance, &object->obj); + instance->p_insert_object(instance, &object->obj);
*callback = object->client.debug_callback; return VK_SUCCESS; @@ -1341,7 +922,7 @@ void wine_vkDestroyDebugReportCallbackEXT(VkInstance client_instance, VkDebugRep return;
instance->p_vkDestroyDebugReportCallbackEXT(instance->host.instance, object->host.debug_callback, NULL); - vulkan_instance_remove_object(instance, &object->obj); + instance->p_remove_object(instance, &object->obj);
free(object); } @@ -1371,7 +952,7 @@ VkResult wine_vkCreateDeferredOperationKHR(VkDevice device_handle,
vulkan_object_init(&object->obj, host_deferred_operation); init_conversion_context(&object->ctx); - vulkan_instance_insert_object(instance, &object->obj); + instance->p_insert_object(instance, &object->obj);
*operation = object->client.deferred_operation; return VK_SUCCESS; @@ -1391,7 +972,7 @@ void wine_vkDestroyDeferredOperationKHR(VkDevice device_handle, return;
device->p_vkDestroyDeferredOperationKHR(device->host.device, object->host.deferred_operation, NULL); - vulkan_instance_remove_object(instance, &object->obj); + instance->p_remove_object(instance, &object->obj);
free_conversion_context(&object->ctx); free(object); diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 2419c8554bd..0497c19add2 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -51368,7 +51368,7 @@ static NTSTATUS thunk64_vkCreateInstance(void *args)
init_conversion_context(ctx); convert_VkInstanceCreateInfo_win64_to_host(ctx, params->pCreateInfo, &pCreateInfo_host); - params->result = wine_vkCreateInstance(&pCreateInfo_host, params->pAllocator, params->pInstance, params->client_ptr); + params->result = wine_vkCreateInstance(&pCreateInfo_host, params->pAllocator, params->pInstance); free_conversion_context(ctx); return STATUS_SUCCESS; } @@ -51381,7 +51381,6 @@ static NTSTATUS thunk32_vkCreateInstance(void *args) PTR32 pCreateInfo; PTR32 pAllocator; PTR32 pInstance; - PTR32 client_ptr; VkResult result; } *params = args; VkInstanceCreateInfo pCreateInfo_host; @@ -51394,7 +51393,7 @@ static NTSTATUS thunk32_vkCreateInstance(void *args) init_conversion_context(ctx); convert_VkInstanceCreateInfo_win32_to_host(ctx, (const VkInstanceCreateInfo32 *)UlongToPtr(params->pCreateInfo), &pCreateInfo_host); pInstance_host = UlongToPtr(*(PTR32 *)UlongToPtr(params->pInstance)); - params->result = wine_vkCreateInstance(&pCreateInfo_host, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator), &pInstance_host, UlongToPtr(params->client_ptr)); + params->result = wine_vkCreateInstance(&pCreateInfo_host, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator), &pInstance_host); *(PTR32 *)UlongToPtr(params->pInstance) = PtrToUlong(pInstance_host); free_conversion_context(ctx); return STATUS_SUCCESS; @@ -53103,7 +53102,7 @@ static NTSTATUS thunk64_vkDestroyInstance(void *args) if (!params->instance) return STATUS_SUCCESS;
- wine_vkDestroyInstance(params->instance, params->pAllocator); + vk_funcs->p_vkDestroyInstance(params->instance, params->pAllocator); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -53121,7 +53120,7 @@ static NTSTATUS thunk32_vkDestroyInstance(void *args) if (!params->instance) return STATUS_SUCCESS;
- wine_vkDestroyInstance((VkInstance)UlongToPtr(params->instance), (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator)); + vk_funcs->p_vkDestroyInstance((VkInstance)UlongToPtr(params->instance), (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator)); return STATUS_SUCCESS; }
diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index fccc2cc3923..52af356d5c6 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -26,12 +26,11 @@ VkResult wine_vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo VkResult wine_vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback); VkResult wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger); VkResult wine_vkCreateDeferredOperationKHR(VkDevice device, const VkAllocationCallbacks *pAllocator, VkDeferredOperationKHR *pDeferredOperation); -VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance, void *client_ptr); +VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance); void wine_vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyDeferredOperationKHR(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks *pAllocator); -void wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator); VkResult wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkLayerProperties *pProperties); VkResult wine_vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties); VkResult wine_vkEnumerateInstanceVersion(uint32_t *pApiVersion); diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index 614a450a9ee..d2e2db3e360 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -67,8 +67,8 @@ struct VkInstance_T { struct vulkan_client_object obj; struct vulkan_instance_extensions extensions; - uint32_t phys_dev_count; - struct VkPhysicalDevice_T phys_devs[1]; + UINT physical_device_count; + struct VkPhysicalDevice_T physical_device[1]; };
struct VkQueue_T @@ -159,6 +159,7 @@ struct vulkan_instance #undef USE_VK_FUNC void (*p_insert_object)( struct vulkan_instance *instance, struct vulkan_object *obj ); void (*p_remove_object)( struct vulkan_instance *instance, struct vulkan_object *obj ); + uint64_t (*p_client_handle_from_host)( struct vulkan_instance *instance, uint64_t host_handle );
struct vulkan_physical_device *physical_devices; uint32_t physical_device_count; @@ -288,6 +289,9 @@ static inline struct vulkan_fence *vulkan_fence_from_handle( VkFence handle )
struct vulkan_funcs { + struct vulkan_instance_extensions host_extensions; + struct vulkan_instance_extensions client_extensions; + /* Vulkan global functions. These are the only calls at this point a graphics driver * needs to provide. Other function calls will be provided indirectly by dispatch * tables part of dispatchable Vulkan objects such as VkInstance or vkDevice. @@ -299,11 +303,13 @@ struct vulkan_funcs PFN_vkCreateDevice p_vkCreateDevice; PFN_vkCreateFence p_vkCreateFence; PFN_vkCreateImage p_vkCreateImage; + PFN_vkCreateInstance p_vkCreateInstance; PFN_vkCreateSemaphore p_vkCreateSemaphore; PFN_vkCreateSwapchainKHR p_vkCreateSwapchainKHR; PFN_vkCreateWin32SurfaceKHR p_vkCreateWin32SurfaceKHR; PFN_vkDestroyDevice p_vkDestroyDevice; PFN_vkDestroyFence p_vkDestroyFence; + PFN_vkDestroyInstance p_vkDestroyInstance; PFN_vkDestroySemaphore p_vkDestroySemaphore; PFN_vkDestroySurfaceKHR p_vkDestroySurfaceKHR; PFN_vkDestroySwapchainKHR p_vkDestroySwapchainKHR; @@ -345,10 +351,6 @@ struct vulkan_funcs PFN_vkQueueSubmit2KHR p_vkQueueSubmit2KHR; PFN_vkUnmapMemory p_vkUnmapMemory; PFN_vkUnmapMemory2KHR p_vkUnmapMemory2KHR; - - /* winevulkan specific functions */ - void (*p_map_instance_extensions)( struct vulkan_instance_extensions *extensions ); - void (*p_map_device_extensions)( struct vulkan_device_extensions *extensions ); };
/* interface between win32u and the user drivers */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 154 ++++++++++------------------------- dlls/win32u/ntuser_private.h | 5 +- dlls/win32u/vulkan.c | 60 +++++++++++--- 3 files changed, 93 insertions(+), 126 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 98f6b935d6f..6ee00d43511 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -165,14 +165,13 @@ struct d3dkmt_resource
struct d3dkmt_adapter { - struct d3dkmt_object obj; /* object header */ - LUID luid; /* LUID of the adapter */ + struct d3dkmt_object obj; + struct vulkan_physical_device *physical_device; };
struct d3dkmt_device { - struct d3dkmt_object obj; /* object header */ - LUID luid; /* LUID of the device adapter */ + struct d3dkmt_object obj; };
struct d3dkmt_vidpn_source @@ -486,63 +485,25 @@ static unsigned int alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, stru return STATUS_SUCCESS; }
-static VkInstance d3dkmt_vk_instance; /* Vulkan instance for D3DKMT functions */ -static PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryProperties2KHR; -static PFN_vkGetPhysicalDeviceMemoryProperties pvkGetPhysicalDeviceMemoryProperties; -static PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR; -static PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices; +static struct vulkan_instance *d3dkmt_vulkan_instance; /* Vulkan instance for D3DKMT functions */
static void d3dkmt_init_vulkan(void) { - static const char *extensions[] = + static const struct vulkan_instance_extensions extensions = { - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, + .has_VK_KHR_get_physical_device_properties2 = 1, + .has_VK_KHR_external_memory_capabilities = 1, }; - VkInstanceCreateInfo create_info = - { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .enabledExtensionCount = ARRAY_SIZE( extensions ), - .ppEnabledExtensionNames = extensions, - }; - PFN_vkDestroyInstance p_vkDestroyInstance; - PFN_vkCreateInstance p_vkCreateInstance; - VkResult vr;
- if (!vulkan_init()) - { - WARN( "Failed to open the Vulkan driver\n" ); - return; - } - - p_vkCreateInstance = (PFN_vkCreateInstance)p_vkGetInstanceProcAddr( NULL, "vkCreateInstance" ); - if ((vr = p_vkCreateInstance( &create_info, NULL, &d3dkmt_vk_instance ))) - { - WARN( "Failed to create a Vulkan instance, vr %d.\n", vr ); - return; - } - - p_vkDestroyInstance = (PFN_vkDestroyInstance)p_vkGetInstanceProcAddr( d3dkmt_vk_instance, "vkDestroyInstance" ); -#define LOAD_VK_FUNC( f ) \ - if (!(p##f = (void *)p_vkGetInstanceProcAddr( d3dkmt_vk_instance, #f ))) \ - { \ - WARN( "Failed to load " #f ".\n" ); \ - p_vkDestroyInstance( d3dkmt_vk_instance, NULL ); \ - d3dkmt_vk_instance = NULL; \ - return; \ - } - LOAD_VK_FUNC( vkEnumeratePhysicalDevices ) - LOAD_VK_FUNC( vkGetPhysicalDeviceProperties2KHR ) - LOAD_VK_FUNC( vkGetPhysicalDeviceMemoryProperties ) - LOAD_VK_FUNC( vkGetPhysicalDeviceMemoryProperties2KHR ) -#undef LOAD_VK_FUNC + d3dkmt_vulkan_instance = vulkan_instance_create( &extensions ); + if (!d3dkmt_vulkan_instance) ERR( "Failed to create the vulkan instance\n" ); }
-static BOOL d3dkmt_use_vulkan(void) +static struct vulkan_instance *get_d3dkmt_vulkan_instance(void) { static pthread_once_t once = PTHREAD_ONCE_INIT; pthread_once( &once, d3dkmt_init_vulkan ); - return !!d3dkmt_vk_instance; + return d3dkmt_vulkan_instance; }
static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *attr ) @@ -608,58 +569,27 @@ NTSTATUS WINAPI NtGdiDdDDICloseAdapter( const D3DKMT_CLOSEADAPTER *desc ) return STATUS_SUCCESS; }
-static UINT get_vulkan_physical_devices( VkPhysicalDevice **devices ) -{ - UINT device_count; - VkResult vr; - - if ((vr = pvkEnumeratePhysicalDevices( d3dkmt_vk_instance, &device_count, NULL ))) - { - WARN( "vkEnumeratePhysicalDevices returned %d\n", vr ); - return 0; - } - - if (!device_count || !(*devices = malloc( device_count * sizeof(**devices) ))) return 0; - - if ((vr = pvkEnumeratePhysicalDevices( d3dkmt_vk_instance, &device_count, *devices ))) - { - WARN( "vkEnumeratePhysicalDevices returned %d\n", vr ); - free( *devices ); - return 0; - } - - return device_count; -} - -static VkPhysicalDevice get_vulkan_physical_device( const LUID *luid ) +static struct vulkan_physical_device *get_vulkan_physical_device( struct vulkan_instance *instance, const LUID *luid ) { - VkPhysicalDevice *devices, device; - UINT device_count, i; GUID uuid;
if (!get_vulkan_uuid_from_luid( luid, &uuid )) { WARN( "Failed to find Vulkan device with LUID %08x:%08x.\n", luid->HighPart, luid->LowPart ); - return VK_NULL_HANDLE; + return NULL; }
- if (!(device_count = get_vulkan_physical_devices( &devices ))) return VK_NULL_HANDLE; - - for (i = 0, device = VK_NULL_HANDLE; i < device_count; ++i) + for (UINT i = 0; i < instance->physical_device_count; ++i) { VkPhysicalDeviceIDProperties id = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES}; VkPhysicalDeviceProperties2 properties2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .pNext = &id}; + struct vulkan_physical_device *physical_device = instance->physical_devices + i;
- pvkGetPhysicalDeviceProperties2KHR( devices[i], &properties2 ); - if (IsEqualGUID( &uuid, id.deviceUUID )) - { - device = devices[i]; - break; - } + instance->p_vkGetPhysicalDeviceProperties2KHR( physical_device->host.physical_device, &properties2 ); + if (IsEqualGUID( &uuid, id.deviceUUID )) return physical_device; }
- free( devices ); - return device; + return NULL; }
/****************************************************************************** @@ -667,15 +597,16 @@ static VkPhysicalDevice get_vulkan_physical_device( const LUID *luid ) */ NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc ) { + struct vulkan_instance *instance; struct d3dkmt_adapter *adapter; NTSTATUS status;
if ((status = d3dkmt_object_alloc( sizeof(*adapter), D3DKMT_ADAPTER, (void **)&adapter ))) return status; if ((status = alloc_object_handle( &adapter->obj ))) goto failed;
- if (!d3dkmt_use_vulkan()) WARN( "Vulkan is unavailable.\n" ); - else if (!get_vulkan_physical_device( &desc->AdapterLuid )) WARN( "Failed to find vulkan device\n" ); - else adapter->luid = desc->AdapterLuid; + if (!(instance = get_d3dkmt_vulkan_instance())) WARN( "Vulkan is unavailable.\n" ); + else adapter->physical_device = get_vulkan_physical_device( instance, &desc->AdapterLuid ); + if (!adapter->physical_device) WARN( "Failed to find Vulkan physical device\n" );
desc->hAdapter = adapter->obj.local; return STATUS_SUCCESS; @@ -703,8 +634,6 @@ NTSTATUS WINAPI NtGdiDdDDICreateDevice( D3DKMT_CREATEDEVICE *desc ) if ((status = d3dkmt_object_alloc( sizeof(*device), D3DKMT_DEVICE, (void **)&device ))) return status; if ((status = alloc_object_handle( &device->obj ))) goto failed;
- device->luid = adapter->luid; - desc->hDevice = device->obj.local; return STATUS_SUCCESS;
@@ -788,8 +717,8 @@ NTSTATUS WINAPI NtGdiDdDDIQueryStatistics( D3DKMT_QUERYSTATISTICS *stats ) NTSTATUS WINAPI NtGdiDdDDIQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc ) { VkPhysicalDeviceMemoryBudgetPropertiesEXT budget; + struct vulkan_physical_device *physical_device; VkPhysicalDeviceMemoryProperties2 properties2; - VkPhysicalDevice phys_dev; struct d3dkmt_adapter *adapter; OBJECT_BASIC_INFORMATION info; NTSTATUS status; @@ -817,13 +746,16 @@ NTSTATUS WINAPI NtGdiDdDDIQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *des desc->CurrentReservation = 0; desc->AvailableForReservation = 0;
- if ((phys_dev = get_vulkan_physical_device( &adapter->luid ))) + if ((physical_device = adapter->physical_device)) { + struct vulkan_instance *instance = physical_device->instance; + memset( &budget, 0, sizeof(budget) ); budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; properties2.pNext = &budget; - pvkGetPhysicalDeviceMemoryProperties2KHR( phys_dev, &properties2 ); + + instance->p_vkGetPhysicalDeviceMemoryProperties2KHR( physical_device->host.physical_device, &properties2 ); for (i = 0; i < properties2.memoryProperties.memoryHeapCount; ++i) { if ((desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL && @@ -835,9 +767,12 @@ NTSTATUS WINAPI NtGdiDdDDIQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *des desc->CurrentUsage += min( budget.heapBudget[i], budget.heapUsage[i] ); } } + desc->AvailableForReservation = desc->Budget / 2; + return STATUS_SUCCESS; }
+ WARN( "Failed to find Vulkan physical device\n" ); return STATUS_SUCCESS; }
@@ -1020,29 +955,27 @@ static int compare_vulkan_physical_devices( const void *v1, const void *v2 )
BOOL get_vulkan_gpus( struct list *gpus ) { + struct vulkan_instance *instance; struct vk_physdev_info *devinfo; - VkPhysicalDevice *devices; - UINT i, j, count; + UINT i, j;
- if (!d3dkmt_use_vulkan()) return FALSE; - if (!(count = get_vulkan_physical_devices( &devices ))) return FALSE; + if (!(instance = get_d3dkmt_vulkan_instance())) return FALSE; + if (!(devinfo = calloc( instance->physical_device_count, sizeof(*devinfo) ))) return FALSE;
- if (!(devinfo = calloc( count, sizeof(*devinfo) ))) - { - free( devices ); - return FALSE; - } - for (i = 0; i < count; ++i) + for (i = 0; i < instance->physical_device_count; ++i) { + struct vulkan_physical_device *physical_device = instance->physical_devices + i; + devinfo[i].id.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; devinfo[i].properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; devinfo[i].properties2.pNext = &devinfo[i].id; - pvkGetPhysicalDeviceProperties2KHR( devices[i], &devinfo[i].properties2 ); - pvkGetPhysicalDeviceMemoryProperties( devices[i], &devinfo[i].mem_properties ); + + instance->p_vkGetPhysicalDeviceProperties2KHR( physical_device->host.physical_device, &devinfo[i].properties2 ); + instance->p_vkGetPhysicalDeviceMemoryProperties( physical_device->host.physical_device, &devinfo[i].mem_properties ); } - qsort( devinfo, count, sizeof(*devinfo), compare_vulkan_physical_devices ); + qsort( devinfo, instance->physical_device_count, sizeof(*devinfo), compare_vulkan_physical_devices );
- for (i = 0; i < count; ++i) + for (i = 0; i < instance->physical_device_count; ++i) { struct vulkan_gpu *gpu;
@@ -1062,7 +995,6 @@ BOOL get_vulkan_gpus( struct list *gpus ) }
free( devinfo ); - free( devices ); return TRUE; }
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 1d0131e5886..005db332e7a 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -219,10 +219,7 @@ extern void check_for_events( UINT flags ); extern LRESULT system_tray_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void *data );
/* vulkan.c */ -extern PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr; -extern PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr; - -extern BOOL vulkan_init(void); +extern struct vulkan_instance *vulkan_instance_create( const struct vulkan_instance_extensions *extensions );
/* window.c */ HANDLE alloc_user_handle( void *ptr, unsigned short type ); diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 9d5dcdd8683..281bc24ca85 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -35,8 +35,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
-PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr = NULL; -PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr = NULL; +static PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr; +static PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr; static PFN_vkCreateInstance p_vkCreateInstance; static PFN_vkEnumerateInstanceExtensionProperties p_vkEnumerateInstanceExtensionProperties;
@@ -606,7 +606,8 @@ static VkResult win32u_vkCreateInstance( const VkInstanceCreateInfo *client_crea unsigned int i; VkResult res;
- if (!(instance = calloc( 1, sizeof(*instance) + sizeof(*physical_devices) * client_instance->physical_device_count) )) return VK_ERROR_OUT_OF_HOST_MEMORY; + if (!(instance = calloc( 1, sizeof(*instance) + sizeof(*physical_devices) * client_instance->physical_device_count) )) + return VK_ERROR_OUT_OF_HOST_MEMORY; physical_devices = (struct vulkan_physical_device *)(instance + 1); instance->obj.extensions = client_instance->extensions; list_init( &instance->utils_messengers ); @@ -3052,24 +3053,61 @@ static void vulkan_init_once(void)
#endif /* SONAME_LIBVULKAN */
-BOOL vulkan_init(void) -{ - static pthread_once_t init_once = PTHREAD_ONCE_INIT; - pthread_once( &init_once, vulkan_init_once ); - return !!vulkan_handle; -} - /*********************************************************************** * __wine_get_vulkan_driver (win32u.so) */ const struct vulkan_funcs *__wine_get_vulkan_driver( UINT version ) { + static pthread_once_t init_once = PTHREAD_ONCE_INIT; + if (version != WINE_VULKAN_DRIVER_VERSION) { ERR( "version mismatch, vulkan wants %u but win32u has %u\n", version, WINE_VULKAN_DRIVER_VERSION ); return NULL; }
- if (!vulkan_init()) return NULL; + pthread_once( &init_once, vulkan_init_once ); + if (!vulkan_handle) return NULL; return &vulkan_funcs; } + +/* unix side client-like instance wrapper to fit with the vulkan wrapping infrastructure */ +struct instance_wrapper +{ + struct VkInstance_T client; +}; + +struct vulkan_instance *vulkan_instance_create( const struct vulkan_instance_extensions *extensions ) +{ + const struct vulkan_funcs *funcs = __wine_get_vulkan_driver( WINE_VULKAN_DRIVER_VERSION ); + VkInstanceCreateInfo create_info = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO}; + const char *extension_names[sizeof(*extensions) * 8]; + struct instance_wrapper *wrapper; + UINT device_count = 8; + VkResult res; + + create_info.ppEnabledExtensionNames = extension_names; +#define USE_VK_EXT(x) if (extensions->has_ ## x) extension_names[create_info.enabledExtensionCount++] = #x; + ALL_VK_INSTANCE_EXTS +#undef USE_VK_EXT + + for (;;) + { + VkInstance instance; + + if (!(wrapper = calloc( 1, offsetof(struct instance_wrapper, client.physical_device[device_count]) ))) return NULL; + wrapper->client.physical_device_count = device_count; + wrapper->client.extensions = *extensions; + instance = &wrapper->client; + + if ((res = funcs->p_vkCreateInstance( &create_info, NULL, &instance ))) break; + if ((wrapper->client.physical_device_count <= device_count)) break; + device_count = wrapper->client.physical_device_count; + free( wrapper ); + } + + if (!res) return vulkan_instance_from_handle( &wrapper->client ); + ERR( "Failed to create instance, res %d\n", res ); + free( wrapper ); + return NULL; +}