stride3d/stride · error · InvalidOperationException
AHardwareBuffer import requires…
Error message
AHardwareBuffer import requires VK_ANDROID_external_memory_android_hardware_buffer.
What it means
Texture.NewFromAndroidHardwareBuffer imports an Android AHardwareBuffer as a Vulkan texture. This requires the Vulkan driver to expose the VK_ANDROID_external_memory_android_hardware_buffer extension (device.HasAndroidHardwareBufferSupport). If the physical device lacks that extension, Stride throws InvalidOperationException rather than attempting an import the driver cannot perform.
Solutions
- Check device.HasAndroidHardwareBufferSupport before calling NewFromAndroidHardwareBuffer and use a fallback (copy the buffer via CPU or a different sharing path) when it is false.
- Recreate the GraphicsDevice enabling the extension chain: VK_ANDROID_external_memory_android_hardware_buffer plus its dependencies (VK_KHR_external_memory, VK_KHR_sampler_ycbcr_conversion) in device creation.
- Run on physical hardware/Android 8.0+ (API 26) with a driver that supports AHardwareBuffer import instead of an emulator or outdated ICD.
- Update the GPU driver/OEM Vulkan ICD, which may add the extension.
Example fix
// before
displayTexture = Texture.NewFromAndroidHardwareBuffer(device, surfaceView.HardwareBuffer);
// after
if (device.HasAndroidHardwareBufferSupport)
displayTexture = Texture.NewFromAndroidHardwareBuffer(device, surfaceView.HardwareBuffer);
else
displayTexture = CopyHardwareBufferToTexture(device, surfaceView.HardwareBuffer); Defensive patterns
Strategy: validation
Validate before calling
if (device == null || hardwareBuffer == IntPtr.Zero) throw new ArgumentException("Invalid device or hardware buffer.");
if (!device.HasAndroidHardwareBufferSupport)
throw new NotSupportedException("VK_ANDROID_external_memory_android_hardware_buffer unavailable; use fallback upload."); Type guard
bool CanImportAHardwareBuffer(GraphicsDevice device) => device != null && device.HasAndroidHardwareBufferSupport;
Try / catch
try
{
texture = Texture.NewFromAndroidHardwareBuffer(device, hardwareBuffer);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("VK_ANDROID_external_memory_android_hardware_buffer"))
{
texture = UploadFallbackTexture(device, hardwareBuffer);
} Prevention
- Gate all AHardwareBuffer imports behind device.HasAndroidHardwareBufferSupport.
- Request the full extension chain (VK_ANDROID_external_memory_android_hardware_buffer + dependencies) at device creation.
- Test on both physical devices and emulators early; emulator Vulkan often lacks this extension.
- Keep a CPU upload fallback path implemented and tested for unsupported devices.
When it happens
Trigger: Calling Texture.NewFromAndroidHardwareBuffer(device, buffer) on a GraphicsDevice whose Vulkan physical device does not report VK_ANDROID_external_memory_android_hardware_buffer; also when the extension is available but not enabled at device creation because the required instance/device extension chain was not requested.
Common situations: Running on an Android emulator or older/low-end GPU whose Vulkan ICD omits the extension; on devices below Android API 26 where AHardwareBuffer APIs are missing; enabling Vulkan on Android without enabling the extension chain (VK_KHR_external_memory, AndroidSamplerYcbcrConversion dependencies) during device creation.
Related errors
- Vulkan: no memory type satisfies the AHardwareBuffer…
- Required extension is not available
- IOSurface import requires VK_EXT_metal_objects.
- Unable to read
- Unable to read
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/44ddc471c51c8c08.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/Vulkan/Texture.Android.Vulkan.cs:60
{
GraphicsDevice.Collect(NativeSamplerYcbcrConversion);
NativeSamplerYcbcrConversion = VkSamplerYcbcrConversion.Null;
}
if (androidHardwareBuffer != IntPtr.Zero)
{
AHardwareBuffer_release(androidHardwareBuffer);
androidHardwareBuffer = IntPtr.Zero;
}
}
/// <summary>Imports an <c>AHardwareBuffer</c> as a Vulkan-backed sampleable Texture.
/// Acquires a reference released when the Texture is destroyed.</summary>
public static unsafe Texture NewFromAndroidHardwareBuffer(GraphicsDevice device, IntPtr hardwareBuffer)
{
if (device == null) throw new ArgumentNullException(nameof(device));
if (hardwareBuffer == IntPtr.Zero) throw new ArgumentNullException(nameof(hardwareBuffer));
if (!device.HasAndroidHardwareBufferSupport)
throw new InvalidOperationException("AHardwareBuffer import requires VK_ANDROID_external_memory_android_hardware_buffer.");
AHardwareBuffer_acquire(hardwareBuffer);
AHardwareBufferDesc desc;
AHardwareBuffer_describe(hardwareBuffer, out desc);
var formatInfo = new VkAndroidHardwareBufferFormatPropertiesANDROID
{
sType = VkStructureType.AndroidHardwareBufferFormatPropertiesAndroid,
};
var props = new VkAndroidHardwareBufferPropertiesANDROID
{
sType = VkStructureType.AndroidHardwareBufferPropertiesAndroid,
pNext = &formatInfo,
};
device.CheckResult(device.NativeDeviceApi.vkGetAndroidHardwareBufferPropertiesANDROID(device.NativeDevice, hardwareBuffer, &props));
// Non-zero externalFormat = buffer needs sampler-YCbCr conversion to read as RGB.View on GitHub (pinned to 96fad776d2)