Uh oh!
There was an error while loading. Please reload this page.
AHB fix plus placed-memmory - #10
Conversation
The direct AHardwareBuffer path exports exclusive swapchain images without releasing queue-family ownership to VK_QUEUE_FAMILY_FOREIGN_EXT. On drivers with private render-target layouts, an external importer can therefore observe unresolved or compressed contents. Pre-record one release barrier per usable queue family and submit it with present. Use GENERAL as the shared layout and a generic memory-write source dependency because WSI cannot know how the application produced the image. Restrict the change to exclusive, non-blit Android images: legacy VkImageMemoryBarrier does not permit FOREIGN_EXT transfers for concurrent images, and the image-blit path has separate presentation commands.
wrapper_device_memory::alloc_size is used to select the backing AHardwareBuffer fd and to resolve VK_WHOLE_SIZE, but it is left zero-initialized. With a multi-fd AHardwareBuffer this accepts the first seekable metadata fd even when it is smaller than the Vulkan allocation, producing a successful but truncated mapping. Retain the authoritative VkMemoryAllocateInfo::allocationSize when the wrapper creates its placed-memory object. The change remains inside the existing host-visible VK_EXT_map_memory_placed allocation path; imported, exported, non-host-visible, and ordinary driver mappings are unchanged.
utkarshdalal
commented
Aug 30, 2026
Thanks, really solid work, the alloc_size fix is a clear bug fix On the release barrier: it changes the present path for every device on the direct no-blit path, and on Adreno the PRESENT_SRC -> GENERAL transition may force UBWC decompression, which we can't easily verify across our device base. Could you gate the info->finish_create assignment in wsi_configure_android_image on driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY (plumbed through wsi_device)? Spec-wise the barrier is probably right everywhere, but I'd rather widen the allowlist as devices prove they need it than risk a fleet-wide regression. Also please drop the per-image "Recorded AHB ownership release barriers" log to debug level. |
abesmon
commented
Aug 30, 2026
Restrict the default AHB ownership release path to NVIDIA's proprietary driver to avoid changing direct no-blit presentation on unvalidated devices.\n\nAdd WRAPPER_AHB_OWNERSHIP_RELEASE as a tri-state override: unset follows the driver default, true opts other drivers in, and false provides a kill switch. Move the per-image success message to Mesa's debug logger.
@utkarshdalal i've pushed update with logs and ENV vars. now its working this way:
|

TLDR: this one fixes AHB problems (very broken image) plus fixes black screen.
This fix primarely made for nintendo switch running android, but i've tryed to made it as much platform indepedent as i can. This Was heavily tested with dozens of A/B on my switch, but never tested on aby other devices, since i dont have one
Summary
This series fixes two independent omissions encountered when a direct Android
hardware-buffer swapchain is used together with the wrapper's emulated placed
memory maps:
VK_QUEUE_FAMILY_FOREIGN_EXTbefore the Android consumer uses them;VkMemoryAllocateInfo::allocationSizein the wrapper memory objectused by placed mappings.
The commits are kept separate so each invariant and its gating can be reviewed
independently.
1. Release direct AHardwareBuffer images
The Android hardware-buffer specification treats Android producers and
consumers as foreign devices for ownership transfer. Vulkan's queue-family
rules require explicit ownership transfer for external resources; without it,
reads by the second queue family have undefined contents even if memory
dependencies were otherwise expressed.
The first commit pre-records a release command for every usable queue family
and submits the matching command during present. It uses
GENERALas theshared external layout and a generic memory-write source dependency because
WSI cannot know which application pipeline stage produced the image.
The behavioral change is structurally restricted to Android swapchain images
which are all of the following:
WSI_SWAPCHAIN_NO_BLIT);VK_SHARING_MODE_EXCLUSIVE;Concurrent images are excluded because legacy
VkImageMemoryBarrierdoes notpermit the same foreign-family transfer for concurrent sharing, and blit
swapchains keep their existing presentation command path. There is no device,
vendor, application, or Switch-specific check.
Specification references:
VK_ANDROID_external_memory_android_hardware_buffer2. Retain allocation size for placed mappings
wrapper_device_memory::alloc_sizeis already used to select the backing fd ofa multi-fd AHardwareBuffer and to resolve
VK_WHOLE_SIZE, but the emulatedallocation path leaves it zero-initialized. That makes the first seekable
metadata fd look large enough and can produce a successful, truncated mapping.
The second commit stores the authoritative
VkMemoryAllocateInfo::allocationSizewhen that wrapper memory object iscreated. This is a one-line bookkeeping fix. The existing control flow limits
it to the host-visible placed-allocation emulation path with
memoryMapPlaced/VK_EXT_map_memory_placedenabled. Imported, exported,non-host-visible, and ordinary driver mappings keep their previous behavior.
This also matches the extension's model:
VK_WHOLE_SIZEmeans the remainder ofthe Vulkan allocation, and placed-map validity and reservation size are defined
using
VkMemoryAllocateInfo::allocationSize.Specification references:
VkMemoryMapInfosize and placed-map requirementsVK_EXT_map_memory_placedproposal and exampleValidation
Tested on an NVIDIA Tegra X1 Android device with the proprietary Vulkan ICD.
Every visual verdict below was checked on the physical display; exit status and
FPS were not used as corruption oracles.
Controlled A/B for AHardwareBuffer ownership, five runs per cell:
Controlled production A/B for placed mapping, DX9 32-bit, five runs per arm:
Final two-commit interaction smoke:
no-blit swapchains, and six ownership-release barrier recordings.
For every evidence-producing run, the wrapper SHA in the container imagefs was
matched to the build artifact and a unique
WRAPPER_LOG_FILEcanary plus thelauncher's final guest environment confirmed that the intended binary and
configuration executed.