stride3d/stride · critical · NotSupportedException
Required Vulkan extension
Error message
Required Vulkan extension {extensionName} is not supported by the current physical device. What it means
Before creating a Vulkan logical device, Stride validates that the chosen physical device exposes the VK_KHR_swapchain extension, which is mandatory for presenting rendered images to a window surface. ValidateExtensionPropertiesAvailability throws NotSupportedException if the device's enumerated extension list does not contain it, since no swapchain can exist without it.
Solutions
- Verify with vulkaninfo that the selected physical device lists VK_KHR_swapchain under device extensions.
- Install/repair full vendor GPU drivers rather than a headless or compute-only ICD.
- Run in headless/offscreen mode without a swapchain if presentation is not needed.
- Select a different, presentation-capable physical device in the adapter list.
Defensive patterns
Strategy: validation
Validate before calling
bool hasSwapchain = physicalDevice.EnumerateDeviceExtensionProperties()
.Any(e => e.ExtensionName == "VK_KHR_swapchain");
if (!hasSwapchain) throw new NotSupportedException("Device lacks VK_KHR_swapchain"); Type guard
bool SupportsSwapchain(PhysicalDevice d) => d.EnumerateDeviceExtensionProperties().Any(e => e.ExtensionName == "VK_KHR_swapchain");
Try / catch
try { device = GraphicsDevice.New(adapter, desc); }
catch (NotSupportedException ex) when (ex.Message.Contains("VK_KHR_swapchain")) { log.Error("Presentation unsupported on this device", ex); throw; } Prevention
- Run vulkaninfo and check device extensions before deployment
- Avoid headless/compute-only ICDs for windowed rendering
- Select presentation-capable adapters explicitly rather than defaulting to index 0
- Install complete vendor drivers, not compute-only variants
When it happens
Trigger: GraphicsDevice creation with a swapchain (windowed mode) on a physical device that fails to enumerate VK_KHR_swapchain in its device extension properties.
Common situations: Headless Vulkan ICDs or compute-only devices (some server GPUs, lavapipe variants) that lack presentation support; misconfigured Vulkan runtime/loader; a device selected without swapchain capability (e.g. picking device index 0 which is a compute accelerator).
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Vulkan: Failed to find GPUs with Vulkan support
- Failed to create vulkan instance
- Required extension is not available
- Vulkan: Dynamic rendering and synchronization2 are not…
- Could not acquire swapchain image
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/73858410de60d2c1.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/Vulkan/GraphicsDevice.Vulkan.cs:672
{
var properties = extensionProperties[index];
var name = new VkUtf8String(properties.extensionName);
var indexOfExtensionName = supportedExtensionProperties.IndexOf(name);
if (indexOfExtensionName >= 0)
availableExtensionProperties.Add(supportedExtensionProperties[indexOfExtensionName]);
}
return availableExtensionProperties;
}
private static void ValidateExtensionPropertiesAvailability(HashSet<VkUtf8String> availableExtensionProperties)
{
if (!availableExtensionProperties.Contains(VK_KHR_SWAPCHAIN_EXTENSION_NAME))
{
string extensionName = Encoding.UTF8.GetString(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
throw new NotSupportedException($"Required Vulkan extension {extensionName} is not supported by the current physical device.");
}
}
internal unsafe IntPtr AllocateUploadBuffer(int size, out VkBuffer resource, out int offset)
{
lock (nativeUploadBufferLock)
{
if (nativeUploadBuffer == VkBuffer.Null || nativeUploadBufferOffset + size > nativeUploadBufferSize)
{
if (nativeUploadBuffer != VkBuffer.Null)
{
NativeDeviceApi.vkUnmapMemory(NativeDevice, nativeUploadBufferMemory);
Collect(nativeUploadBuffer);
Collect(nativeUploadBufferMemory);
}
// Allocate new buffer
// TODO D3D12 recycle old ones (using fences to know when GPU is done with them)View on GitHub (pinned to 96fad776d2)