stride3d/stride · error · ArgumentNullException

argumentsBuffer

Error message

argumentsBuffer

What it means

CommandList.DrawIndexedInstanced on the Vulkan backend validates that the indirect arguments buffer is non-null (ArgumentNullException "argumentsBuffer"), but the method itself is not implemented for Vulkan and immediately throws NotImplementedException after the guard.

Solutions

  1. Avoid DrawIndexedInstanced on Vulkan; use Draw/DrawIndexed with CPU-side instancing arguments.
  2. Implement the indirect draw by extending CommandList.Vulkan.cs with vkCmdDrawIndexedIndirect via the NativeCommandBuffer.
  3. Branch on the active GraphicsPlatform and use a supported indirect-draw path for Vulkan.
  4. Null-check the argumentsBuffer anyway (also throws ArgumentNullException before the NotImplementedException).

Example fix

// before
commandList.DrawIndexedInstanced(indirectArgsBuffer);

// after
if (graphicsDevice.Platform == GraphicsPlatform.Vulkan)
{
    commandList.DrawIndexed(indexCount, instanceCount);
}
else
{
    commandList.DrawIndexedInstanced(indirectArgsBuffer);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (argumentsBuffer == null) throw new InvalidOperationException("Indirect arguments buffer must be created before DrawIndexedInstanced");
if (graphicsDevice.Platform == GraphicsPlatform.Vulkan) throw new NotSupportedException("DrawIndexedInstanced is not implemented on Vulkan");

Type guard

bool CanIndirectDraw(GraphicsDevice device) => device.Platform != GraphicsPlatform.Vulkan && device.Platform != GraphicsPlatform.OpenGL;

Try / catch

try { commandList.DrawIndexedInstanced(argsBuffer); }
catch (NotImplementedException) { log.Warn("Indirect draw unsupported on this backend; falling back to CPU instancing"); }
catch (ArgumentNullException ex) { log.Error("Arguments buffer missing", ex); }

Prevention

When it happens

Trigger: Calling CommandList.DrawIndexedInstanced on Stride's Vulkan backend (Linux/Android or Vulkan forced on Windows) with any Buffer; even with a valid argumentsBuffer the call throws NotImplementedException.

Common situations: Porting an indirect/instanced draw pipeline from D3D11/D3D12 to Vulkan-backed platforms; code paths shared across graphics platforms hitting an unimplemented Vulkan API surface.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs:700

        public void DrawIndexedInstanced(int indexCountPerInstance, int instanceCount, int startIndexLocation = 0, int baseVertexLocation = 0, int startInstanceLocation = 0)
        {
            PrepareDraw();

            GraphicsDevice.NativeDeviceApi.vkCmdDrawIndexed(currentCommandList.NativeCommandBuffer, (uint) indexCountPerInstance, (uint) instanceCount, (uint) startIndexLocation, baseVertexLocation, (uint) startInstanceLocation);
            //NativeCommandList.DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);

            GraphicsDevice.FrameDrawCalls++;
            GraphicsDevice.FrameTriangleCount += (uint) (indexCountPerInstance * instanceCount);
        }

        /// <summary>
        /// Draw indexed, instanced, GPU-generated primitives.
        /// </summary>
        /// <param name="argumentsBuffer">A buffer containing the GPU generated primitives.</param>
        /// <param name="alignedByteOffsetForArgs">Offset in <em>pBufferForArgs</em> to the start of the GPU generated primitives.</param>
        public void DrawIndexedInstanced(Buffer argumentsBuffer, int alignedByteOffsetForArgs = 0)
        {
            if (argumentsBuffer == null) throw new ArgumentNullException("argumentsBuffer");

            PrepareDraw();

            throw new NotImplementedException();
            //NativeCommandBuffer.DrawIndirect(argumentsBuffer.NativeBuffer, (ulong) alignedByteOffsetForArgs, );
            //NativeDeviceContext.DrawIndexedInstancedIndirect(argumentsBuffer.NativeBuffer, alignedByteOffsetForArgs);

            GraphicsDevice.FrameDrawCalls++;
        }

        /// <summary>
        /// Draw non-indexed, instanced primitives.
        /// </summary>
        /// <param name="vertexCountPerInstance">Number of vertices to draw.</param>
        /// <param name="instanceCount">Number of instances to draw.</param>
        /// <param name="startVertexLocation">Index of the first vertex.</param>
        /// <param name="startInstanceLocation">A value added to each index before reading per-instance data from a vertex buffer.</param>
        public void DrawInstanced(int vertexCountPerInstance, int instanceCount, int startVertexLocation = 0, int startInstanceLocation = 0)

View on GitHub (pinned to 96fad776d2)