Signed-off-by: Georg Lehmann dadschoorse@gmail.com --- dlls/winevulkan/make_vulkan | 81 +++++++++++++++++++++++++++----- dlls/winevulkan/vulkan.c | 21 +-------- dlls/winevulkan/vulkan_private.h | 3 ++ 3 files changed, 74 insertions(+), 31 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 7f89cfdabaa..13a4962dd1a 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -371,20 +371,21 @@ class VkEnum(object): # Value is either a value or a bitpos, only one can exist. value = v.attrib.get("value") alias_name = v.attrib.get("alias") + comment = v.attrib.get("comment") if alias_name: alias = next(x for x in values if x.name == alias_name) - values.append(VkEnumValue(v.attrib.get("name"), value=alias.value, hex=alias.hex)) + values.append(VkEnumValue(v.attrib.get("name"), value=alias.value, hex=alias.hex, comment=comment)) elif value: # Some values are in hex form. We want to preserve the hex representation # at least when we convert back to a string. Internally we want to use int. if "0x" in value: - values.append(VkEnumValue(v.attrib.get("name"), value=int(value, 0), hex=True)) + values.append(VkEnumValue(v.attrib.get("name"), value=int(value, 0), hex=True, comment=comment)) else: - values.append(VkEnumValue(v.attrib.get("name"), value=int(value, 0))) + values.append(VkEnumValue(v.attrib.get("name"), value=int(value, 0), comment=comment)) else: # bitmask value = 1 << int(v.attrib.get("bitpos")) - values.append(VkEnumValue(v.attrib.get("name"), value=value, hex=True)) + values.append(VkEnumValue(v.attrib.get("name"), value=value, hex=True, comment=comment))
# vulkan.h contains a *_MAX_ENUM value set to 32-bit at the time of writing, # which is to prepare for extensions as they can add values and hence affect @@ -435,11 +436,12 @@ class VkEnum(object):
class VkEnumValue(object): - def __init__(self, name, value=None, hex=False, alias=None): + def __init__(self, name, value=None, hex=False, alias=None, comment=None): self.name = name self.value = value self.hex = hex self.alias = alias + self.comment = comment
def __repr__(self): if self.is_alias(): @@ -885,6 +887,7 @@ class VkHandle(object): self.parent = parent self.alias = alias self.required = False + self.object_type = None
@staticmethod def from_alias(handle, alias): @@ -939,9 +942,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 +965,9 @@ 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 +
class VkMember(object): def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None, @@ -2276,6 +2279,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 FALSE") + for handle in self.registry.handles: + if not handle.is_required() or not handle.is_wrapped() or handle.is_alias(): + continue + f.write(" ||\n type == {}".format(handle.object_type)) + f.write(";\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() or handle.is_alias(): + 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): @@ -2619,6 +2652,8 @@ class VkRegistry(object): self._parse_features(root) self._parse_extensions(root)
+ self._match_object_types() + self.copyright = root.find('./comment').text
def _is_feature_supported(self, feature): @@ -2689,6 +2724,26 @@ class VkRegistry(object): elif type_info["category"] == "bitmask": mark_bitmask_dependencies(type_info["data"], self.types)
+ def _match_object_types(self): + """ Matches each handle with the correct object type. """ + for handle in self.handles: + if not handle.is_required() or handle.is_alias(): + continue + for value in self.enums["VkObjectType"].values: + if value.comment == handle.name: + handle.object_type = value.name + break + else: + LOGGER.warning("No object type found for {}".format(handle.name)) + + for handle in self.handles: + if not handle.is_required() or not handle.is_alias(): + continue + # Use the object type of the alias + handle.object_type = handle.alias.object_type + if not handle.object_type: + LOGGER.warning("No object type found for {}".format(handle.name)) + def _parse_commands(self, root): """ Parse command section containing the Vulkan function calls. """ funcs = {} @@ -2782,10 +2837,12 @@ class VkRegistry(object): if only_aliased and not aliased: return
+ comment = enum_elem.attrib.get("comment") + if "bitpos" in enum_elem.keys(): # We need to add an extra value to an existing enum type. # E.g. VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG to VkFormatFeatureFlagBits. - enum.add(VkEnumValue(enum_elem.attrib["name"], value=(1 << int(enum_elem.attrib["bitpos"])), hex=True)) + enum.add(VkEnumValue(enum_elem.attrib["name"], value=(1 << int(enum_elem.attrib["bitpos"])), hex=True, comment=comment))
elif "offset" in enum_elem.keys(): # Extensions promoted to Core, have the extension number as part @@ -2802,12 +2859,12 @@ class VkRegistry(object): if direction is not None: value = -value
- enum.add(VkEnumValue(enum_elem.attrib["name"], value=value)) + enum.add(VkEnumValue(enum_elem.attrib["name"], value=value, comment=comment))
elif "value" in enum_elem.keys(): - enum.add(VkEnumValue(enum_elem.attrib["name"], value=int(enum_elem.attrib["value"]))) + enum.add(VkEnumValue(enum_elem.attrib["name"], value=int(enum_elem.attrib["value"]), comment=comment)) elif "alias" in enum_elem.keys(): - enum.add(VkEnumValue(enum_elem.attrib["name"], alias=enum_elem.attrib["alias"])) + enum.add(VkEnumValue(enum_elem.attrib["name"], alias=enum_elem.attrib["alias"], comment=comment))
elif "value" in enum_elem.keys(): # Constants are not aliased, no need to add them here, they'll get added later on. diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index f730c04923a..3d1e8bd0abd 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 4bcc4de440d..bf09401c52a 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 3d1e8bd0abd..c140ff3a0e8 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 bf09401c52a..959a813a213 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)
Signed-off-by: Liam Middlebrook lmiddlebrook@nvidia.com
On 10/13/20 10:28 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 3d1e8bd0abd..c140ff3a0e8 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 bf09401c52a..959a813a213 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)
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49813
Signed-off-by: Georg Lehmann dadschoorse@gmail.com --- dlls/winevulkan/make_vulkan | 10 +- dlls/winevulkan/vulkan.c | 207 +++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_private.h | 29 +++++ 3 files changed, 245 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 13a4962dd1a..f3f2da7548c 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,13 @@ 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}, + "vkSetDebugUtilsObjectTagEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True}, + "vkSetDebugUtilsObjectNameEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True}, }
STRUCT_CHAIN_CONVERSIONS = [ @@ -944,6 +950,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 c140ff3a0e8..92c26be1fc0 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; + unsigned 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,108 @@ 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; + unsigned 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, severity, types, &native_callback_data); + + heap_free(object_names); +} + +VkResult WINAPI wine_vkSetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *tag_info) +{ + VkDebugUtilsObjectTagInfoEXT wine_tag_info; + + TRACE("%p, %p\n", device, tag_info); + + wine_tag_info = *tag_info; + wine_tag_info.objectHandle = wine_vk_unwrap_handle(tag_info->objectType, tag_info->objectHandle); + + return thunk_vkSetDebugUtilsObjectTagEXT(device, &wine_tag_info); +} + +VkResult WINAPI wine_vkSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *name_info) +{ + VkDebugUtilsObjectNameInfoEXT wine_name_info; + + TRACE("%p, %p\n", device, name_info); + + wine_name_info = *name_info; + wine_name_info.objectHandle = wine_vk_unwrap_handle(name_info->objectType, name_info->objectHandle); + + return thunk_vkSetDebugUtilsObjectNameEXT(device, &wine_name_info); +} + 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 959a813a213..eec0ef595d0 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,30 @@ 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;
Signed-off-by: Liam Middlebrook lmiddlebrook@nvidia.com
Additionally adding a:
Tested-by: Liam Middlebrook lmiddlebrook@nvidia.com
since I verified that this implementation allows for me to see Label start/end regions when inspecting Quake II RTX running in WINE with Nsight Systems.
Thanks,
Liam Middlebrook
On 10/13/20 10:28 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 | 10 +- dlls/winevulkan/vulkan.c | 207 +++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_private.h | 29 +++++ 3 files changed, 245 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 13a4962dd1a..f3f2da7548c 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,13 @@ 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},
"vkSetDebugUtilsObjectTagEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True},
"vkSetDebugUtilsObjectNameEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True}, }
STRUCT_CHAIN_CONVERSIONS = [
@@ -944,6 +950,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 c140ff3a0e8..92c26be1fc0 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;
- unsigned 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,108 @@ 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;
- unsigned 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, severity, types, &native_callback_data);
- heap_free(object_names);
+}
+VkResult WINAPI wine_vkSetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *tag_info) +{
- VkDebugUtilsObjectTagInfoEXT wine_tag_info;
- TRACE("%p, %p\n", device, tag_info);
- wine_tag_info = *tag_info;
- wine_tag_info.objectHandle = wine_vk_unwrap_handle(tag_info->objectType, tag_info->objectHandle);
- return thunk_vkSetDebugUtilsObjectTagEXT(device, &wine_tag_info);
+}
+VkResult WINAPI wine_vkSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *name_info) +{
- VkDebugUtilsObjectNameInfoEXT wine_name_info;
- TRACE("%p, %p\n", device, name_info);
- wine_name_info = *name_info;
- wine_name_info.objectHandle = wine_vk_unwrap_handle(name_info->objectType, name_info->objectHandle);
- return thunk_vkSetDebugUtilsObjectNameEXT(device, &wine_name_info);
+}
- 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 959a813a213..eec0ef595d0 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,30 @@ 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;
Signed-off-by: Liam Middlebrook lmiddlebrook@nvidia.com
On 10/13/20 10:28 AM, Georg Lehmann wrote:
Signed-off-by: Georg Lehmann dadschoorse@gmail.com
dlls/winevulkan/make_vulkan | 81 +++++++++++++++++++++++++++----- dlls/winevulkan/vulkan.c | 21 +-------- dlls/winevulkan/vulkan_private.h | 3 ++ 3 files changed, 74 insertions(+), 31 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 7f89cfdabaa..13a4962dd1a 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -371,20 +371,21 @@ class VkEnum(object): # Value is either a value or a bitpos, only one can exist. value = v.attrib.get("value") alias_name = v.attrib.get("alias")
comment = v.attrib.get("comment") if alias_name: alias = next(x for x in values if x.name == alias_name)
values.append(VkEnumValue(v.attrib.get("name"), value=alias.value, hex=alias.hex))
values.append(VkEnumValue(v.attrib.get("name"), value=alias.value, hex=alias.hex, comment=comment)) elif value: # Some values are in hex form. We want to preserve the hex representation # at least when we convert back to a string. Internally we want to use int. if "0x" in value:
values.append(VkEnumValue(v.attrib.get("name"), value=int(value, 0), hex=True))
values.append(VkEnumValue(v.attrib.get("name"), value=int(value, 0), hex=True, comment=comment)) else:
values.append(VkEnumValue(v.attrib.get("name"), value=int(value, 0)))
values.append(VkEnumValue(v.attrib.get("name"), value=int(value, 0), comment=comment)) else: # bitmask value = 1 << int(v.attrib.get("bitpos"))
values.append(VkEnumValue(v.attrib.get("name"), value=value, hex=True))
values.append(VkEnumValue(v.attrib.get("name"), value=value, hex=True, comment=comment)) # vulkan.h contains a *_MAX_ENUM value set to 32-bit at the time of writing, # which is to prepare for extensions as they can add values and hence affect
@@ -435,11 +436,12 @@ class VkEnum(object):
class VkEnumValue(object):
- def __init__(self, name, value=None, hex=False, alias=None):
def __init__(self, name, value=None, hex=False, alias=None, comment=None): self.name = name self.value = value self.hex = hex self.alias = alias
self.comment = comment def __repr__(self): if self.is_alias():
@@ -885,6 +887,7 @@ class VkHandle(object): self.parent = parent self.alias = alias self.required = False
self.object_type = None @staticmethod def from_alias(handle, alias):
@@ -939,9 +942,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 +965,9 @@ 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
class VkMember(object): def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None,
@@ -2276,6 +2279,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 FALSE")
for handle in self.registry.handles:
if not handle.is_required() or not handle.is_wrapped() or handle.is_alias():
continue
f.write(" ||\n type == {}".format(handle.object_type))
f.write(";\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() or handle.is_alias():
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):
@@ -2619,6 +2652,8 @@ class VkRegistry(object): self._parse_features(root) self._parse_extensions(root)
self._match_object_types()
self.copyright = root.find('./comment').text def _is_feature_supported(self, feature):
@@ -2689,6 +2724,26 @@ class VkRegistry(object): elif type_info["category"] == "bitmask": mark_bitmask_dependencies(type_info["data"], self.types)
- def _match_object_types(self):
""" Matches each handle with the correct object type. """
for handle in self.handles:
if not handle.is_required() or handle.is_alias():
continue
for value in self.enums["VkObjectType"].values:
if value.comment == handle.name:
handle.object_type = value.name
break
else:
LOGGER.warning("No object type found for {}".format(handle.name))
for handle in self.handles:
if not handle.is_required() or not handle.is_alias():
continue
# Use the object type of the alias
handle.object_type = handle.alias.object_type
if not handle.object_type:
LOGGER.warning("No object type found for {}".format(handle.name))
def _parse_commands(self, root): """ Parse command section containing the Vulkan function calls. """ funcs = {}
@@ -2782,10 +2837,12 @@ class VkRegistry(object): if only_aliased and not aliased: return
comment = enum_elem.attrib.get("comment")
if "bitpos" in enum_elem.keys(): # We need to add an extra value to an existing enum type. # E.g. VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG to VkFormatFeatureFlagBits.
enum.add(VkEnumValue(enum_elem.attrib["name"], value=(1 << int(enum_elem.attrib["bitpos"])), hex=True))
enum.add(VkEnumValue(enum_elem.attrib["name"], value=(1 << int(enum_elem.attrib["bitpos"])), hex=True, comment=comment)) elif "offset" in enum_elem.keys(): # Extensions promoted to Core, have the extension number as part
@@ -2802,12 +2859,12 @@ class VkRegistry(object): if direction is not None: value = -value
enum.add(VkEnumValue(enum_elem.attrib["name"], value=value))
enum.add(VkEnumValue(enum_elem.attrib["name"], value=value, comment=comment)) elif "value" in enum_elem.keys():
enum.add(VkEnumValue(enum_elem.attrib["name"], value=int(enum_elem.attrib["value"])))
enum.add(VkEnumValue(enum_elem.attrib["name"], value=int(enum_elem.attrib["value"]), comment=comment)) elif "alias" in enum_elem.keys():
enum.add(VkEnumValue(enum_elem.attrib["name"], alias=enum_elem.attrib["alias"]))
enum.add(VkEnumValue(enum_elem.attrib["name"], alias=enum_elem.attrib["alias"], comment=comment)) elif "value" in enum_elem.keys(): # Constants are not aliased, no need to add them here, they'll get added later on.
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index f730c04923a..3d1e8bd0abd 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 4bcc4de440d..bf09401c52a 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 */