From c8ab9d2584c50daed02c634efa738e01216a35e1 Mon Sep 17 00:00:00 2001 From: leegao Date: Mon, 11 Aug 2025 23:03:18 +1000 Subject: [PATCH 1/3] Add WRAPPER macros that logs all wrapper entry/exist --- src/vulkan/wrapper/vk_entrypoints.py | 101 +++++++++++++++++- src/vulkan/wrapper/vk_unwrapper_gen.py | 2 +- .../wrapper/vk_wrapper_trampolines_gen.py | 14 ++- src/vulkan/wrapper/wrapper_checks.h | 4 + src/vulkan/wrapper/wrapper_debug.c | 18 ++++ src/vulkan/wrapper/wrapper_debug.h | 4 +- src/vulkan/wrapper/wrapper_device.c | 1 + src/vulkan/wrapper/wrapper_device_memory.c | 28 +---- src/vulkan/wrapper/wrapper_image.c | 10 +- src/vulkan/wrapper/wrapper_instance.c | 16 ++- src/vulkan/wrapper/wrapper_log.c | 2 + src/vulkan/wrapper/wrapper_log.h | 7 +- src/vulkan/wrapper/wrapper_physical_device.c | 21 ++-- 13 files changed, 166 insertions(+), 62 deletions(-) diff --git a/src/vulkan/wrapper/vk_entrypoints.py b/src/vulkan/wrapper/vk_entrypoints.py index f07417ce6ad..91a0651d33e 100644 --- a/src/vulkan/wrapper/vk_entrypoints.py +++ b/src/vulkan/wrapper/vk_entrypoints.py @@ -54,7 +54,7 @@ wrapper_tramp_$name( $decl_params) { - int cmd_id = commands++; + int cmd_id = __wrapper_commands++; struct temporary_objects temp; list_inithead(&temp.objects); $handle_unwrap_logic @@ -64,6 +64,7 @@ return $return_block; }""") + COMMAND_BLACKLIST = [ 'FreeCommandBuffers', # implemented 'CreateDevice', # implemented @@ -169,7 +170,7 @@ def _generate_trampoline(command, dispatch_table="device->dispatch_table"): physical_device = "base->physical" # handle_unwrap_logic.append(f"#ifdef NEEDS_PRINTING_{command.name}") - handle_unwrap_logic.append(f" VK_CMD_LOG(\"{command.name} (id=%d)\", cmd_id);") + handle_unwrap_logic.append(f" VK_CMD_LOG(\"dispatch->{command.name} (id=%d)\", cmd_id);") # handle_unwrap_logic.append(f"#endif") handle_unwrap_logic.append(f"") @@ -359,7 +360,7 @@ def _generate_trampoline(command, dispatch_table="device->dispatch_table"): if command.return_type == 'VkResult' and command.name not in SPAMMY_COMMANDS: logger = "WLOGE" if command.name not in ("AllocateDescriptorSets", "GetPhysicalDeviceImageFormatProperties") else "WLOG" handle_wrap_logic.append(f" if (result != VK_SUCCESS) {{") - handle_wrap_logic.append(f" {logger}(\"Call to {command.name} with ({",".join(types)}) failed with result: %d\", {",".join(call)}, result);") + handle_wrap_logic.append(f" {logger}(\"dispatch->{command.name}({",".join(types)}) failed with result: %d (id=%d)\", {",".join(call)}, result, cmd_id);") handle_wrap_logic.append(f" }}") if command.return_type == 'VkResult': @@ -371,7 +372,9 @@ def _generate_trampoline(command, dispatch_table="device->dispatch_table"): return_block = "" if command.return_type == 'void' else "result" assign_block = "" if command.return_type == 'void' else f"{command.return_type} result = " - handle_unwrap_logic[idx] = f"WLOGA(\"{command.name}({', '.join(types)})\", {', '.join([p.name for p in params])});" + if command.name not in SPAMMY_COMMANDS: + handle_unwrap_logic[idx] = f" WLOGA(\"dispatch->{command.name}({', '.join(types)}) (id=%d)\", {', '.join([p.name for p in params])}, cmd_id);" + handle_wrap_logic.append(f" WLOGA(\"dispatch->{command.name} {'returned %d' if command.return_type != 'void' else 'finished'} (id=%d)\"{', result' if command.return_type != 'void' else ''}, cmd_id);") return TRAMPOLINE_TEMPLATE.substitute( return_type=command.return_type, @@ -402,6 +405,18 @@ def __init__(self, name): def prefixed_name(self, prefix): return prefix + '_' + self.name +WRAP_TEMPLATE = string.Template(""" +VKAPI_ATTR $return_type VKAPI_CALL wrapper_$name($decl_params) { + int cmd_id = __wrapper_commands++; + WLOGT("wrapper->$name($type_params) (id=%d)", $call_params, cmd_id); + bool should_print = VK_CMD_CAN_TRACE; +$PRINT_PRE + $assign __wrapper_$name($call_params); + WLOGT("wrapper->$name $return_str (id=%d)", $return_fmt cmd_id); +$PRINT_POST + return $result; +}""") + class Entrypoint(EntrypointBase): def __init__(self, name, return_type, params): super(Entrypoint, self).__init__(name) @@ -443,6 +458,84 @@ def trampoline(self): return _generate_trampoline(self, dispatch_table="base->dispatch_table") else: return _generate_trampoline(self, dispatch_table="base->device->dispatch_table") + + def wrap(self): + if self.alias: + return "" + + call = [param.name for param in self.params] + types = [] + + for param in self.params: + is_input = param.num_pointers == 0 or param.is_const + + if not is_input: + types.append(f"{param.name}: %p") + continue + is_wrapped = param.type in WrappedStructs + is_struct = param.type in TYPES + is_special = param.type in SPECIAL_TYPES + + # Wrapped handles + if is_wrapped: + types.append(f"{param.name}: %p") + elif is_struct: + types.append(f"{param.name}: %p") + elif is_special: + types.append(f"{param.name}: %x") + else: + types.append(f"{param.name}: %x") + # handle_wrap_logic.append(f" WLOGA(\"dispatch->{command.name} {'returned %d' if command.return_type != 'void' else 'finished'} (id=%d)\"{', result' if command.return_type != 'void' else ''}, cmd_id);") + pre_print = [] + pre_print.append(f" if (should_log) {{") + pre_print.append(f" VK_CMD_LOG(\"wrapper_{self.name} (id=%d)\", cmd_id);") + # pre_print += print_param(self, self.params[0], mode='input') + for param in self.params: + if self.name in COMMAND_BLACKLIST: + continue + is_input = param.num_pointers == 0 or param.is_const + if not is_input: + continue + pre_print += print_param(self, param, mode='input') + pre_print.append(f" VK_CMD_FLUSH();") + pre_print.append(f" }}") + + post_print = [] + post_print.append(f" if (should_log) {{") + if self.return_type == 'VkResult': + post_print += print_param(self, 'result', mode='output') + for param in self.params[1:]: + if self.name in COMMAND_BLACKLIST: + continue + is_input = param.num_pointers == 0 or param.is_const + if is_input: + continue + if self.return_type == 'VkResult': + post_print.append(f" if ({param.name} && result == VK_SUCCESS) {{") + else: + post_print.append(f" if ({param.name}) {{") + post_print += print_param(self, param, mode='output') + post_print.append(f" }} else {{") + post_print += [ + f" VK_CMD_LOG_UNCONDITIONAL(\" out: *{param.name}: {param.type}* = %p\", {param.name});", + f" }}" + ] + post_print.append(f" }}") + + + return WRAP_TEMPLATE.substitute( + return_type=self.return_type, + name=self.name, + assign=f"{self.return_type} result =" if self.return_type != "void" else "", + result=f"result" if self.return_type != "void" else "", + decl_params=self.decl_params(), + call_params=", ".join(call), + type_params=types, + return_str='returned %d' if self.return_type != 'void' else 'finished', + return_fmt='result,' if self.return_type != 'void' else '', + PRINT_PRE="\n".join(pre_print), + PRINT_POST="\n".join(post_print), + ) class EntrypointAlias(EntrypointBase): def __init__(self, name, entrypoint): diff --git a/src/vulkan/wrapper/vk_unwrapper_gen.py b/src/vulkan/wrapper/vk_unwrapper_gen.py index 4bb81889fe7..020057cb72f 100644 --- a/src/vulkan/wrapper/vk_unwrapper_gen.py +++ b/src/vulkan/wrapper/vk_unwrapper_gen.py @@ -191,7 +191,7 @@ 'VkWin32SurfaceCreateInfoKHR', # Too complex, and not needed # 'VkDeviceCreateInfo', # 2d array of cstrings - 'VkInstanceCreateInfo', + # 'VkInstanceCreateInfo', 'VkMicromapVersionInfoEXT', # latexmath 'VkPipelineMultisampleStateCreateInfo', # latexmath 'VkPipelineMultisampleStateCreateInfo', # latexmath diff --git a/src/vulkan/wrapper/vk_wrapper_trampolines_gen.py b/src/vulkan/wrapper/vk_wrapper_trampolines_gen.py index 2f40a6e0ac2..ee607d6cee1 100644 --- a/src/vulkan/wrapper/vk_wrapper_trampolines_gen.py +++ b/src/vulkan/wrapper/vk_wrapper_trampolines_gen.py @@ -57,6 +57,8 @@ extern struct wrapper_entry_masks wrapper_printer_masks; +_Atomic extern int __wrapper_commands; + % for e in entrypoints: % if e.alias: <% continue %> @@ -75,6 +77,16 @@ #define has_device_wrapper_${e.name}(...) (wrapper_device_entrypoints.${e.name}) #define has_physical_device_wrapper_${e.name}(...) (wrapper_physical_device_entrypoints.${e.name}) #define name_of_wrapper_${e.name}(...) "wrapper_${e.name}" + +#define WRAPPED_${e.name} ${"\\n".join([line + " \\\\" for line in e.wrap().split("\\n")])} + +#define RETURN_${e.name} VKAPI_ATTR ${e.return_type} VKAPI_CALL +#define WRAPPER_NAME_${e.name}(...) ${e.name} +#define WRAPPER_${e.name}(...) \\\\\n +static RETURN_${e.name} __wrapper_${e.name}(__VA_ARGS__); \\\\\n +WRAPPED_${e.name} \\\\\n +static RETURN_${e.name} __wrapper_${e.name}(__VA_ARGS__) + % if e.guard is not None: #else #define TRY_${e.name}(TRUE, FALSE) FALSE @@ -113,7 +125,7 @@ #include "vk_unwrappers.h" #include "vk_printers.h" -_Atomic static int commands = 0; +_Atomic int __wrapper_commands = 0; #define VK_PRINT_VkAccelerationStructureVersionInfoKHR(...) #define VK_PRINT_VkAccelerationStructureBuildGeometryInfoKHR(...) diff --git a/src/vulkan/wrapper/wrapper_checks.h b/src/vulkan/wrapper/wrapper_checks.h index 407f30eabf9..997ff2bad39 100644 --- a/src/vulkan/wrapper/wrapper_checks.h +++ b/src/vulkan/wrapper/wrapper_checks.h @@ -27,3 +27,7 @@ #define WCHECKV(call) {__W_WRAP__(call, { if(has_device_wrapper_##call) { __CHECKV__(wrapper_device_entrypoints. call); } else { CHECKV(call); }})} #define WPCHECK(call) ({__W_WRAP__(call, has_physical_device_wrapper_##call ? __CHECK__(wrapper_physical_device_entrypoints. call) : PCHECK(call))}) #define WPCHECKV(call) {__W_WRAP__(call, { if(has_physical_device_wrapper_##call) { __CHECKV__(wrapper_physical_device_entrypoints. call); } else { PCHECKV(call); }})} + +#define __WRAP(call) return call + +#define __WRAPV(call) call diff --git a/src/vulkan/wrapper/wrapper_debug.c b/src/vulkan/wrapper/wrapper_debug.c index 99d3ef8fd51..7627d26114d 100644 --- a/src/vulkan/wrapper/wrapper_debug.c +++ b/src/vulkan/wrapper/wrapper_debug.c @@ -348,3 +348,21 @@ bool use_compute_shader_mode() { return g_use_compute_shader_mode; } + + +bool use_wrapper_trace() { + static bool value; + static bool init; + if (init) + return value; + init = true; + const char* mask_bcn = getenv("WRAPPER_CMD_LOG_LEVEL"); + if (!mask_bcn) + return value = false; + + if (strstr(mask_bcn, "trace")) { + return value = true; + } + + return value = false; +} diff --git a/src/vulkan/wrapper/wrapper_debug.h b/src/vulkan/wrapper/wrapper_debug.h index 5bbd6d0ed17..39ef0fa8fed 100644 --- a/src/vulkan/wrapper/wrapper_debug.h +++ b/src/vulkan/wrapper/wrapper_debug.h @@ -26,4 +26,6 @@ void initialize_cmd_print_masks(void); bool use_image_view_mode(void); -bool use_compute_shader_mode(void); \ No newline at end of file +bool use_compute_shader_mode(void); + +bool use_wrapper_trace(void); \ No newline at end of file diff --git a/src/vulkan/wrapper/wrapper_device.c b/src/vulkan/wrapper/wrapper_device.c index 1b6401e25e7..da978f273d0 100644 --- a/src/vulkan/wrapper/wrapper_device.c +++ b/src/vulkan/wrapper/wrapper_device.c @@ -16,6 +16,7 @@ #include "wrapper_trampolines.h" #include "wrapper_debug.h" #include "vk_unwrappers.h" +#include "vk_printers.h" #include "spirv_edit.h" #include "bcdec.h" diff --git a/src/vulkan/wrapper/wrapper_device_memory.c b/src/vulkan/wrapper/wrapper_device_memory.c index 4f140adfb4f..36688ea68fd 100644 --- a/src/vulkan/wrapper/wrapper_device_memory.c +++ b/src/vulkan/wrapper/wrapper_device_memory.c @@ -295,8 +295,7 @@ wrapper_device_memory_from_handle(struct wrapper_device *device, return mem; } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_AllocateMemory(VkDevice _device, +WRAPPER_AllocateMemory(VkDevice _device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) { @@ -304,19 +303,6 @@ wrapper_AllocateMemory(VkDevice _device, struct wrapper_device_memory *mem; VkResult result; - // LOG("in wrapper_AllocateMemory"); - - // __vk_println_all("AllocateMemory"); - // __loga("AllocateMemory(device: %p, pAllocateInfo: %p, pAllocator: %p, pMemory: %p)", device, pAllocateInfo, pAllocator, pMemory); - // __vk_println(" in: device: VkDevice (handle) = %p", device); - // __vk_flush(2); - // __vk_println(" in: pAllocateInfo: VkMemoryAllocateInfo*"); - // vk_print_VkMemoryAllocateInfo(" ", pAllocateInfo); - // __vk_flush(2); - // __vk_println(" in: pAllocator: VkAllocationCallbacks*"); - // vk_print_VkAllocationCallbacks(" ", pAllocator); - // __vk_flush(2); - VkMemoryPropertyFlags property_flags = device->physical->memory_properties.memoryTypes[ pAllocateInfo->memoryTypeIndex].propertyFlags; @@ -376,8 +362,7 @@ wrapper_AllocateMemory(VkDevice _device, return result; } -VKAPI_ATTR void VKAPI_CALL -wrapper_FreeMemory(VkDevice _device, VkDeviceMemory _memory, +WRAPPER_FreeMemory(VkDevice _device, VkDeviceMemory _memory, const VkAllocationCallbacks* pAllocator) { VK_FROM_HANDLE(wrapper_device, device, _device); @@ -394,8 +379,7 @@ wrapper_FreeMemory(VkDevice _device, VkDeviceMemory _memory, pAllocator); } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_MapMemory2KHR(VkDevice _device, +WRAPPER_MapMemory2KHR(VkDevice _device, const VkMemoryMapInfoKHR* pMemoryMapInfo, void** ppData) { @@ -467,13 +451,11 @@ wrapper_MapMemory2KHR(VkDevice _device, return VK_SUCCESS; } -VKAPI_ATTR void VKAPI_CALL -wrapper_UnmapMemory(VkDevice _device, VkDeviceMemory _memory) { +WRAPPER_UnmapMemory(VkDevice _device, VkDeviceMemory _memory) { vk_common_UnmapMemory(_device, _memory); } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_UnmapMemory2KHR(VkDevice _device, +WRAPPER_UnmapMemory2KHR(VkDevice _device, const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo) { VK_FROM_HANDLE(wrapper_device, device, _device); diff --git a/src/vulkan/wrapper/wrapper_image.c b/src/vulkan/wrapper/wrapper_image.c index 6e40876b6a3..619069e420d 100644 --- a/src/vulkan/wrapper/wrapper_image.c +++ b/src/vulkan/wrapper/wrapper_image.c @@ -13,9 +13,7 @@ #include #endif - -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_CreateImage(VkDevice _device, +WRAPPER_CreateImage(VkDevice _device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage) @@ -73,8 +71,7 @@ wrapper_CreateImage(VkDevice _device, return result; } -VKAPI_ATTR void VKAPI_CALL -wrapper_DestroyImage(VkDevice _device, +WRAPPER_DestroyImage(VkDevice _device, VkImage _image, const VkAllocationCallbacks* pAllocator) { @@ -91,8 +88,7 @@ wrapper_DestroyImage(VkDevice _device, } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_CreateImageView( +WRAPPER_CreateImageView( VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, diff --git a/src/vulkan/wrapper/wrapper_instance.c b/src/vulkan/wrapper/wrapper_instance.c index 49bc8c3a5a8..6b864c68962 100644 --- a/src/vulkan/wrapper/wrapper_instance.c +++ b/src/vulkan/wrapper/wrapper_instance.c @@ -6,6 +6,7 @@ #include "vk_extensions.h" #include "vk_debug_utils.h" #include "wrapper_debug.h" +#include "vk_printers.h" const struct vk_instance_extension_table wrapper_instance_extensions = { .KHR_get_surface_capabilities2 = true, @@ -161,8 +162,7 @@ static VkResult wrapper_vulkan_init() return VK_SUCCESS; } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_EnumerateInstanceVersion(uint32_t* pApiVersion) +WRAPPER_EnumerateInstanceVersion(uint32_t* pApiVersion) { if (!vulkan_library_init()) @@ -171,8 +171,7 @@ wrapper_EnumerateInstanceVersion(uint32_t* pApiVersion) return enumerate_instance_version(pApiVersion); } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_EnumerateInstanceExtensionProperties(const char* pLayerName, +WRAPPER_EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) { @@ -235,8 +234,7 @@ static void wrapper_register_internal_log_callback(struct wrapper_instance *inst instance->internal_debug_messenger = messenger; } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, +WRAPPER_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) { @@ -352,8 +350,7 @@ wrapper_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, return VK_SUCCESS; } -VKAPI_ATTR void VKAPI_CALL -wrapper_DestroyInstance(VkInstance _instance, +WRAPPER_DestroyInstance(VkInstance _instance, const VkAllocationCallbacks *pAllocator) { VK_FROM_HANDLE(wrapper_instance, instance, _instance); @@ -372,8 +369,7 @@ wrapper_DestroyInstance(VkInstance _instance, pAllocator); } -VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL -wrapper_GetInstanceProcAddr(VkInstance _instance, +WRAPPER_GetInstanceProcAddr(VkInstance _instance, const char *pName) { diff --git a/src/vulkan/wrapper/wrapper_log.c b/src/vulkan/wrapper/wrapper_log.c index 3cbbed00d29..fb7a1b51dfe 100644 --- a/src/vulkan/wrapper/wrapper_log.c +++ b/src/vulkan/wrapper/wrapper_log.c @@ -108,6 +108,8 @@ int should_log() { __log_level = LOG_LEVEL_ERROR; } else if (strcmp(log_level, "all") == 0) { __log_level = LOG_LEVEL_ALL; + } else if (strcmp(log_level, "trace") == 0) { + __log_level = LOG_LEVEL_TRACE; } else if (strcmp(log_level, "debug") == 0) { __log_level = LOG_LEVEL_DEBUG; } else if (strcmp(log_level, "verbose") == 0) { diff --git a/src/vulkan/wrapper/wrapper_log.h b/src/vulkan/wrapper/wrapper_log.h index 976fcf508e5..03b8c855ddb 100644 --- a/src/vulkan/wrapper/wrapper_log.h +++ b/src/vulkan/wrapper/wrapper_log.h @@ -4,6 +4,8 @@ extern "C" { #endif +#include "wrapper_debug.h" + #include #include #include @@ -19,7 +21,8 @@ extern int __android_log_print( // For wrapper log #define LOG_FD get_wrapper_log_fd() -#define LOG_LEVEL_ALL 4 +#define LOG_LEVEL_ALL 5 +#define LOG_LEVEL_TRACE 4 #define LOG_LEVEL_DEBUG 3 #define LOG_LEVEL_VERBOSE 2 #define LOG_LEVEL_ERROR 1 @@ -42,6 +45,7 @@ extern int __android_log_print( LOG(WFORMAT(fmt, ## __VA_ARGS__)); \ } +#define WLOGT(fmt, ...) __WLOG__(LOG_LEVEL_TRACE, "" fmt, ## __VA_ARGS__) #define WLOGA(fmt, ...) __WLOG__(LOG_LEVEL_ALL, "! " fmt, ## __VA_ARGS__) #define WLOGD(fmt, ...) __WLOG__(LOG_LEVEL_DEBUG, fmt, ## __VA_ARGS__) #define WLOG(fmt, ...) __WLOG__(LOG_LEVEL_VERBOSE, fmt, ## __VA_ARGS__) @@ -73,6 +77,7 @@ extern int __android_log_print( #define VK_CMD_LOGA(...) __VK_CMD_LOG(VK_CMD_CAN_LOG_LEVEL, VK_CMD_ALL, VK_CMD_FD, __VA_ARGS__) #define VK_CMD_CAN_LOGA ((VK_CMD_CAN_LOG_LEVEL >= VK_CMD_ALL) && (VK_CMD_FD)) +#define VK_CMD_CAN_TRACE ((VK_CMD_CAN_LOG_LEVEL >= VK_CMD_ALL) && (VK_CMD_FD) && use_wrapper_trace()) #define VK_CMD_PRINTF(fmt, ...) { if ((VK_CMD_CAN_LOG_LEVEL >= VK_CMD_ALL) && (VK_CMD_FD)) fprintf(VK_CMD_FD, fmt, ## __VA_ARGS__); } #define VK_CMD_FLUSH() { if ((VK_CMD_CAN_LOG_LEVEL >= VK_CMD_ALL) && (VK_CMD_FD)) fflush(VK_CMD_FD); } diff --git a/src/vulkan/wrapper/wrapper_physical_device.c b/src/vulkan/wrapper/wrapper_physical_device.c index ac307391a68..b53c5e28ed7 100644 --- a/src/vulkan/wrapper/wrapper_physical_device.c +++ b/src/vulkan/wrapper/wrapper_physical_device.c @@ -270,8 +270,7 @@ void destroy_physical_device(struct vk_physical_device *pdevice) { vk_free(&pdevice->instance->alloc, pdevice); } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, +WRAPPER_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) @@ -289,15 +288,13 @@ wrapper_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, return result; } -VKAPI_ATTR void VKAPI_CALL -wrapper_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, +WRAPPER_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) { return vk_common_GetPhysicalDeviceFeatures(physicalDevice, pFeatures); } -VKAPI_ATTR void VKAPI_CALL -wrapper_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, +WRAPPER_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) { vk_common_GetPhysicalDeviceFeatures2(physicalDevice, pFeatures); // Fake select dxvk 1.10.3 mandatory features @@ -332,8 +329,7 @@ wrapper_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, } } -VKAPI_ATTR void VKAPI_CALL -wrapper_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, +WRAPPER_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) { VK_FROM_HANDLE(wrapper_physical_device, pdevice, physicalDevice); @@ -433,8 +429,7 @@ wrapper_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, } } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, +WRAPPER_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, @@ -493,8 +488,7 @@ wrapper_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, return result; } -VKAPI_ATTR VkResult VKAPI_CALL -wrapper_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, +WRAPPER_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) { @@ -586,8 +580,7 @@ wrapper_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, return result; } -VKAPI_ATTR void VKAPI_CALL -wrapper_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, +WRAPPER_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) { From 55110a7ec3bce70b55d072029f71a57ca52dc1a5 Mon Sep 17 00:00:00 2001 From: leegao Date: Mon, 11 Aug 2025 23:46:45 +1000 Subject: [PATCH 2/3] Add more memory debugging for addr_placed and external mem emulation --- src/vulkan/wrapper/wrapper_debug.c | 4 ++ src/vulkan/wrapper/wrapper_debug.h | 4 +- src/vulkan/wrapper/wrapper_device_memory.c | 53 +++++++++++++++++++--- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/vulkan/wrapper/wrapper_debug.c b/src/vulkan/wrapper/wrapper_debug.c index 7627d26114d..9e14dab1609 100644 --- a/src/vulkan/wrapper/wrapper_debug.c +++ b/src/vulkan/wrapper/wrapper_debug.c @@ -366,3 +366,7 @@ bool use_wrapper_trace() { return value = false; } + +bool should_log_memory_debug() { + return CHECK_FLAG("DEBUG_MEMORY"); +} diff --git a/src/vulkan/wrapper/wrapper_debug.h b/src/vulkan/wrapper/wrapper_debug.h index 39ef0fa8fed..f45b7ed9bec 100644 --- a/src/vulkan/wrapper/wrapper_debug.h +++ b/src/vulkan/wrapper/wrapper_debug.h @@ -28,4 +28,6 @@ bool use_image_view_mode(void); bool use_compute_shader_mode(void); -bool use_wrapper_trace(void); \ No newline at end of file +bool use_wrapper_trace(void); + +bool should_log_memory_debug(void); \ No newline at end of file diff --git a/src/vulkan/wrapper/wrapper_device_memory.c b/src/vulkan/wrapper/wrapper_device_memory.c index 36688ea68fd..575fe1ef3f0 100644 --- a/src/vulkan/wrapper/wrapper_device_memory.c +++ b/src/vulkan/wrapper/wrapper_device_memory.c @@ -303,12 +303,21 @@ WRAPPER_AllocateMemory(VkDevice _device, struct wrapper_device_memory *mem; VkResult result; + bool debug = should_log_memory_debug(); + + if (debug) { + WLOGD("WRAPPER_AllocateMemory, pAllocateInfo:"); + LOG_STRUCT(VkMemoryAllocateInfo, pAllocateInfo); + } + VkMemoryPropertyFlags property_flags = device->physical->memory_properties.memoryTypes[ pAllocateInfo->memoryTypeIndex].propertyFlags; - if (!(property_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) + if (!(property_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { + if (debug) WLOGD("Memory type %d does not support VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT", pAllocateInfo->memoryTypeIndex); goto fallback; + } if (!device->vk.enabled_features.memoryMapPlaced || !device->vk.enabled_extensions.EXT_map_memory_placed) @@ -323,6 +332,7 @@ WRAPPER_AllocateMemory(VkDevice _device, if (vk_find_struct_const(pAllocateInfo, EXPORT_MEMORY_ALLOCATE_INFO)) goto fallback; + if (debug) WLOGD("Emulating AllocateMemory"); simple_mtx_lock(&device->resource_mutex); result = wrapper_device_memory_create(device, pAllocator, &mem); @@ -331,17 +341,22 @@ WRAPPER_AllocateMemory(VkDevice _device, goto out; } + if (debug) WLOGD("Trying dmabuf"); result = wrapper_allocate_memory_dmabuf(device, pAllocateInfo, pAllocator, &mem->dispatch_handle, &mem->dmabuf_fd); if (result != VK_SUCCESS) { wrapper_device_memory_reset(mem); + + if (debug) WLOGD("Trying dmaheap"); result = wrapper_allocate_memory_dmaheap(device, pAllocateInfo, pAllocator, &mem->dispatch_handle, &mem->dmabuf_fd); } if (result != VK_SUCCESS) { wrapper_device_memory_reset(mem); + + if (debug) WLOGD("Trying ahb"); result = wrapper_allocate_memory_ahardware_buffer(device, pAllocateInfo, pAllocator, &mem->dispatch_handle, &mem->ahardware_buffer); } @@ -351,14 +366,18 @@ WRAPPER_AllocateMemory(VkDevice _device, vk_error(device, result); } else { *pMemory = mem->dispatch_handle; + if (debug) WLOGD("AllocateMemory out VkDeviceMemory: %p", *pMemory); } out: simple_mtx_unlock(&mem->device->resource_mutex); + if (debug) WLOGD("vkAllocateMemory returned %d", result); return result; fallback: + if (debug) WLOGD("Dispatching to vkAllocateMemory (not emulating AllocateMemory)"); result = CHECK(AllocateMemory(_device, pAllocateInfo, pAllocator, pMemory)); + if (debug) WLOGD("vkAllocateMemory returned %d", result); return result; } @@ -384,31 +403,44 @@ WRAPPER_MapMemory2KHR(VkDevice _device, void** ppData) { VK_FROM_HANDLE(wrapper_device, device, _device); + bool debug = should_log_memory_debug(); const VkMemoryMapPlacedInfoEXT *placed_info = NULL; struct wrapper_device_memory *mem; int fd; - if (pMemoryMapInfo->flags & VK_MEMORY_MAP_PLACED_BIT_EXT) + if (pMemoryMapInfo->flags & VK_MEMORY_MAP_PLACED_BIT_EXT) { placed_info = vk_find_struct_const(pMemoryMapInfo->pNext, MEMORY_MAP_PLACED_INFO_EXT); + if (debug) { + WLOGD("Using VK_MEMORY_MAP_PLACED_BIT_EXT:") + LOG_STRUCT(VkMemoryMapPlacedInfoEXT, placed_info); + } + } mem = wrapper_device_memory_from_handle(device, pMemoryMapInfo->memory); - if (!placed_info || !mem) + if (!placed_info || !mem) { + if (debug) WLOGD("Not emulating MapMemory2KHR"); return CHECK(MapMemory(_device, pMemoryMapInfo->memory, pMemoryMapInfo->offset, pMemoryMapInfo->size, 0, ppData)); + } if (mem->map_address) { + if (debug) WLOGD("mem %p has already been mapped to %p", pMemoryMapInfo->memory, mem->map_address); if (placed_info->pPlacedAddress != mem->map_address) { + WLOGE("mem %p has already been mapped to %p, but is requested to be remapped to %p, an invalid operation", mem, mem->map_address, placed_info->pPlacedAddress); return VK_ERROR_MEMORY_MAP_FAILED; } else { *ppData = (char *)mem->map_address + pMemoryMapInfo->offset; + if (debug) WLOGD("mem %p successfully mapped to %p", pMemoryMapInfo->memory, *ppData); return VK_SUCCESS; } } assert(mem->dmabuf_fd >= 0 || mem->ahardware_buffer != NULL); + if (debug) WLOGD("Creating a memory map for mem %p (ahb=%p)", pMemoryMapInfo->memory, mem->ahardware_buffer); + if (mem->ahardware_buffer) { const native_handle_t *handle; const int *handle_fds; @@ -429,12 +461,15 @@ WRAPPER_MapMemory2KHR(VkDevice _device, fd = mem->dmabuf_fd; } + if (debug) WLOGD("mem %p associated with fd %d", pMemoryMapInfo->memory, fd); + if (pMemoryMapInfo->size == VK_WHOLE_SIZE) mem->map_size = mem->alloc_size > 0 ? mem->alloc_size : lseek(fd, 0, SEEK_END); else mem->map_size = pMemoryMapInfo->size; + if (debug) WLOGD("Mmapping mem %p with fd %d to %p", pMemoryMapInfo->memory, fd, placed_info->pPlacedAddress); mem->map_address = mmap(placed_info->pPlacedAddress, mem->map_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); @@ -442,12 +477,14 @@ WRAPPER_MapMemory2KHR(VkDevice _device, if (mem->map_address == MAP_FAILED) { mem->map_address = NULL; mem->map_size = 0; - fprintf(stderr, "%s: mmap failed\n", __func__); + WLOGE("mmap failed emulating MapMemory2KHR"); return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED); } *ppData = (char *)mem->map_address + pMemoryMapInfo->offset; + if (debug) WLOGD("mem %p successfully mapped to %p", pMemoryMapInfo->memory, *ppData); + return VK_SUCCESS; } @@ -460,19 +497,21 @@ WRAPPER_UnmapMemory2KHR(VkDevice _device, { VK_FROM_HANDLE(wrapper_device, device, _device); struct wrapper_device_memory *mem; + bool debug = should_log_memory_debug(); mem = wrapper_device_memory_from_handle(device, pMemoryUnmapInfo->memory); if (!mem) { - device->dispatch_table.UnmapMemory(device->dispatch_handle, - pMemoryUnmapInfo->memory); + if (debug) WLOGD("Unmapping mem %p without emulation", pMemoryUnmapInfo->memory); + CHECKV(UnmapMemory(_device, pMemoryUnmapInfo->memory)); return VK_SUCCESS; } + if (debug) WLOGD("Unmapping mem %p (mapped at %p)", pMemoryUnmapInfo->memory, mem->map_address); if (pMemoryUnmapInfo->flags & VK_MEMORY_UNMAP_RESERVE_BIT_EXT) { mem->map_address = mmap(mem->map_address, mem->map_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); if (mem->map_address == MAP_FAILED) { - fprintf(stderr, "Failed to replace mapping with reserved memory"); + WLOGE("Failed to replace mapping with reserved memory"); return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED); } } else { From 068afd77a83edd099db881c5b659346e7083d2a2 Mon Sep 17 00:00:00 2001 From: leegao Date: Tue, 12 Aug 2025 12:53:13 +1000 Subject: [PATCH 3/3] Fix bug in MapMemory2KHR where lseek on a non-memory fd can return errno ESPIPE --- src/vulkan/wrapper/wrapper_device_memory.c | 30 +++++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/vulkan/wrapper/wrapper_device_memory.c b/src/vulkan/wrapper/wrapper_device_memory.c index 575fe1ef3f0..7a4026d4bb8 100644 --- a/src/vulkan/wrapper/wrapper_device_memory.c +++ b/src/vulkan/wrapper/wrapper_device_memory.c @@ -441,6 +441,7 @@ WRAPPER_MapMemory2KHR(VkDevice _device, if (debug) WLOGD("Creating a memory map for mem %p (ahb=%p)", pMemoryMapInfo->memory, mem->ahardware_buffer); + int ahb_size = -1; if (mem->ahardware_buffer) { const native_handle_t *handle; const int *handle_fds; @@ -450,12 +451,22 @@ WRAPPER_MapMemory2KHR(VkDevice _device, int idx; for (idx = 0; idx < handle->numFds; idx++) { - size_t size = lseek(handle_fds[idx], 0, SEEK_END); + off_t size = lseek(handle_fds[idx], 0, SEEK_END); + if (size < 0) { + int error = errno; + WLOG("lseek(0, SEEK_END) failed on the AHB fd (idx=%d, fd=%d), errno = %d, trying another fd", idx, handle_fds[idx], error); + continue; + } if (size >= mem->alloc_size) { + if (debug) WLOGD("Found size from lseek(idx=%d, fd=%d) = %x (vs alloc_size of %x)", idx, handle_fds[idx], size, mem->alloc_size); + ahb_size = size; break; } } - assert(idx < handle->numFds); + if (idx >= handle->numFds) { + WLOGE("Failed to find an appropriate AHB fd >= alloc_size of 0x%x", mem->alloc_size); + return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED); + } fd = handle_fds[idx]; } else { fd = mem->dmabuf_fd; @@ -463,13 +474,18 @@ WRAPPER_MapMemory2KHR(VkDevice _device, if (debug) WLOGD("mem %p associated with fd %d", pMemoryMapInfo->memory, fd); - if (pMemoryMapInfo->size == VK_WHOLE_SIZE) - mem->map_size = mem->alloc_size > 0 ? + if (pMemoryMapInfo->size == VK_WHOLE_SIZE) { + int result = mem->alloc_size > 0 ? mem->alloc_size : lseek(fd, 0, SEEK_END); - else + if (result < 0) { + WLOGE("Failed to lseek(fd=%d, 0, SEEK_END), previous ahb_size = %x, errno = %d", fd, ahb_size, errno); + } + mem->map_size = result; + } else { mem->map_size = pMemoryMapInfo->size; + } - if (debug) WLOGD("Mmapping mem %p with fd %d to %p", pMemoryMapInfo->memory, fd, placed_info->pPlacedAddress); + if (debug) WLOGD("Mmapping mem %p with fd %d to %p with size %x", pMemoryMapInfo->memory, fd, placed_info->pPlacedAddress, mem->map_size); mem->map_address = mmap(placed_info->pPlacedAddress, mem->map_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); @@ -477,7 +493,7 @@ WRAPPER_MapMemory2KHR(VkDevice _device, if (mem->map_address == MAP_FAILED) { mem->map_address = NULL; mem->map_size = 0; - WLOGE("mmap failed emulating MapMemory2KHR"); + WLOGE("mmap failed emulating MapMemory2KHR: errno = %d", errno); return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED); }