stride3d/stride · error · InvalidOperationException

Creation of additional Command Lists is not supported for…

Error message

Creation of additional Command Lists is not supported for Direct3D 11

What it means

D3D11 only supports a single immediate-command-list model per device context, unlike D3D12/Vulkan which support multiple deferred command lists. CommandList.New(GraphicsDevice) exists to satisfy the cross-backend API surface, but on Direct3D 11 it always throws InvalidOperationException instead of creating an extra CommandList.

Solutions

  1. Reuse the existing CommandList (e.g. GraphicsDevice's immediate command list) instead of creating new ones.
  2. Upgrade the graphics backend to Direct3D 12 if multiple command lists/parallel recording is required.
  3. Restructure work to be single-threaded command recording on D3D11, or use per-thread rendering with separate GraphicsDevice instances (heavyweight).

Example fix

// before
var cmdList = CommandList.New(graphicsDevice);
cmdList.Begin(graphicsDevice);
// after
var cmdList = graphicsDevice.Commands.CommandList; // reuse the immediate command list on D3D11
Defensive patterns

Strategy: try-catch

Validate before calling

if (device.Backend == GraphicsBackend.Direct3D11 && needExtraCommandList)
    throw new NotSupportedException("D3D11 supports only the immediate command list");

Type guard

bool SupportsAdditionalCommandLists(GraphicsDevice d) => d.Backend is not GraphicsBackend.Direct3D11;

Try / catch

try { cmdList = CommandList.New(device); }
catch (InvalidOperationException)
{ cmdList = device.Commands.CommandList; /* reuse immediate command list */ }

Prevention

When it happens

Trigger: Calling the static CommandList.New(device) on a GraphicsDevice whose backend is Direct3D 11 — typically in backend-agnostic code that creates additional command lists for multithreaded or deferred rendering.

Common situations: Porting D3D12/Vulkan-era Stride code (or generic sample code) to a D3D11 project; attempting parallel command recording with a second CommandList; factory-style command list creation shared across graphics backends.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/aecd3d50ec4a6691. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Graphics/Direct3D11/CommandList.Direct3D11.cs:69

        /// <summary>
        ///   Gets the internal Direct3D 11 Device Context.
        /// </summary>
        /// <remarks>
        ///   If the reference is going to be kept, use <c>AddRef()</c> on the COM pointer to increment the internal
        ///   reference count, and <see cref="ComPtr{T}.Dispose()"/> when no longer needed to release the object.
        /// </remarks>
        internal ComPtr<ID3D11DeviceContext> NativeDeviceContext => ToComPtr(nativeDeviceContext);


        /// <summary>
        ///   Creates a new <see cref="CommandList"/>.
        /// </summary>
        /// <param name="device">The Graphics Device.</param>
        /// <returns>The new instance of <see cref="CommandList"/>.</returns>
        /// <exception cref="InvalidOperationException">Creation of additional Command Lists is not supported for Direct3D 11.</exception>
        public static CommandList New(GraphicsDevice device)
        {
            throw new InvalidOperationException("Creation of additional Command Lists is not supported for Direct3D 11");
        }

        /// <summary>
        ///   Initializes a new instance of the <see cref="CommandList"/> class.
        /// </summary>
        /// <param name="device">The Graphics Device.</param>
        internal CommandList(GraphicsDevice device) : base(device)
        {
            // We just take ownership of the native device context. No need to call AddRef() on it
            nativeDeviceContext = device.NativeDeviceContext.Handle;
            SetNativeDeviceChild(NativeDeviceContext.AsDeviceChild());

            ComPtr<ID3DUserDefinedAnnotation> deviceProfiler = default;
            if (device.IsDebugMode)
            {
                HResult result = nativeDeviceContext->QueryInterface(out deviceProfiler);
                if (result.IsFailure)
                    deviceProfiler = null;

View on GitHub (pinned to 96fad776d2)