proxy: let the device decide whether a device entry point exists
Two users hit the same crash under gamescope with 64-bit games while X11 was fine: Cyber on an Adreno 840 phone (Control, BioShock 2 Remastered, Cult of the Lamb; Turnip Gen8 V38, Proton 9/10) and Yurim on an Adreno 750 phone (Hollow Knight Silksong; Turnip 26.2.0 R4, Proton 11). Proton 11 logs it as err:vulkan:vkMapMemory Exception 0xc0000005 in Unix call.; Proton 9 asserts !status && "vkMapMemory" in loader_thunks.c and msvcrt's dialog stays hidden behind the splash, so the game looks stuck on "Launching Game".
What happens: gn_real_device_proc resolved a guest's device entry points through dlsym on the system libvulkan.so and the loader's instance resolver before ever asking the device, and the one-hop alias turned vkMapMemory2KHR into vkMapMemory2. Android 16's libvulkan exports the 1.4 core names (# introduced=36 in AOSP's libvulkan.map.txt; Android 15 does not), so the alias handed Wine the loader trampoline, which calls dispatch.MapMemory2 with no NULL check. That slot is a non-required INIT_PROC and stays empty on a device created at 1.3, which is what DXVK does. 64-bit winevulkan calls p_vkMapMemory2KHR whenever it is non-NULL (win32u/vulkan.c:1341), so the first map jumped to PC 0. wow64 guests enable VK_KHR_map_memory2, so the slot is filled there, and the X11 route goes through libvulkan_wrapper, which folds MapMemory2KHR into the v1 map. The Odin 3 (Android 15) could not reproduce it for that reason.
The fix:
- lands 72d58f4 from #7 (it was pushed after the merge and never reached master): with a device at hand its own
vkGetDeviceProcAddris final; - moves that check in front of dlsym and makes it an existence gate: NULL from the device means miss, for the alias name too. dlsym still picks the implementation when the device says the name exists, so the hooks keep the loader's copy.
Verified on the Odin 3 (Android 15, Turnip Gen8 V37, Vampire Survivors, DXVK 2.4.1, Proton 9): renders under gamescope and X11 with the new shim, vkMapMemory2KHR resolves to miss and Wine takes vkMapMemory. The Android 16 crash path cannot be exercised on any device here; the payload with this shim is 20261023.2 (app PR follows) and needs a boot from Cyber or Yurim to confirm.