stride3d/stride · critical · InvalidOperationException
No graphics+compute queue family
Error message
No graphics+compute queue family
What it means
Thrown by CreateDevice during Vulkan physical-device setup when no queue family supports both graphics and compute operations. The renderer requires a single queue family capable of both (it probes vkGetPhysicalDeviceQueueFamilyProperties for combined GRAPHICS|COMPUTE flag bits) and refuses to create a logical device without one. This keeps the pipeline simple by avoiding separate graphics and compute queues.
Solutions
- Select a different physicalDevice that exposes a graphics+compute queue family (iterate vkEnumeratePhysicalDevices and probe each one's queue families before creating the device).
- If separate families must be used, extend the probe to allow graphics-only and compute-only families and create two queues instead of one combined queue.
- Verify with vkinfo/vulkaninfo that the intended device actually has a queue family with both GRAPHICS and COMPUTE caps; update drivers if a capable device exists but reports none.
Example fix
// before
var physicalDevice = physicalDevices.First();
CreateDevice(physicalDevice);
// after
var physicalDevice = physicalDevices.FirstOrDefault(CapableOfGraphicsCompute)
?? throw new InvalidOperationException("No device with graphics+compute queue family");
CreateDevice(physicalDevice);
static bool CapableOfGraphicsCompute(PhysicalDevice d) { /* probe queue families */ } Defensive patterns
Strategy: validation
Validate before calling
uint FindGraphicsComputeFamily(PhysicalDevice physical, GetQueueFamilyPropertiesFn getProps)
{
getProps(physical, out uint count, null);
var fams = new VkQueueFamilyProperties[count];
getProps(physical, out _, fams);
for (uint i = 0; i < count; i++)
if ((fams[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 && (fams[i].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)
return i;
return uint.MaxValue; // check before CreateDevice and pick another physical device
} Prevention
- Probe every physical device's queue families during device selection, not just the first one.
- Run vulkaninfo in CI to assert test machines expose a graphics+compute-capable device.
- Prefer devices known to support compute (discrete GPUs, modern iGPUs) for the test harness.
When it happens
Trigger: Calling EnsureSharedContext/CreateDevice on a device whose vkGetPhysicalDeviceQueueFamilyProperties returns no family with both VK_QUEUE_GRAPHICS_BIT and VK_QUEUE_COMPUTE_BIT set, so the loop ends with queueFamily still == uint.MaxValue.
Common situations: Running on a compute-only device (e.g. a headless NVIDIA compute GPU, Intel Xe compute-only iGPU) or a minimal display-only device; picking the wrong physicalDevice among multiple devices in a multi-GPU system; running in an emulator or software rasterizer (llvmpipe variants) that exposes no compute support.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- No Vulkan 1.2+ physical device
- No Vulkan physical device
- AHardwareBuffer import requires…
- argumentsBuffer
- Bound render targets
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/4762637449ffc25b.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Tests/FrameRenderer.Vulkan.cs:199
private static void CreateDevice()
{
uint familyCount = 0;
instanceApi.vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, null);
var families = new VkQueueFamilyProperties[familyCount];
fixed (VkQueueFamilyProperties* familiesPtr = families)
instanceApi.vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, familiesPtr);
queueFamily = uint.MaxValue;
for (uint i = 0; i < familyCount; i++)
{
if ((families[i].queueFlags & (VkQueueFlags.Graphics | VkQueueFlags.Compute)) == (VkQueueFlags.Graphics | VkQueueFlags.Compute))
{
queueFamily = i;
break;
}
}
if (queueFamily == uint.MaxValue)
throw new InvalidOperationException("No graphics+compute queue family");
// The bytecode keeps UserSemantic decorations (SPV_GOOGLE_hlsl_functionality1);
// enable the matching extension where the driver wants it declared.
uint extensionCount = 0;
Check(instanceApi.vkEnumerateDeviceExtensionProperties(physicalDevice, null, &extensionCount, null));
var extensions = new VkExtensionProperties[extensionCount];
fixed (VkExtensionProperties* extensionsPtr = extensions)
Check(instanceApi.vkEnumerateDeviceExtensionProperties(physicalDevice, null, &extensionCount, extensionsPtr));
var availableExtensions = new HashSet<string>();
for (int i = 0; i < extensions.Length; i++)
{
fixed (VkExtensionProperties* extensionPtr = &extensions[i])
availableExtensions.Add(Marshal.PtrToStringUTF8((nint)extensionPtr->extensionName));
}
var enabledExtensions = new List<string>();
foreach (var wanted in new[] { "VK_GOOGLE_hlsl_functionality1", "VK_GOOGLE_user_type" })
{
if (availableExtensions.Contains(wanted))View on GitHub (pinned to 96fad776d2)