Signed-off-by: Georg Lehmann dadschoorse@gmail.com --- dlls/winevulkan/make_vulkan | 51 ++++++++++++++++++++++++++++++-- dlls/winevulkan/vulkan.c | 21 ++----------- dlls/winevulkan/vulkan_private.h | 3 ++ 3 files changed, 53 insertions(+), 22 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 2cddb161d6..afea087a92 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -939,9 +939,6 @@ class VkHandle(object): def native_handle(self, name): """ Provide access to the native handle of a wrapped object. """
- # Remember to add any new native handle whose parent is VkDevice - # to unwrap_object_handle() in vulkan.c - if self.name == "VkCommandPool": return "wine_cmd_pool_from_handle({0})->command_pool".format(name)
@@ -965,6 +962,24 @@ class VkHandle(object): LOGGER.error("Unhandled native handle for: {0}".format(self.name)) return None
+ def is_wrapped(self): + return self.native_handle("test") is not None + + def object_type(self): + """ Generates the matching VkObjectType """ + + # FIXME: use the xml comments for VkObjectType instead + if not self.name.startswith("Vk") or any(c.isdigit() for c in self.name): + LOGGER.warn("object type generation might fail for: {0}".format(self.name)) + + type_ = "VK_OBJECT_TYPE" + previous = "f" + for char in self.name[2:]: + if char.isupper() and previous.islower(): + type_ += "_" + type_ += char.upper() + previous = char + return type_
class VkMember(object): def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None, @@ -2276,6 +2291,36 @@ class VkGenerator(object): f.write(" return TRUE;\n") f.write(" }\n") f.write(" return FALSE;\n") + f.write("}\n\n") + + f.write("BOOL wine_vk_is_type_wrapped(VkObjectType type)\n") + f.write("{\n") + f.write(" return ") + for handle in self.registry.handles: + if not handle.is_required() or not handle.is_wrapped(): + continue + f.write("type == {} || ".format(handle.object_type())) + f.write("FALSE;\n") + f.write("}\n\n") + + f.write("uint64_t wine_vk_unwrap_handle(VkObjectType type, uint64_t handle)\n") + f.write("{\n") + f.write(" switch(type)\n") + f.write(" {\n") + for handle in self.registry.handles: + if not handle.is_required() or not handle.is_wrapped(): + continue + f.write(" case {}:\n".format(handle.object_type())) + if handle.is_dispatchable(): + f.write(" return (uint64_t) (uintptr_t) ") + f.write(handle.native_handle("(({}) (uintptr_t) handle)".format(handle.name))) + else: + f.write(" return (uint64_t) ") + f.write(handle.native_handle("handle")) + f.write(";\n"); + f.write(" default:\n") + f.write(" return handle;\n") + f.write(" }\n") f.write("}\n")
def generate_thunks_h(self, f, prefix): diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index f730c04923..3d1e8bd0ab 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -1534,30 +1534,13 @@ void WINAPI wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDev properties->externalSemaphoreFeatures = 0; }
-static uint64_t unwrap_object_handle(VkObjectType type, uint64_t handle) -{ - switch (type) - { - case VK_OBJECT_TYPE_DEVICE: - return (uint64_t) (uintptr_t) ((VkDevice) (uintptr_t) handle)->device; - case VK_OBJECT_TYPE_QUEUE: - return (uint64_t) (uintptr_t) ((VkQueue) (uintptr_t) handle)->queue; - case VK_OBJECT_TYPE_COMMAND_BUFFER: - return (uint64_t) (uintptr_t) ((VkCommandBuffer) (uintptr_t) handle)->command_buffer; - case VK_OBJECT_TYPE_COMMAND_POOL: - return (uint64_t) wine_cmd_pool_from_handle(handle)->command_pool; - default: - return handle; - } -} - VkResult WINAPI wine_vkSetPrivateDataEXT(VkDevice device, VkObjectType object_type, uint64_t object_handle, VkPrivateDataSlotEXT private_data_slot, uint64_t data) { TRACE("%p, %#x, 0x%s, 0x%s, 0x%s\n", device, object_type, wine_dbgstr_longlong(object_handle), wine_dbgstr_longlong(private_data_slot), wine_dbgstr_longlong(data));
- object_handle = unwrap_object_handle(object_type, object_handle); + object_handle = wine_vk_unwrap_handle(object_type, object_handle); return device->funcs.p_vkSetPrivateDataEXT(device->device, object_type, object_handle, private_data_slot, data); }
@@ -1567,7 +1550,7 @@ void WINAPI wine_vkGetPrivateDataEXT(VkDevice device, VkObjectType object_type, TRACE("%p, %#x, 0x%s, 0x%s, %p\n", device, object_type, wine_dbgstr_longlong(object_handle), wine_dbgstr_longlong(private_data_slot), data);
- object_handle = unwrap_object_handle(object_type, object_handle); + object_handle = wine_vk_unwrap_handle(object_type, object_handle); device->funcs.p_vkGetPrivateDataEXT(device->device, object_type, object_handle, private_data_slot, data); }
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 4bcc4de440..bf09401c52 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -138,4 +138,7 @@ void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN; BOOL wine_vk_device_extension_supported(const char *name) DECLSPEC_HIDDEN; BOOL wine_vk_instance_extension_supported(const char *name) DECLSPEC_HIDDEN;
+BOOL wine_vk_is_type_wrapped(VkObjectType type) DECLSPEC_HIDDEN; +uint64_t wine_vk_unwrap_handle(VkObjectType type, uint64_t handle) DECLSPEC_HIDDEN; + #endif /* __WINE_VULKAN_PRIVATE_H */
Signed-off-by: Georg Lehmann dadschoorse@gmail.com --- dlls/winevulkan/vulkan.c | 74 ++++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_private.h | 26 +++++++++++ 2 files changed, 100 insertions(+)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 3d1e8bd0ab..54b910c5e5 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -66,11 +66,59 @@ static VkResult (*p_vkEnumerateInstanceVersion)(uint32_t *version); void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physical_device, VkPhysicalDeviceProperties *properties);
+#define WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, object, native_handle) \ + wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (uintptr_t) (native_handle), &(object)->mapping) +#define WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, native_handle) \ + wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (native_handle), &(object)->mapping) +static void wine_vk_add_handle_mapping(struct VkInstance_T *instance, uint64_t wrapped_handle, + uint64_t native_handle, struct wine_vk_mapping *mapping) +{ + if (instance->enable_wrapper_list) + { + mapping->native_handle = native_handle; + mapping->wine_wrapped_handle = wrapped_handle; + AcquireSRWLockExclusive(&instance->wrapper_lock); + list_add_tail(&instance->wrappers, &mapping->link); + ReleaseSRWLockExclusive(&instance->wrapper_lock); + } +} + +#define WINE_VK_REMOVE_HANDLE_MAPPING(instance, object) \ + wine_vk_remove_handle_mapping((instance), &(object)->mapping) +static void wine_vk_remove_handle_mapping(struct VkInstance_T *instance, struct wine_vk_mapping *mapping) +{ + if (instance->enable_wrapper_list) + { + AcquireSRWLockExclusive(&instance->wrapper_lock); + list_remove(&mapping->link); + ReleaseSRWLockExclusive(&instance->wrapper_lock); + } +} + +static uint64_t wine_vk_get_wrapper(struct VkInstance_T *instance, uint64_t native_handle) +{ + struct wine_vk_mapping *mapping; + uint64_t result = 0; + + AcquireSRWLockShared(&instance->wrapper_lock); + LIST_FOR_EACH_ENTRY(mapping, &instance->wrappers, struct wine_vk_mapping, link) + { + if (mapping->native_handle == native_handle) + { + result = mapping->wine_wrapped_handle; + break; + } + } + ReleaseSRWLockShared(&instance->wrapper_lock); + return result; +} + static void wine_vk_physical_device_free(struct VkPhysicalDevice_T *phys_dev) { if (!phys_dev) return;
+ WINE_VK_REMOVE_HANDLE_MAPPING(phys_dev->instance, phys_dev); heap_free(phys_dev->extensions); heap_free(phys_dev); } @@ -91,6 +139,8 @@ static struct VkPhysicalDevice_T *wine_vk_physical_device_alloc(struct VkInstanc object->instance = instance; object->phys_dev = phys_dev;
+ WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, object, phys_dev); + res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(phys_dev, NULL, &num_host_properties, NULL); if (res != VK_SUCCESS) @@ -169,6 +219,7 @@ static void wine_vk_free_command_buffers(struct VkDevice_T *device,
device->funcs.p_vkFreeCommandBuffers(device->device, pool->command_pool, 1, &buffers[i]->command_buffer); list_remove(&buffers[i]->pool_link); + WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, buffers[i]); heap_free(buffers[i]); } } @@ -212,6 +263,8 @@ static struct VkQueue_T *wine_vk_device_alloc_queues(struct VkDevice_T *device, { device->funcs.p_vkGetDeviceQueue(device->device, family_index, i, &queue->queue); } + + WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, queue, queue->queue); }
return queues; @@ -294,6 +347,8 @@ static void wine_vk_device_free(struct VkDevice_T *device) unsigned int i; for (i = 0; i < device->max_queue_families; i++) { + if (device->queues[i] && device->queues[i]->queue) + WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, device->queues[i]); heap_free(device->queues[i]); } heap_free(device->queues); @@ -302,6 +357,7 @@ static void wine_vk_device_free(struct VkDevice_T *device)
if (device->device && device->funcs.p_vkDestroyDevice) { + WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, device); device->funcs.p_vkDestroyDevice(device->device, NULL /* pAllocator */); }
@@ -466,7 +522,10 @@ static void wine_vk_instance_free(struct VkInstance_T *instance) }
if (instance->instance) + { vk_funcs->p_vkDestroyInstance(instance->instance, NULL /* allocator */); + WINE_VK_REMOVE_HANDLE_MAPPING(instance, instance); + }
heap_free(instance); } @@ -512,6 +571,7 @@ VkResult WINAPI wine_vkAllocateCommandBuffers(VkDevice device, list_add_tail(&pool->command_buffers, &buffers[i]->pool_link); res = device->funcs.p_vkAllocateCommandBuffers(device->device, &allocate_info_host, &buffers[i]->command_buffer); + WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, buffers[i], buffers[i]->command_buffer); if (res != VK_SUCCESS) { ERR("Failed to allocate command buffer, res=%d.\n", res); @@ -589,6 +649,7 @@ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev, return VK_ERROR_OUT_OF_HOST_MEMORY;
object->base.loader_magic = VULKAN_ICD_MAGIC_VALUE; + object->phys_dev = phys_dev;
res = wine_vk_device_convert_create_info(create_info, &create_info_host); if (res != VK_SUCCESS) @@ -597,6 +658,7 @@ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev, res = phys_dev->instance->funcs.p_vkCreateDevice(phys_dev->phys_dev, &create_info_host, NULL /* allocator */, &object->device); wine_vk_device_free_create_info(&create_info_host); + WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev->instance, object, object->device); if (res != VK_SUCCESS) { WARN("Failed to create device, res=%d.\n", res); @@ -678,6 +740,8 @@ VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, return VK_ERROR_OUT_OF_HOST_MEMORY; } object->base.loader_magic = VULKAN_ICD_MAGIC_VALUE; + list_init(&object->wrappers); + InitializeSRWLock(&object->wrapper_lock);
res = wine_vk_instance_convert_create_info(create_info, &create_info_host, object); if (res != VK_SUCCESS) @@ -695,6 +759,8 @@ VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, return res; }
+ WINE_VK_ADD_DISPATCHABLE_MAPPING(object, object, object->instance); + /* 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. @@ -1129,9 +1195,14 @@ VkResult WINAPI wine_vkCreateCommandPool(VkDevice device, const VkCommandPoolCre res = device->funcs.p_vkCreateCommandPool(device->device, info, NULL, &object->command_pool);
if (res == VK_SUCCESS) + { + WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device->phys_dev->instance, object, object->command_pool); *command_pool = wine_cmd_pool_to_handle(object); + } else + { heap_free(object); + }
return res; } @@ -1156,9 +1227,12 @@ void WINAPI wine_vkDestroyCommandPool(VkDevice device, VkCommandPool handle, */ LIST_FOR_EACH_ENTRY_SAFE(buffer, cursor, &pool->command_buffers, struct VkCommandBuffer_T, pool_link) { + WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, buffer); heap_free(buffer); }
+ WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, pool); + device->funcs.p_vkDestroyCommandPool(device->device, pool->command_pool, NULL); heap_free(pool); } diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index bf09401c52..7000da7133 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -60,6 +60,16 @@ struct wine_vk_base UINT_PTR loader_magic; };
+/* Some extensions have callbacks for those we need to be able to + * get the wine wrapper for a native handle + */ +struct wine_vk_mapping +{ + struct list link; + uint64_t native_handle; + uint64_t wine_wrapped_handle; +}; + struct VkCommandBuffer_T { struct wine_vk_base base; @@ -67,18 +77,22 @@ struct VkCommandBuffer_T VkCommandBuffer command_buffer; /* native command buffer */
struct list pool_link; + struct wine_vk_mapping mapping; };
struct VkDevice_T { struct wine_vk_base base; struct vulkan_device_funcs funcs; + struct VkPhysicalDevice_T *phys_dev; /* parent */ VkDevice device; /* native device */
struct VkQueue_T **queues; uint32_t max_queue_families;
unsigned int quirks; + + struct wine_vk_mapping mapping; };
struct VkInstance_T @@ -93,7 +107,13 @@ struct VkInstance_T struct VkPhysicalDevice_T **phys_devs; uint32_t phys_dev_count;
+ VkBool32 enable_wrapper_list; + struct list wrappers; + SRWLOCK wrapper_lock; + unsigned int quirks; + + struct wine_vk_mapping mapping; };
struct VkPhysicalDevice_T @@ -104,6 +124,8 @@ struct VkPhysicalDevice_T
VkExtensionProperties *extensions; uint32_t extension_count; + + struct wine_vk_mapping mapping; };
struct VkQueue_T @@ -113,6 +135,8 @@ struct VkQueue_T VkQueue queue; /* native queue */
VkDeviceQueueCreateFlags flags; + + struct wine_vk_mapping mapping; };
struct wine_cmd_pool @@ -120,6 +144,8 @@ struct wine_cmd_pool VkCommandPool command_pool;
struct list command_buffers; + + struct wine_vk_mapping mapping; };
static inline struct wine_cmd_pool *wine_cmd_pool_from_handle(VkCommandPool handle)
Sorry, I didn't catch this before, but when reviewing I found some trailing whitespace added on a few lines, see below.
On 9/25/20 8:16 AM, Georg Lehmann wrote:
Signed-off-by: Georg Lehmann dadschoorse@gmail.com
dlls/winevulkan/vulkan.c | 74 ++++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_private.h | 26 +++++++++++ 2 files changed, 100 insertions(+)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 3d1e8bd0ab..54b910c5e5 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -66,11 +66,59 @@ static VkResult (*p_vkEnumerateInstanceVersion)(uint32_t *version); void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physical_device, VkPhysicalDeviceProperties *properties);
+#define WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, object, native_handle) \
- wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (uintptr_t) (native_handle), &(object)->mapping)
+#define WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, native_handle) \
- wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (native_handle), &(object)->mapping)
+static void wine_vk_add_handle_mapping(struct VkInstance_T *instance, uint64_t wrapped_handle,
uint64_t native_handle, struct wine_vk_mapping *mapping)
+{
- if (instance->enable_wrapper_list)
- {
mapping->native_handle = native_handle;
mapping->wine_wrapped_handle = wrapped_handle;
AcquireSRWLockExclusive(&instance->wrapper_lock);
list_add_tail(&instance->wrappers, &mapping->link);
ReleaseSRWLockExclusive(&instance->wrapper_lock);
- }
+}
+#define WINE_VK_REMOVE_HANDLE_MAPPING(instance, object) \
- wine_vk_remove_handle_mapping((instance), &(object)->mapping)
+static void wine_vk_remove_handle_mapping(struct VkInstance_T *instance, struct wine_vk_mapping *mapping) +{
- if (instance->enable_wrapper_list)
- {
AcquireSRWLockExclusive(&instance->wrapper_lock);
list_remove(&mapping->link);
ReleaseSRWLockExclusive(&instance->wrapper_lock);
- }
+}
+static uint64_t wine_vk_get_wrapper(struct VkInstance_T *instance, uint64_t native_handle) +{
- struct wine_vk_mapping *mapping;
- uint64_t result = 0;
- AcquireSRWLockShared(&instance->wrapper_lock);
- LIST_FOR_EACH_ENTRY(mapping, &instance->wrappers, struct wine_vk_mapping, link)
- {
if (mapping->native_handle == native_handle)
{
result = mapping->wine_wrapped_handle;
break;
}
- }
- ReleaseSRWLockShared(&instance->wrapper_lock);
- return result;
+}
static void wine_vk_physical_device_free(struct VkPhysicalDevice_T *phys_dev) { if (!phys_dev) return;
WINE_VK_REMOVE_HANDLE_MAPPING(phys_dev->instance, phys_dev); heap_free(phys_dev->extensions); heap_free(phys_dev); }
@@ -91,6 +139,8 @@ static struct VkPhysicalDevice_T *wine_vk_physical_device_alloc(struct VkInstanc object->instance = instance; object->phys_dev = phys_dev;
- WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, object, phys_dev);
res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(phys_dev, NULL, &num_host_properties, NULL); if (res != VK_SUCCESS)
@@ -169,6 +219,7 @@ static void wine_vk_free_command_buffers(struct VkDevice_T *device,
device->funcs.p_vkFreeCommandBuffers(device->device, pool->command_pool, 1, &buffers[i]->command_buffer); list_remove(&buffers[i]->pool_link);
}WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, buffers[i]); heap_free(buffers[i]); }
@@ -212,6 +263,8 @@ static struct VkQueue_T *wine_vk_device_alloc_queues(struct VkDevice_T *device, { device->funcs.p_vkGetDeviceQueue(device->device, family_index, i, &queue->queue); }
WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, queue, queue->queue);
nit: Trailing whitespace in first line.
} return queues;
@@ -294,6 +347,8 @@ static void wine_vk_device_free(struct VkDevice_T *device) unsigned int i; for (i = 0; i < device->max_queue_families; i++) {
if (device->queues[i] && device->queues[i]->queue)
WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, device->queues[i]); heap_free(device->queues[i]); } heap_free(device->queues);
@@ -302,6 +357,7 @@ static void wine_vk_device_free(struct VkDevice_T *device)
if (device->device && device->funcs.p_vkDestroyDevice) {
WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, device); device->funcs.p_vkDestroyDevice(device->device, NULL /* pAllocator */); }
@@ -466,7 +522,10 @@ static void wine_vk_instance_free(struct VkInstance_T *instance) }
if (instance->instance)
{ vk_funcs->p_vkDestroyInstance(instance->instance, NULL /* allocator */);
WINE_VK_REMOVE_HANDLE_MAPPING(instance, instance);
}
heap_free(instance); }
@@ -512,6 +571,7 @@ VkResult WINAPI wine_vkAllocateCommandBuffers(VkDevice device, list_add_tail(&pool->command_buffers, &buffers[i]->pool_link); res = device->funcs.p_vkAllocateCommandBuffers(device->device, &allocate_info_host, &buffers[i]->command_buffer);
WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, buffers[i], buffers[i]->command_buffer); if (res != VK_SUCCESS) { ERR("Failed to allocate command buffer, res=%d.\n", res);
@@ -589,6 +649,7 @@ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev, return VK_ERROR_OUT_OF_HOST_MEMORY;
object->base.loader_magic = VULKAN_ICD_MAGIC_VALUE;
object->phys_dev = phys_dev;
res = wine_vk_device_convert_create_info(create_info, &create_info_host); if (res != VK_SUCCESS)
@@ -597,6 +658,7 @@ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev, res = phys_dev->instance->funcs.p_vkCreateDevice(phys_dev->phys_dev, &create_info_host, NULL /* allocator */, &object->device); wine_vk_device_free_create_info(&create_info_host);
- WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev->instance, object, object->device); if (res != VK_SUCCESS) { WARN("Failed to create device, res=%d.\n", res);
@@ -678,6 +740,8 @@ VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, return VK_ERROR_OUT_OF_HOST_MEMORY; } object->base.loader_magic = VULKAN_ICD_MAGIC_VALUE;
list_init(&object->wrappers);
InitializeSRWLock(&object->wrapper_lock);
res = wine_vk_instance_convert_create_info(create_info, &create_info_host, object); if (res != VK_SUCCESS)
@@ -695,6 +759,8 @@ VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, return res; }
- WINE_VK_ADD_DISPATCHABLE_MAPPING(object, object, object->instance);
/* 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.
@@ -1129,9 +1195,14 @@ VkResult WINAPI wine_vkCreateCommandPool(VkDevice device, const VkCommandPoolCre res = device->funcs.p_vkCreateCommandPool(device->device, info, NULL, &object->command_pool);
if (res == VK_SUCCESS)
{
WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device->phys_dev->instance, object, object->command_pool); *command_pool = wine_cmd_pool_to_handle(object);
} else
{ heap_free(object);
}
return res; }
@@ -1156,9 +1227,12 @@ void WINAPI wine_vkDestroyCommandPool(VkDevice device, VkCommandPool handle, */ LIST_FOR_EACH_ENTRY_SAFE(buffer, cursor, &pool->command_buffers, struct VkCommandBuffer_T, pool_link) {
WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, buffer); heap_free(buffer); }
WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, pool);
device->funcs.p_vkDestroyCommandPool(device->device, pool->command_pool, NULL); heap_free(pool);
}
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index bf09401c52..7000da7133 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -60,6 +60,16 @@ struct wine_vk_base UINT_PTR loader_magic; };
+/* Some extensions have callbacks for those we need to be able to
- get the wine wrapper for a native handle
- */
+struct wine_vk_mapping +{
- struct list link;
- uint64_t native_handle;
- uint64_t wine_wrapped_handle;
+};
- struct VkCommandBuffer_T { struct wine_vk_base base;
@@ -67,18 +77,22 @@ struct VkCommandBuffer_T VkCommandBuffer command_buffer; /* native command buffer */
struct list pool_link;
struct wine_vk_mapping mapping; };
struct VkDevice_T { struct wine_vk_base base; struct vulkan_device_funcs funcs;
struct VkPhysicalDevice_T *phys_dev; /* parent */ VkDevice device; /* native device */
struct VkQueue_T **queues; uint32_t max_queue_families;
unsigned int quirks;
struct wine_vk_mapping mapping;
nit: Trailing whitespace in first line.
};
struct VkInstance_T @@ -93,7 +107,13 @@ struct VkInstance_T struct VkPhysicalDevice_T **phys_devs; uint32_t phys_dev_count;
- VkBool32 enable_wrapper_list;
- struct list wrappers;
- SRWLOCK wrapper_lock;
unsigned int quirks;
- struct wine_vk_mapping mapping;
nit: Trailing whitespace in first line.
};
struct VkPhysicalDevice_T @@ -104,6 +124,8 @@ struct VkPhysicalDevice_T
VkExtensionProperties *extensions; uint32_t extension_count;
- struct wine_vk_mapping mapping;
nit: Trailing whitespace in first line.
};
struct VkQueue_T @@ -113,6 +135,8 @@ struct VkQueue_T VkQueue queue; /* native queue */
VkDeviceQueueCreateFlags flags;
- struct wine_vk_mapping mapping;
nit: Trailing whitespace in first line.
};
struct wine_cmd_pool @@ -120,6 +144,8 @@ struct wine_cmd_pool VkCommandPool command_pool;
struct list command_buffers;
- struct wine_vk_mapping mapping;
nit: Trailing whitespace in first line.
Thanks,
Liam Middlebrook
};
static inline struct wine_cmd_pool *wine_cmd_pool_from_handle(VkCommandPool handle)
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49813
Signed-off-by: Georg Lehmann dadschoorse@gmail.com --- dlls/winevulkan/make_vulkan | 8 +- dlls/winevulkan/vulkan.c | 183 +++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_private.h | 31 ++++++ 3 files changed, 221 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index afea087a92..623d1b9cde 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -92,7 +92,6 @@ UNSUPPORTED_EXTENSIONS = [ # plumbing down to the native layer, we will get each message twice as we # use 2 loaders (win32+native), but we may get output from the driver. # In any case callback conversion is required. - "VK_EXT_debug_utils", "VK_EXT_validation_features", "VK_EXT_validation_flags", "VK_KHR_display", # Needs WSI work. @@ -225,6 +224,11 @@ FUNCTION_OVERRIDES = { # VK_EXT_calibrated_timestamps "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT" : {"dispatch" : True, "driver" : False, "thunk" : False}, "vkGetCalibratedTimestampsEXT" : {"dispatch" : True, "driver" : False, "thunk" : False}, + + # VK_EXT_debug_utils + "vkCreateDebugUtilsMessengerEXT" : {"dispatch": True, "driver" : False, "thunk" : False}, + "vkDestroyDebugUtilsMessengerEXT" : {"dispatch": True, "driver" : False, "thunk" : False}, + "vkSubmitDebugUtilsMessageEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True}, }
STRUCT_CHAIN_CONVERSIONS = [ @@ -941,6 +945,8 @@ class VkHandle(object):
if self.name == "VkCommandPool": return "wine_cmd_pool_from_handle({0})->command_pool".format(name) + if self.name == "VkDebugUtilsMessengerEXT": + return "wine_debug_utils_messenger_from_handle({0})->debug_messenger".format(name)
native_handle_name = None
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 54b910c5e5..f831d486d0 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -57,6 +57,21 @@ static void *wine_vk_find_struct_(void *s, VkStructureType t) return NULL; }
+#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; +} + static void *wine_vk_get_global_proc_addr(const char *name);
static HINSTANCE hinstance; @@ -113,6 +128,68 @@ static uint64_t wine_vk_get_wrapper(struct VkInstance_T *instance, uint64_t nati return result; }
+static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity, + VkDebugUtilsMessageTypeFlagsEXT message_types, +#if defined(USE_STRUCT_CONVERSION) + const VkDebugUtilsMessengerCallbackDataEXT_host *callback_data, +#else + const VkDebugUtilsMessengerCallbackDataEXT *callback_data, +#endif + void *user_data) +{ + struct VkDebugUtilsMessengerCallbackDataEXT wine_callback_data; + VkDebugUtilsObjectNameInfoEXT *object_name_infos; + struct wine_debug_utils_messenger *object; + VkBool32 result; + int i; + + TRACE("%i, %u, %p, %p\n", severity, message_types, callback_data, user_data); + + object = user_data; + + if (!object->instance->instance) + { + /* instance wasn't yet created, this is a message from the native loader */ + return VK_FALSE; + } + + wine_callback_data = *((VkDebugUtilsMessengerCallbackDataEXT *) callback_data); + + object_name_infos = heap_calloc(wine_callback_data.objectCount, sizeof(*object_name_infos)); + + for (i = 0; i < wine_callback_data.objectCount; i++) + { + object_name_infos[i].sType = callback_data->pObjects[i].sType; + object_name_infos[i].pNext = callback_data->pObjects[i].pNext; + object_name_infos[i].objectType = callback_data->pObjects[i].objectType; + object_name_infos[i].pObjectName = callback_data->pObjects[i].pObjectName; + + if (wine_vk_is_type_wrapped(callback_data->pObjects[i].objectType)) + { + object_name_infos[i].objectHandle = wine_vk_get_wrapper(object->instance, callback_data->pObjects[i].objectHandle); + if (!object_name_infos[i].objectHandle) + { + WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle)); + heap_free(object_name_infos); + return VK_FALSE; + } + } + else + { + object_name_infos[i].objectHandle = callback_data->pObjects[i].objectHandle; + } + } + + wine_callback_data.pObjects = object_name_infos; + + /* applications should always return VK_FALSE */ + result = object->user_callback(severity, message_types, &wine_callback_data, object->user_data); + + heap_free(object_name_infos); + + return result; +} + static void wine_vk_physical_device_free(struct VkPhysicalDevice_T *phys_dev) { if (!phys_dev) @@ -393,6 +470,8 @@ static void wine_vk_init_once(void) static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, VkInstanceCreateInfo *dst, struct VkInstance_T *object) { + VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger; + VkBaseInStructure *header; unsigned int i; VkResult res;
@@ -404,6 +483,26 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo return res; }
+ object->utils_messenger_count = wine_vk_count_struct(dst, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT); + object->utils_messengers = heap_calloc(object->utils_messenger_count, sizeof(*object->utils_messengers)); + header = (VkBaseInStructure *) dst; + for (i = 0; i < object->utils_messenger_count; i++) + { + header = wine_vk_find_struct(header->pNext, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT); + debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *) header; + + object->utils_messengers[i].instance = object; + object->utils_messengers[i].debug_messenger = VK_NULL_HANDLE; + object->utils_messengers[i].user_callback = debug_utils_messenger->pfnUserCallback; + object->utils_messengers[i].user_data = debug_utils_messenger->pUserData; + + /* convert_VkInstanceCreateInfo_struct_chain already copied the chain, + * so we can modify it in-place. + */ + debug_utils_messenger->pfnUserCallback = (void *) &debug_utils_callback_conversion; + debug_utils_messenger->pUserData = &object->utils_messengers[i]; + } + /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader * filter this data out as well. */ @@ -427,6 +526,10 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo free_VkInstanceCreateInfo_struct_chain(dst); return VK_ERROR_EXTENSION_NOT_PRESENT; } + if (!strcmp(extension_name, "VK_EXT_debug_utils")) + { + object->enable_wrapper_list = VK_TRUE; + } }
return VK_SUCCESS; @@ -527,6 +630,8 @@ static void wine_vk_instance_free(struct VkInstance_T *instance) WINE_VK_REMOVE_HANDLE_MAPPING(instance, instance); }
+ heap_free(instance->utils_messengers); + heap_free(instance); }
@@ -1673,6 +1778,84 @@ VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice return res; }
+VkResult WINAPI wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *create_info, + const VkAllocationCallbacks *allocator, VkDebugUtilsMessengerEXT *messenger) +{ + VkDebugUtilsMessengerCreateInfoEXT wine_create_info; + struct wine_debug_utils_messenger *object; + VkResult res; + + TRACE("%p, %p, %p, %p\n", instance, create_info, allocator, messenger); + + if (allocator) + FIXME("Support for allocation callbacks not implemented yet\n"); + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + object->instance = instance; + object->user_callback = create_info->pfnUserCallback; + object->user_data = create_info->pUserData; + + wine_create_info = *create_info; + + wine_create_info.pfnUserCallback = (void *) &debug_utils_callback_conversion; + wine_create_info.pUserData = object; + + res = instance->funcs.p_vkCreateDebugUtilsMessengerEXT(instance->instance, &wine_create_info, NULL, &object->debug_messenger); + + if (res != VK_SUCCESS) + { + heap_free(object); + return res; + } + + WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, object->debug_messenger); + *messenger = wine_debug_utils_messenger_to_handle(object); + + return VK_SUCCESS; +} + +void WINAPI wine_vkDestroyDebugUtilsMessengerEXT( + VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks *allocator) +{ + struct wine_debug_utils_messenger *object; + + TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(messenger), allocator); + + object = wine_debug_utils_messenger_from_handle(messenger); + + instance->funcs.p_vkDestroyDebugUtilsMessengerEXT(instance->instance, object->debug_messenger, NULL); + WINE_VK_REMOVE_HANDLE_MAPPING(instance, object); + + heap_free(object); +} + +void WINAPI wine_vkSubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT severity, + VkDebugUtilsMessageTypeFlagsEXT types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data) +{ + VkDebugUtilsMessengerCallbackDataEXT native_callback_data; + VkDebugUtilsObjectNameInfoEXT *object_names; + int i; + + TRACE("%p, %#x, %#x, %p\n", instance, severity, types, callback_data); + + native_callback_data = *callback_data; + object_names = heap_calloc(callback_data->objectCount, sizeof(*object_names)); + memcpy(object_names, callback_data->pObjects, callback_data->objectCount * sizeof(*object_names)); + native_callback_data.pObjects = object_names; + + for (i = 0; i < callback_data->objectCount; i++) + { + object_names[i].objectHandle = + wine_vk_unwrap_handle(callback_data->pObjects[i].objectType, callback_data->pObjects[i].objectHandle); + } + + thunk_vkSubmitDebugUtilsMessageEXT(instance->instance, severity, types, &native_callback_data); + + heap_free(object_names); +} + BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) { TRACE("%p, %u, %p\n", hinst, reason, reserved); diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 7000da7133..8379fafecf 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -95,6 +95,8 @@ struct VkDevice_T struct wine_vk_mapping mapping; };
+struct wine_debug_utils_messenger; + struct VkInstance_T { struct wine_vk_base base; @@ -111,6 +113,9 @@ struct VkInstance_T struct list wrappers; SRWLOCK wrapper_lock;
+ struct wine_debug_utils_messenger *utils_messengers; + uint32_t utils_messenger_count; + unsigned int quirks;
struct wine_vk_mapping mapping; @@ -158,6 +163,32 @@ static inline VkCommandPool wine_cmd_pool_to_handle(struct wine_cmd_pool *cmd_po return (VkCommandPool)(uintptr_t)cmd_pool; }
+struct wine_debug_utils_messenger +{ + struct VkInstance_T *instance; /* parent */ + VkDebugUtilsMessengerEXT debug_messenger; /* native messenger */ + + /* application callback + data */ + PFN_vkDebugUtilsMessengerCallbackEXT user_callback; + void *user_data; + + struct wine_vk_mapping mapping; +}; + +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 VkDebugUtilsMessengerEXT wine_debug_utils_messenger_to_handle( + struct wine_debug_utils_messenger *debug_messenger) +{ + return (VkDebugUtilsMessengerEXT)(uintptr_t)debug_messenger; +} + + + void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN; void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
This looks good to me, but given the requested changes to dependent patches 1/3 and 2/3, I'll wait to sign-off on this one.
Thanks,
Liam Middlebrook
On 9/25/20 8:16 AM, Georg Lehmann wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49813
Signed-off-by: Georg Lehmann dadschoorse@gmail.com
dlls/winevulkan/make_vulkan | 8 +- dlls/winevulkan/vulkan.c | 183 +++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_private.h | 31 ++++++ 3 files changed, 221 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index afea087a92..623d1b9cde 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -92,7 +92,6 @@ UNSUPPORTED_EXTENSIONS = [ # plumbing down to the native layer, we will get each message twice as we # use 2 loaders (win32+native), but we may get output from the driver. # In any case callback conversion is required.
- "VK_EXT_debug_utils", "VK_EXT_validation_features", "VK_EXT_validation_flags", "VK_KHR_display", # Needs WSI work.
@@ -225,6 +224,11 @@ FUNCTION_OVERRIDES = { # VK_EXT_calibrated_timestamps "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT" : {"dispatch" : True, "driver" : False, "thunk" : False}, "vkGetCalibratedTimestampsEXT" : {"dispatch" : True, "driver" : False, "thunk" : False},
# VK_EXT_debug_utils
"vkCreateDebugUtilsMessengerEXT" : {"dispatch": True, "driver" : False, "thunk" : False},
"vkDestroyDebugUtilsMessengerEXT" : {"dispatch": True, "driver" : False, "thunk" : False},
"vkSubmitDebugUtilsMessageEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True}, }
STRUCT_CHAIN_CONVERSIONS = [
@@ -941,6 +945,8 @@ class VkHandle(object):
if self.name == "VkCommandPool": return "wine_cmd_pool_from_handle({0})->command_pool".format(name)
if self.name == "VkDebugUtilsMessengerEXT":
return "wine_debug_utils_messenger_from_handle({0})->debug_messenger".format(name) native_handle_name = None
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 54b910c5e5..f831d486d0 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -57,6 +57,21 @@ static void *wine_vk_find_struct_(void *s, VkStructureType t) return NULL; }
+#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;
+}
static void *wine_vk_get_global_proc_addr(const char *name);
static HINSTANCE hinstance;
@@ -113,6 +128,68 @@ static uint64_t wine_vk_get_wrapper(struct VkInstance_T *instance, uint64_t nati return result; }
+static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
- VkDebugUtilsMessageTypeFlagsEXT message_types,
+#if defined(USE_STRUCT_CONVERSION)
- const VkDebugUtilsMessengerCallbackDataEXT_host *callback_data,
+#else
- const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
+#endif
- void *user_data)
+{
- struct VkDebugUtilsMessengerCallbackDataEXT wine_callback_data;
- VkDebugUtilsObjectNameInfoEXT *object_name_infos;
- struct wine_debug_utils_messenger *object;
- VkBool32 result;
- int i;
- TRACE("%i, %u, %p, %p\n", severity, message_types, callback_data, user_data);
- object = user_data;
- if (!object->instance->instance)
- {
/* instance wasn't yet created, this is a message from the native loader */
return VK_FALSE;
- }
- wine_callback_data = *((VkDebugUtilsMessengerCallbackDataEXT *) callback_data);
- object_name_infos = heap_calloc(wine_callback_data.objectCount, sizeof(*object_name_infos));
- for (i = 0; i < wine_callback_data.objectCount; i++)
- {
object_name_infos[i].sType = callback_data->pObjects[i].sType;
object_name_infos[i].pNext = callback_data->pObjects[i].pNext;
object_name_infos[i].objectType = callback_data->pObjects[i].objectType;
object_name_infos[i].pObjectName = callback_data->pObjects[i].pObjectName;
if (wine_vk_is_type_wrapped(callback_data->pObjects[i].objectType))
{
object_name_infos[i].objectHandle = wine_vk_get_wrapper(object->instance, callback_data->pObjects[i].objectHandle);
if (!object_name_infos[i].objectHandle)
{
WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle));
heap_free(object_name_infos);
return VK_FALSE;
}
}
else
{
object_name_infos[i].objectHandle = callback_data->pObjects[i].objectHandle;
}
- }
- wine_callback_data.pObjects = object_name_infos;
- /* applications should always return VK_FALSE */
- result = object->user_callback(severity, message_types, &wine_callback_data, object->user_data);
- heap_free(object_name_infos);
- return result;
+}
- static void wine_vk_physical_device_free(struct VkPhysicalDevice_T *phys_dev) { if (!phys_dev)
@@ -393,6 +470,8 @@ static void wine_vk_init_once(void) static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, VkInstanceCreateInfo *dst, struct VkInstance_T *object) {
- VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger;
- VkBaseInStructure *header; unsigned int i; VkResult res;
@@ -404,6 +483,26 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo return res; }
- object->utils_messenger_count = wine_vk_count_struct(dst, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);
- object->utils_messengers = heap_calloc(object->utils_messenger_count, sizeof(*object->utils_messengers));
- header = (VkBaseInStructure *) dst;
- for (i = 0; i < object->utils_messenger_count; i++)
- {
header = wine_vk_find_struct(header->pNext, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);
debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *) header;
object->utils_messengers[i].instance = object;
object->utils_messengers[i].debug_messenger = VK_NULL_HANDLE;
object->utils_messengers[i].user_callback = debug_utils_messenger->pfnUserCallback;
object->utils_messengers[i].user_data = debug_utils_messenger->pUserData;
/* convert_VkInstanceCreateInfo_struct_chain already copied the chain,
* so we can modify it in-place.
*/
debug_utils_messenger->pfnUserCallback = (void *) &debug_utils_callback_conversion;
debug_utils_messenger->pUserData = &object->utils_messengers[i];
- }
/* ICDs don't support any layers, so nothing to copy. Modern versions of the loader * filter this data out as well. */
@@ -427,6 +526,10 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo free_VkInstanceCreateInfo_struct_chain(dst); return VK_ERROR_EXTENSION_NOT_PRESENT; }
if (!strcmp(extension_name, "VK_EXT_debug_utils"))
{
object->enable_wrapper_list = VK_TRUE;
} } return VK_SUCCESS;
@@ -527,6 +630,8 @@ static void wine_vk_instance_free(struct VkInstance_T *instance) WINE_VK_REMOVE_HANDLE_MAPPING(instance, instance); }
- heap_free(instance->utils_messengers);
}heap_free(instance);
@@ -1673,6 +1778,84 @@ VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice return res; }
+VkResult WINAPI wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *create_info,
const VkAllocationCallbacks *allocator, VkDebugUtilsMessengerEXT *messenger)
+{
- VkDebugUtilsMessengerCreateInfoEXT wine_create_info;
- struct wine_debug_utils_messenger *object;
- VkResult res;
- TRACE("%p, %p, %p, %p\n", instance, create_info, allocator, messenger);
- if (allocator)
FIXME("Support for allocation callbacks not implemented yet\n");
- if (!(object = heap_alloc_zero(sizeof(*object))))
return VK_ERROR_OUT_OF_HOST_MEMORY;
- object->instance = instance;
- object->user_callback = create_info->pfnUserCallback;
- object->user_data = create_info->pUserData;
- wine_create_info = *create_info;
- wine_create_info.pfnUserCallback = (void *) &debug_utils_callback_conversion;
- wine_create_info.pUserData = object;
- res = instance->funcs.p_vkCreateDebugUtilsMessengerEXT(instance->instance, &wine_create_info, NULL, &object->debug_messenger);
- if (res != VK_SUCCESS)
- {
heap_free(object);
return res;
- }
- WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, object->debug_messenger);
- *messenger = wine_debug_utils_messenger_to_handle(object);
- return VK_SUCCESS;
+}
+void WINAPI wine_vkDestroyDebugUtilsMessengerEXT(
VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks *allocator)
+{
- struct wine_debug_utils_messenger *object;
- TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(messenger), allocator);
- object = wine_debug_utils_messenger_from_handle(messenger);
- instance->funcs.p_vkDestroyDebugUtilsMessengerEXT(instance->instance, object->debug_messenger, NULL);
- WINE_VK_REMOVE_HANDLE_MAPPING(instance, object);
- heap_free(object);
+}
+void WINAPI wine_vkSubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data)
+{
- VkDebugUtilsMessengerCallbackDataEXT native_callback_data;
- VkDebugUtilsObjectNameInfoEXT *object_names;
- int i;
- TRACE("%p, %#x, %#x, %p\n", instance, severity, types, callback_data);
- native_callback_data = *callback_data;
- object_names = heap_calloc(callback_data->objectCount, sizeof(*object_names));
- memcpy(object_names, callback_data->pObjects, callback_data->objectCount * sizeof(*object_names));
- native_callback_data.pObjects = object_names;
- for (i = 0; i < callback_data->objectCount; i++)
- {
object_names[i].objectHandle =
wine_vk_unwrap_handle(callback_data->pObjects[i].objectType, callback_data->pObjects[i].objectHandle);
- }
- thunk_vkSubmitDebugUtilsMessageEXT(instance->instance, severity, types, &native_callback_data);
- heap_free(object_names);
+}
- BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) { TRACE("%p, %u, %p\n", hinst, reason, reserved);
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 7000da7133..8379fafecf 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -95,6 +95,8 @@ struct VkDevice_T struct wine_vk_mapping mapping; };
+struct wine_debug_utils_messenger;
- struct VkInstance_T { struct wine_vk_base base;
@@ -111,6 +113,9 @@ struct VkInstance_T struct list wrappers; SRWLOCK wrapper_lock;
struct wine_debug_utils_messenger *utils_messengers;
uint32_t utils_messenger_count;
unsigned int quirks; struct wine_vk_mapping mapping;
@@ -158,6 +163,32 @@ static inline VkCommandPool wine_cmd_pool_to_handle(struct wine_cmd_pool *cmd_po return (VkCommandPool)(uintptr_t)cmd_pool; }
+struct wine_debug_utils_messenger +{
- struct VkInstance_T *instance; /* parent */
- VkDebugUtilsMessengerEXT debug_messenger; /* native messenger */
- /* application callback + data */
- PFN_vkDebugUtilsMessengerCallbackEXT user_callback;
- void *user_data;
- struct wine_vk_mapping mapping;
+};
+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 VkDebugUtilsMessengerEXT wine_debug_utils_messenger_to_handle(
struct wine_debug_utils_messenger *debug_messenger)
+{
- return (VkDebugUtilsMessengerEXT)(uintptr_t)debug_messenger;
+}
- void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN; void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
Just a heads up, I was testing these patches and found they cause Horizon Zero Dawn to crash on startup on nvidia. works fine on AMD/radv
On Tue, Sep 29, 2020 at 5:21 PM Liam Middlebrook lmiddlebrook@nvidia.com wrote:
This looks good to me, but given the requested changes to dependent patches 1/3 and 2/3, I'll wait to sign-off on this one.
Thanks,
Liam Middlebrook
On 9/25/20 8:16 AM, Georg Lehmann wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49813
Signed-off-by: Georg Lehmann dadschoorse@gmail.com
dlls/winevulkan/make_vulkan | 8 +- dlls/winevulkan/vulkan.c | 183 +++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_private.h | 31 ++++++ 3 files changed, 221 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index afea087a92..623d1b9cde 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -92,7 +92,6 @@ UNSUPPORTED_EXTENSIONS = [ # plumbing down to the native layer, we will get each message
twice as we
# use 2 loaders (win32+native), but we may get output from the
driver.
# In any case callback conversion is required.
- "VK_EXT_debug_utils", "VK_EXT_validation_features", "VK_EXT_validation_flags", "VK_KHR_display", # Needs WSI work.
@@ -225,6 +224,11 @@ FUNCTION_OVERRIDES = { # VK_EXT_calibrated_timestamps "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT" : {"dispatch" :
True, "driver" : False, "thunk" : False},
"vkGetCalibratedTimestampsEXT" : {"dispatch" : True, "driver" :
False, "thunk" : False},
- # VK_EXT_debug_utils
- "vkCreateDebugUtilsMessengerEXT" : {"dispatch": True, "driver" :
False, "thunk" : False},
- "vkDestroyDebugUtilsMessengerEXT" : {"dispatch": True, "driver" :
False, "thunk" : False},
- "vkSubmitDebugUtilsMessageEXT" : {"dispatch": True, "driver" :
False, "thunk" : True, "private_thunk" : True},
}
STRUCT_CHAIN_CONVERSIONS = [ @@ -941,6 +945,8 @@ class VkHandle(object):
if self.name == "VkCommandPool": return
"wine_cmd_pool_from_handle({0})->command_pool".format(name)
if self.name == "VkDebugUtilsMessengerEXT":
return
"wine_debug_utils_messenger_from_handle({0})->debug_messenger".format(name)
native_handle_name = None
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 54b910c5e5..f831d486d0 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -57,6 +57,21 @@ static void *wine_vk_find_struct_(void *s,
VkStructureType t)
return NULL;
}
+#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;
+}
static void *wine_vk_get_global_proc_addr(const char *name);
static HINSTANCE hinstance;
@@ -113,6 +128,68 @@ static uint64_t wine_vk_get_wrapper(struct
VkInstance_T *instance, uint64_t nati
return result;
}
+static VkBool32
debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
- VkDebugUtilsMessageTypeFlagsEXT message_types,
+#if defined(USE_STRUCT_CONVERSION)
- const VkDebugUtilsMessengerCallbackDataEXT_host *callback_data,
+#else
- const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
+#endif
- void *user_data)
+{
- struct VkDebugUtilsMessengerCallbackDataEXT wine_callback_data;
- VkDebugUtilsObjectNameInfoEXT *object_name_infos;
- struct wine_debug_utils_messenger *object;
- VkBool32 result;
- int i;
- TRACE("%i, %u, %p, %p\n", severity, message_types, callback_data,
user_data);
- object = user_data;
- if (!object->instance->instance)
- {
/* instance wasn't yet created, this is a message from the
native loader */
return VK_FALSE;
- }
- wine_callback_data = *((VkDebugUtilsMessengerCallbackDataEXT *)
callback_data);
- object_name_infos = heap_calloc(wine_callback_data.objectCount,
sizeof(*object_name_infos));
- for (i = 0; i < wine_callback_data.objectCount; i++)
- {
object_name_infos[i].sType = callback_data->pObjects[i].sType;
object_name_infos[i].pNext = callback_data->pObjects[i].pNext;
object_name_infos[i].objectType =
callback_data->pObjects[i].objectType;
object_name_infos[i].pObjectName =
callback_data->pObjects[i].pObjectName;
if
(wine_vk_is_type_wrapped(callback_data->pObjects[i].objectType))
{
object_name_infos[i].objectHandle =
wine_vk_get_wrapper(object->instance, callback_data->pObjects[i].objectHandle);
if (!object_name_infos[i].objectHandle)
{
WARN("handle conversion failed 0x%s\n",
wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle));
heap_free(object_name_infos);
return VK_FALSE;
}
}
else
{
object_name_infos[i].objectHandle =
callback_data->pObjects[i].objectHandle;
}
- }
- wine_callback_data.pObjects = object_name_infos;
- /* applications should always return VK_FALSE */
- result = object->user_callback(severity, message_types,
&wine_callback_data, object->user_data);
- heap_free(object_name_infos);
- return result;
+}
- static void wine_vk_physical_device_free(struct VkPhysicalDevice_T
*phys_dev)
{ if (!phys_dev) @@ -393,6 +470,8 @@ static void wine_vk_init_once(void) static VkResult wine_vk_instance_convert_create_info(const
VkInstanceCreateInfo *src,
VkInstanceCreateInfo *dst, struct VkInstance_T *object)
{
- VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger;
- VkBaseInStructure *header; unsigned int i; VkResult res;
@@ -404,6 +483,26 @@ static VkResult
wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
return res; }
- object->utils_messenger_count = wine_vk_count_struct(dst,
DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);
- object->utils_messengers =
heap_calloc(object->utils_messenger_count, sizeof(*object->utils_messengers));
- header = (VkBaseInStructure *) dst;
- for (i = 0; i < object->utils_messenger_count; i++)
- {
header = wine_vk_find_struct(header->pNext,
DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);
debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *)
header;
object->utils_messengers[i].instance = object;
object->utils_messengers[i].debug_messenger = VK_NULL_HANDLE;
object->utils_messengers[i].user_callback =
debug_utils_messenger->pfnUserCallback;
object->utils_messengers[i].user_data =
debug_utils_messenger->pUserData;
/* convert_VkInstanceCreateInfo_struct_chain already copied the
chain,
* so we can modify it in-place.
*/
debug_utils_messenger->pfnUserCallback = (void *)
&debug_utils_callback_conversion;
debug_utils_messenger->pUserData = &object->utils_messengers[i];
- }
/* ICDs don't support any layers, so nothing to copy. Modern
versions of the loader
* filter this data out as well. */
@@ -427,6 +526,10 @@ static VkResult
wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
free_VkInstanceCreateInfo_struct_chain(dst); return VK_ERROR_EXTENSION_NOT_PRESENT; }
if (!strcmp(extension_name, "VK_EXT_debug_utils"))
{
object->enable_wrapper_list = VK_TRUE;
} } return VK_SUCCESS;
@@ -527,6 +630,8 @@ static void wine_vk_instance_free(struct
VkInstance_T *instance)
WINE_VK_REMOVE_HANDLE_MAPPING(instance, instance); }
- heap_free(instance->utils_messengers);
}heap_free(instance);
@@ -1673,6 +1778,84 @@ VkResult WINAPI
wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice
return res;
}
+VkResult WINAPI wine_vkCreateDebugUtilsMessengerEXT(VkInstance
instance, const VkDebugUtilsMessengerCreateInfoEXT *create_info,
const VkAllocationCallbacks *allocator,
VkDebugUtilsMessengerEXT *messenger)
+{
- VkDebugUtilsMessengerCreateInfoEXT wine_create_info;
- struct wine_debug_utils_messenger *object;
- VkResult res;
- TRACE("%p, %p, %p, %p\n", instance, create_info, allocator,
messenger);
- if (allocator)
FIXME("Support for allocation callbacks not implemented yet\n");
- if (!(object = heap_alloc_zero(sizeof(*object))))
return VK_ERROR_OUT_OF_HOST_MEMORY;
- object->instance = instance;
- object->user_callback = create_info->pfnUserCallback;
- object->user_data = create_info->pUserData;
- wine_create_info = *create_info;
- wine_create_info.pfnUserCallback = (void *)
&debug_utils_callback_conversion;
- wine_create_info.pUserData = object;
- res =
instance->funcs.p_vkCreateDebugUtilsMessengerEXT(instance->instance, &wine_create_info, NULL, &object->debug_messenger);
- if (res != VK_SUCCESS)
- {
heap_free(object);
return res;
- }
- WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object,
object->debug_messenger);
- *messenger = wine_debug_utils_messenger_to_handle(object);
- return VK_SUCCESS;
+}
+void WINAPI wine_vkDestroyDebugUtilsMessengerEXT(
VkInstance instance, VkDebugUtilsMessengerEXT messenger, const
VkAllocationCallbacks *allocator)
+{
- struct wine_debug_utils_messenger *object;
- TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(messenger),
allocator);
- object = wine_debug_utils_messenger_from_handle(messenger);
instance->funcs.p_vkDestroyDebugUtilsMessengerEXT(instance->instance, object->debug_messenger, NULL);
- WINE_VK_REMOVE_HANDLE_MAPPING(instance, object);
- heap_free(object);
+}
+void WINAPI wine_vkSubmitDebugUtilsMessageEXT(VkInstance instance,
VkDebugUtilsMessageSeverityFlagBitsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT types, const
VkDebugUtilsMessengerCallbackDataEXT *callback_data)
+{
- VkDebugUtilsMessengerCallbackDataEXT native_callback_data;
- VkDebugUtilsObjectNameInfoEXT *object_names;
- int i;
- TRACE("%p, %#x, %#x, %p\n", instance, severity, types,
callback_data);
- native_callback_data = *callback_data;
- object_names = heap_calloc(callback_data->objectCount,
sizeof(*object_names));
- memcpy(object_names, callback_data->pObjects,
callback_data->objectCount * sizeof(*object_names));
- native_callback_data.pObjects = object_names;
- for (i = 0; i < callback_data->objectCount; i++)
- {
object_names[i].objectHandle =
wine_vk_unwrap_handle(callback_data->pObjects[i].objectType, callback_data->pObjects[i].objectHandle);
- }
- thunk_vkSubmitDebugUtilsMessageEXT(instance->instance, severity,
types, &native_callback_data);
- heap_free(object_names);
+}
- BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) { TRACE("%p, %u, %p\n", hinst, reason, reserved);
diff --git a/dlls/winevulkan/vulkan_private.h
b/dlls/winevulkan/vulkan_private.h
index 7000da7133..8379fafecf 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -95,6 +95,8 @@ struct VkDevice_T struct wine_vk_mapping mapping; };
+struct wine_debug_utils_messenger;
- struct VkInstance_T { struct wine_vk_base base;
@@ -111,6 +113,9 @@ struct VkInstance_T struct list wrappers; SRWLOCK wrapper_lock;
struct wine_debug_utils_messenger *utils_messengers;
uint32_t utils_messenger_count;
unsigned int quirks; struct wine_vk_mapping mapping;
@@ -158,6 +163,32 @@ static inline VkCommandPool
wine_cmd_pool_to_handle(struct wine_cmd_pool *cmd_po
return (VkCommandPool)(uintptr_t)cmd_pool;
}
+struct wine_debug_utils_messenger +{
- struct VkInstance_T *instance; /* parent */
- VkDebugUtilsMessengerEXT debug_messenger; /* native messenger */
- /* application callback + data */
- PFN_vkDebugUtilsMessengerCallbackEXT user_callback;
- void *user_data;
- struct wine_vk_mapping mapping;
+};
+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 VkDebugUtilsMessengerEXT
wine_debug_utils_messenger_to_handle(
struct wine_debug_utils_messenger *debug_messenger)
+{
- return (VkDebugUtilsMessengerEXT)(uintptr_t)debug_messenger;
+}
- void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN; void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
I was testing Serious Sam 4 crash on start on Nvidia and found that it also happens due to debug function implementation in winevulkan. More precisely, in case of Serious Sam, the crash happens in host vkSetDebugUtilsObjectNameEXT() when called with objectType VK_OBJECT_TYPE_SURFACE_KHR. wine_vk_unwrap_handle() returns an unwrapped handler for this object type, while the native handle is actually wrapped in struct wine_vk_surfaceby wine driver (winex11.drv). I tested that correctly unwrapping it fixes the crash.
I am a bit unsure how to properly fix it. The straightforward way is to pull all the debug functions to wine[x11|mac].drv, but that means pulling rather lot. Besides, debugging functions have to be queried from device which winex11 currently doesn't do so we would probably need to also pull vkCreateDevice() to initialize native function pointers. The other much shorter way would be to export the unwrapping function from the wine driver which will be unwrapping handles wrapped in there. It would probably be unfortunate to introduce a special export for that, maybe we could put it in the generated 'struct vulkan_funcs' somehow?
Any suggestions?
On 10/6/20 06:35, Thomas Crider wrote:
Just a heads up, I was testing these patches and found they cause Horizon Zero Dawn to crash on startup on nvidia. works fine on AMD/radv
On Tue, Sep 29, 2020 at 5:21 PM Liam Middlebrook <lmiddlebrook@nvidia.com mailto:lmiddlebrook@nvidia.com> wrote:
This looks good to me, but given the requested changes to dependent patches 1/3 and 2/3, I'll wait to sign-off on this one. Thanks, Liam Middlebrook On 9/25/20 8:16 AM, Georg Lehmann wrote: > Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49813 <https://bugs.winehq.org/show_bug.cgi?id=49813> > > Signed-off-by: Georg Lehmann <dadschoorse@gmail.com <mailto:dadschoorse@gmail.com>> > --- > dlls/winevulkan/make_vulkan | 8 +- > dlls/winevulkan/vulkan.c | 183 +++++++++++++++++++++++++++++++ > dlls/winevulkan/vulkan_private.h | 31 ++++++ > 3 files changed, 221 insertions(+), 1 deletion(-) > > diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan > index afea087a92..623d1b9cde 100755 > --- a/dlls/winevulkan/make_vulkan > +++ b/dlls/winevulkan/make_vulkan > @@ -92,7 +92,6 @@ UNSUPPORTED_EXTENSIONS = [ > # plumbing down to the native layer, we will get each message twice as we > # use 2 loaders (win32+native), but we may get output from the driver. > # In any case callback conversion is required. > - "VK_EXT_debug_utils", > "VK_EXT_validation_features", > "VK_EXT_validation_flags", > "VK_KHR_display", # Needs WSI work. > @@ -225,6 +224,11 @@ FUNCTION_OVERRIDES = { > # VK_EXT_calibrated_timestamps > "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT" : {"dispatch" : True, "driver" : False, "thunk" : False}, > "vkGetCalibratedTimestampsEXT" : {"dispatch" : True, "driver" : False, "thunk" : False}, > + > + # VK_EXT_debug_utils > + "vkCreateDebugUtilsMessengerEXT" : {"dispatch": True, "driver" : False, "thunk" : False}, > + "vkDestroyDebugUtilsMessengerEXT" : {"dispatch": True, "driver" : False, "thunk" : False}, > + "vkSubmitDebugUtilsMessageEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True}, > } > > STRUCT_CHAIN_CONVERSIONS = [ > @@ -941,6 +945,8 @@ class VkHandle(object): > > if self.name <http://self.name> == "VkCommandPool": > return "wine_cmd_pool_from_handle({0})->command_pool".format(name) > + if self.name <http://self.name> == "VkDebugUtilsMessengerEXT": > + return "wine_debug_utils_messenger_from_handle({0})->debug_messenger".format(name) > > native_handle_name = None > > diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c > index 54b910c5e5..f831d486d0 100644 > --- a/dlls/winevulkan/vulkan.c > +++ b/dlls/winevulkan/vulkan.c > @@ -57,6 +57,21 @@ static void *wine_vk_find_struct_(void *s, VkStructureType t) > return NULL; > } > > +#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; > +} > + > static void *wine_vk_get_global_proc_addr(const char *name); > > static HINSTANCE hinstance; > @@ -113,6 +128,68 @@ static uint64_t wine_vk_get_wrapper(struct VkInstance_T *instance, uint64_t nati > return result; > } > > +static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity, > + VkDebugUtilsMessageTypeFlagsEXT message_types, > +#if defined(USE_STRUCT_CONVERSION) > + const VkDebugUtilsMessengerCallbackDataEXT_host *callback_data, > +#else > + const VkDebugUtilsMessengerCallbackDataEXT *callback_data, > +#endif > + void *user_data) > +{ > + struct VkDebugUtilsMessengerCallbackDataEXT wine_callback_data; > + VkDebugUtilsObjectNameInfoEXT *object_name_infos; > + struct wine_debug_utils_messenger *object; > + VkBool32 result; > + int i; > + > + TRACE("%i, %u, %p, %p\n", severity, message_types, callback_data, user_data); > + > + object = user_data; > + > + if (!object->instance->instance) > + { > + /* instance wasn't yet created, this is a message from the native loader */ > + return VK_FALSE; > + } > + > + wine_callback_data = *((VkDebugUtilsMessengerCallbackDataEXT *) callback_data); > + > + object_name_infos = heap_calloc(wine_callback_data.objectCount, sizeof(*object_name_infos)); > + > + for (i = 0; i < wine_callback_data.objectCount; i++) > + { > + object_name_infos[i].sType = callback_data->pObjects[i].sType; > + object_name_infos[i].pNext = callback_data->pObjects[i].pNext; > + object_name_infos[i].objectType = callback_data->pObjects[i].objectType; > + object_name_infos[i].pObjectName = callback_data->pObjects[i].pObjectName; > + > + if (wine_vk_is_type_wrapped(callback_data->pObjects[i].objectType)) > + { > + object_name_infos[i].objectHandle = wine_vk_get_wrapper(object->instance, callback_data->pObjects[i].objectHandle); > + if (!object_name_infos[i].objectHandle) > + { > + WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle)); > + heap_free(object_name_infos); > + return VK_FALSE; > + } > + } > + else > + { > + object_name_infos[i].objectHandle = callback_data->pObjects[i].objectHandle; > + } > + } > + > + wine_callback_data.pObjects = object_name_infos; > + > + /* applications should always return VK_FALSE */ > + result = object->user_callback(severity, message_types, &wine_callback_data, object->user_data); > + > + heap_free(object_name_infos); > + > + return result; > +} > + > static void wine_vk_physical_device_free(struct VkPhysicalDevice_T *phys_dev) > { > if (!phys_dev) > @@ -393,6 +470,8 @@ static void wine_vk_init_once(void) > static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, > VkInstanceCreateInfo *dst, struct VkInstance_T *object) > { > + VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger; > + VkBaseInStructure *header; > unsigned int i; > VkResult res; > > @@ -404,6 +483,26 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo > return res; > } > > + object->utils_messenger_count = wine_vk_count_struct(dst, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT); > + object->utils_messengers = heap_calloc(object->utils_messenger_count, sizeof(*object->utils_messengers)); > + header = (VkBaseInStructure *) dst; > + for (i = 0; i < object->utils_messenger_count; i++) > + { > + header = wine_vk_find_struct(header->pNext, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT); > + debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *) header; > + > + object->utils_messengers[i].instance = object; > + object->utils_messengers[i].debug_messenger = VK_NULL_HANDLE; > + object->utils_messengers[i].user_callback = debug_utils_messenger->pfnUserCallback; > + object->utils_messengers[i].user_data = debug_utils_messenger->pUserData; > + > + /* convert_VkInstanceCreateInfo_struct_chain already copied the chain, > + * so we can modify it in-place. > + */ > + debug_utils_messenger->pfnUserCallback = (void *) &debug_utils_callback_conversion; > + debug_utils_messenger->pUserData = &object->utils_messengers[i]; > + } > + > /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader > * filter this data out as well. > */ > @@ -427,6 +526,10 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo > free_VkInstanceCreateInfo_struct_chain(dst); > return VK_ERROR_EXTENSION_NOT_PRESENT; > } > + if (!strcmp(extension_name, "VK_EXT_debug_utils")) > + { > + object->enable_wrapper_list = VK_TRUE; > + } > } > > return VK_SUCCESS; > @@ -527,6 +630,8 @@ static void wine_vk_instance_free(struct VkInstance_T *instance) > WINE_VK_REMOVE_HANDLE_MAPPING(instance, instance); > } > > + heap_free(instance->utils_messengers); > + > heap_free(instance); > } > > @@ -1673,6 +1778,84 @@ VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice > return res; > } > > +VkResult WINAPI wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *create_info, > + const VkAllocationCallbacks *allocator, VkDebugUtilsMessengerEXT *messenger) > +{ > + VkDebugUtilsMessengerCreateInfoEXT wine_create_info; > + struct wine_debug_utils_messenger *object; > + VkResult res; > + > + TRACE("%p, %p, %p, %p\n", instance, create_info, allocator, messenger); > + > + if (allocator) > + FIXME("Support for allocation callbacks not implemented yet\n"); > + > + if (!(object = heap_alloc_zero(sizeof(*object)))) > + return VK_ERROR_OUT_OF_HOST_MEMORY; > + > + object->instance = instance; > + object->user_callback = create_info->pfnUserCallback; > + object->user_data = create_info->pUserData; > + > + wine_create_info = *create_info; > + > + wine_create_info.pfnUserCallback = (void *) &debug_utils_callback_conversion; > + wine_create_info.pUserData = object; > + > + res = instance->funcs.p_vkCreateDebugUtilsMessengerEXT(instance->instance, &wine_create_info, NULL, &object->debug_messenger); > + > + if (res != VK_SUCCESS) > + { > + heap_free(object); > + return res; > + } > + > + WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, object->debug_messenger); > + *messenger = wine_debug_utils_messenger_to_handle(object); > + > + return VK_SUCCESS; > +} > + > +void WINAPI wine_vkDestroyDebugUtilsMessengerEXT( > + VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks *allocator) > +{ > + struct wine_debug_utils_messenger *object; > + > + TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(messenger), allocator); > + > + object = wine_debug_utils_messenger_from_handle(messenger); > + > + instance->funcs.p_vkDestroyDebugUtilsMessengerEXT(instance->instance, object->debug_messenger, NULL); > + WINE_VK_REMOVE_HANDLE_MAPPING(instance, object); > + > + heap_free(object); > +} > + > +void WINAPI wine_vkSubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT severity, > + VkDebugUtilsMessageTypeFlagsEXT types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data) > +{ > + VkDebugUtilsMessengerCallbackDataEXT native_callback_data; > + VkDebugUtilsObjectNameInfoEXT *object_names; > + int i; > + > + TRACE("%p, %#x, %#x, %p\n", instance, severity, types, callback_data); > + > + native_callback_data = *callback_data; > + object_names = heap_calloc(callback_data->objectCount, sizeof(*object_names)); > + memcpy(object_names, callback_data->pObjects, callback_data->objectCount * sizeof(*object_names)); > + native_callback_data.pObjects = object_names; > + > + for (i = 0; i < callback_data->objectCount; i++) > + { > + object_names[i].objectHandle = > + wine_vk_unwrap_handle(callback_data->pObjects[i].objectType, callback_data->pObjects[i].objectHandle); > + } > + > + thunk_vkSubmitDebugUtilsMessageEXT(instance->instance, severity, types, &native_callback_data); > + > + heap_free(object_names); > +} > + > BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) > { > TRACE("%p, %u, %p\n", hinst, reason, reserved); > diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h > index 7000da7133..8379fafecf 100644 > --- a/dlls/winevulkan/vulkan_private.h > +++ b/dlls/winevulkan/vulkan_private.h > @@ -95,6 +95,8 @@ struct VkDevice_T > struct wine_vk_mapping mapping; > }; > > +struct wine_debug_utils_messenger; > + > struct VkInstance_T > { > struct wine_vk_base base; > @@ -111,6 +113,9 @@ struct VkInstance_T > struct list wrappers; > SRWLOCK wrapper_lock; > > + struct wine_debug_utils_messenger *utils_messengers; > + uint32_t utils_messenger_count; > + > unsigned int quirks; > > struct wine_vk_mapping mapping; > @@ -158,6 +163,32 @@ static inline VkCommandPool wine_cmd_pool_to_handle(struct wine_cmd_pool *cmd_po > return (VkCommandPool)(uintptr_t)cmd_pool; > } > > +struct wine_debug_utils_messenger > +{ > + struct VkInstance_T *instance; /* parent */ > + VkDebugUtilsMessengerEXT debug_messenger; /* native messenger */ > + > + /* application callback + data */ > + PFN_vkDebugUtilsMessengerCallbackEXT user_callback; > + void *user_data; > + > + struct wine_vk_mapping mapping; > +}; > + > +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 VkDebugUtilsMessengerEXT wine_debug_utils_messenger_to_handle( > + struct wine_debug_utils_messenger *debug_messenger) > +{ > + return (VkDebugUtilsMessengerEXT)(uintptr_t)debug_messenger; > +} > + > + > + > void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN; > void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN; > >
On 18.11.20 23:42, Paul Gofman wrote:
I was testing Serious Sam 4 crash on start on Nvidia and found that it also happens due to debug function implementation in winevulkan. More precisely, in case of Serious Sam, the crash happens in host vkSetDebugUtilsObjectNameEXT() when called with objectType VK_OBJECT_TYPE_SURFACE_KHR. wine_vk_unwrap_handle() returns an unwrapped handler for this object type, while the native handle is actually wrapped in struct wine_vk_surfaceby wine driver (winex11.drv). I tested that correctly unwrapping it fixes the crash.
I wasn't aware that the wine drivers wrap VkSurfaceKHR, but now that I think about it makes sense.
I am a bit unsure how to properly fix it. The straightforward way is to
pull all the debug functions to wine[x11|mac].drv, but that means pulling rather lot. Besides, debugging functions have to be queried from device which winex11 currently doesn't do so we would probably need to also pull vkCreateDevice() to initialize native function pointers.
This would duplicate a lot of code and make changes harder. I would like to avoid this solution.
The other much shorter way would be to export the unwrapping function from the wine driver which will be unwrapping handles wrapped in there. It would probably be unfortunate to introduce a special export for that, maybe we could put it in the generated 'struct vulkan_funcs' somehow?
That would fix the unwrapping issue, but it's not really a full solution: We also need to handle VkSurfaceKHR in the debug callbacks wrappers.
Any suggestions?
Another solution is defining a struct similar to this:
struct wine_vk_driver_surface_base { VkSurfaceKHR surface; /* native surface */ struct wine_vk_mapping mapping; };
The wine drivers would use that as the first member in their wrapper, set the native surface and winevulkan can handle VkSurfaceKHR like every other wrapped handle. I have already done a bit of work [0] on that and it should fix your issue.
Thanks,
Georg Lehmann
[0] - https://github.com/DadSchoorse/wine/tree/wrapped-surface
On 9/25/20 8:16 AM, Georg Lehmann wrote:
Signed-off-by: Georg Lehmann dadschoorse@gmail.com
dlls/winevulkan/make_vulkan | 51 ++++++++++++++++++++++++++++++-- dlls/winevulkan/vulkan.c | 21 ++----------- dlls/winevulkan/vulkan_private.h | 3 ++ 3 files changed, 53 insertions(+), 22 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 2cddb161d6..afea087a92 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -939,9 +939,6 @@ class VkHandle(object): def native_handle(self, name): """ Provide access to the native handle of a wrapped object. """
# Remember to add any new native handle whose parent is VkDevice
# to unwrap_object_handle() in vulkan.c
if self.name == "VkCommandPool": return "wine_cmd_pool_from_handle({0})->command_pool".format(name)
@@ -965,6 +962,24 @@ class VkHandle(object): LOGGER.error("Unhandled native handle for: {0}".format(self.name)) return None
- def is_wrapped(self):
return self.native_handle("test") is not None
- def object_type(self):
""" Generates the matching VkObjectType """
# FIXME: use the xml comments for VkObjectType instead
if not self.name.startswith("Vk") or any(c.isdigit() for c in self.name):
LOGGER.warn("object type generation might fail for: {0}".format(self.name))
I think it would be good to define out a VkObjectType class that is parsed into the VkRegistry. Then at generation time, you should be able to look up the VkObjectType's value/name from the comment.
I'd prefer to see this patch without the FIXME.
type_ = "VK_OBJECT_TYPE"
previous = "f"
for char in self.name[2:]:
if char.isupper() and previous.islower():
type_ += "_"
type_ += char.upper()
previous = char
return type_
class VkMember(object): def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None,
@@ -2276,6 +2291,36 @@ class VkGenerator(object): f.write(" return TRUE;\n") f.write(" }\n") f.write(" return FALSE;\n")
f.write("}\n\n")
f.write("BOOL wine_vk_is_type_wrapped(VkObjectType type)\n")
f.write("{\n")
f.write(" return ")
for handle in self.registry.handles:
if not handle.is_required() or not handle.is_wrapped():
continue
f.write("type == {} || ".format(handle.object_type()))
f.write("FALSE;\n")
f.write("}\n\n")
While it's generated code so it probably doesn't matter much. I think it would be nice if there were some newlines here.
How about generating it to look like:
+BOOL wine_vk_is_type_wrapped(VkObjectType type) +{
- return FALSE ||
type == VK_OBJECT_TYPE_COMMAND_BUFFER ||
type == VK_OBJECT_TYPE_COMMAND_POOL ||
type == VK_OBJECT_TYPE_DEVICE ||
type == VK_OBJECT_TYPE_INSTANCE ||
type == VK_OBJECT_TYPE_PHYSICAL_DEVICE ||
type == VK_OBJECT_TYPE_QUEUE;
+}
Thanks,
Liam Middlebrook
f.write("uint64_t wine_vk_unwrap_handle(VkObjectType type, uint64_t handle)\n")
f.write("{\n")
f.write(" switch(type)\n")
f.write(" {\n")
for handle in self.registry.handles:
if not handle.is_required() or not handle.is_wrapped():
continue
f.write(" case {}:\n".format(handle.object_type()))
if handle.is_dispatchable():
f.write(" return (uint64_t) (uintptr_t) ")
f.write(handle.native_handle("(({}) (uintptr_t) handle)".format(handle.name)))
else:
f.write(" return (uint64_t) ")
f.write(handle.native_handle("handle"))
f.write(";\n");
f.write(" default:\n")
f.write(" return handle;\n")
f.write(" }\n") f.write("}\n") def generate_thunks_h(self, f, prefix):
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index f730c04923..3d1e8bd0ab 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -1534,30 +1534,13 @@ void WINAPI wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDev properties->externalSemaphoreFeatures = 0; }
-static uint64_t unwrap_object_handle(VkObjectType type, uint64_t handle) -{
- switch (type)
- {
case VK_OBJECT_TYPE_DEVICE:
return (uint64_t) (uintptr_t) ((VkDevice) (uintptr_t) handle)->device;
case VK_OBJECT_TYPE_QUEUE:
return (uint64_t) (uintptr_t) ((VkQueue) (uintptr_t) handle)->queue;
case VK_OBJECT_TYPE_COMMAND_BUFFER:
return (uint64_t) (uintptr_t) ((VkCommandBuffer) (uintptr_t) handle)->command_buffer;
case VK_OBJECT_TYPE_COMMAND_POOL:
return (uint64_t) wine_cmd_pool_from_handle(handle)->command_pool;
default:
return handle;
- }
-}
VkResult WINAPI wine_vkSetPrivateDataEXT(VkDevice device, VkObjectType object_type, uint64_t object_handle, VkPrivateDataSlotEXT private_data_slot, uint64_t data) { TRACE("%p, %#x, 0x%s, 0x%s, 0x%s\n", device, object_type, wine_dbgstr_longlong(object_handle), wine_dbgstr_longlong(private_data_slot), wine_dbgstr_longlong(data));
object_handle = unwrap_object_handle(object_type, object_handle);
- object_handle = wine_vk_unwrap_handle(object_type, object_handle); return device->funcs.p_vkSetPrivateDataEXT(device->device, object_type, object_handle, private_data_slot, data); }
@@ -1567,7 +1550,7 @@ void WINAPI wine_vkGetPrivateDataEXT(VkDevice device, VkObjectType object_type, TRACE("%p, %#x, 0x%s, 0x%s, %p\n", device, object_type, wine_dbgstr_longlong(object_handle), wine_dbgstr_longlong(private_data_slot), data);
- object_handle = unwrap_object_handle(object_type, object_handle);
- object_handle = wine_vk_unwrap_handle(object_type, object_handle); device->funcs.p_vkGetPrivateDataEXT(device->device, object_type, object_handle, private_data_slot, data); }
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 4bcc4de440..bf09401c52 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -138,4 +138,7 @@ void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN; BOOL wine_vk_device_extension_supported(const char *name) DECLSPEC_HIDDEN; BOOL wine_vk_instance_extension_supported(const char *name) DECLSPEC_HIDDEN;
+BOOL wine_vk_is_type_wrapped(VkObjectType type) DECLSPEC_HIDDEN; +uint64_t wine_vk_unwrap_handle(VkObjectType type, uint64_t handle) DECLSPEC_HIDDEN;
- #endif /* __WINE_VULKAN_PRIVATE_H */