stride3d/stride · error · ArgumentException

size needs to be a multiple of constant buffer alignment

Error message

size needs to be a multiple of constant buffer alignment ({constantBufferAlignment})

What it means

BufferPool's internal constructor validates that the pool size is a multiple of the device's ConstantBufferDataPlacementAlignment, because buffers are carved into constant-buffer allocations at that alignment. A size that isn't a multiple would desynchronize the allocation offsets. Note the parameter is internal, so users usually hit this indirectly.

Solutions

  1. Round the requested size up to the next multiple of graphicsDevice.ConstantBufferDataPlacementAlignment.
  2. Compute sizes from the alignment instead of hardcoding them.
  3. If you hit this via Stride internals, update Stride — historical versions had such issues in profiler/recorder code paths.

Example fix

// before
var poolSize = 4100;
new BufferPool(allocator, device, poolSize); // throws
// after
var align = device.ConstantBufferDataPlacementAlignment;
var poolSize = (4100 + align - 1) / align * align;
Defensive patterns

Strategy: validation

Validate before calling

int align = device.ConstantBufferDataPlacementAlignment;
size = (size + align - 1) / align * align; // round up before constructing

Type guard

bool IsAlignedSize(int size, int alignment) => size % alignment == 0;

Try / catch

try { pool = new BufferPool(allocator, device, size); }
catch (ArgumentException ex) when (ex.Message.Contains("multiple of constant buffer alignment"))
{
    var a = device.ConstantBufferDataPlacementAlignment;
    pool = new BufferPool(allocator, device, (size + a - 1) / a * a);
}

Prevention

When it happens

Trigger: Constructing (internally) a BufferPool with a size not divisible by graphicsDevice.ConstantBufferDataPlacementAlignment (commonly 16 or 256 bytes); platform changes (e.g. different GPU/vendor alignment) invalidating a hardcoded size.

Common situations: Code that hardcodes a pool size like 4096 on a device whose alignment is 256 is fine, but 4100 fails; per-platform alignment differences between desktop and mobile.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Graphics/BufferPool.cs:34

        private const bool UseBufferOffsets = false;
#endif

        private readonly int constantBufferAlignment;
        public int Size;
        public IntPtr Data;

        private readonly GraphicsResourceAllocator allocator;
        private Buffer constantBuffer;
        private MappedResource mappedConstantBuffer;
        private CommandList commandList;

        private int bufferAllocationOffset;

        internal BufferPool(GraphicsResourceAllocator allocator, GraphicsDevice graphicsDevice, int size)
        {
            constantBufferAlignment = graphicsDevice.ConstantBufferDataPlacementAlignment;
            if (size % constantBufferAlignment != 0)
                throw new ArgumentException($"size needs to be a multiple of constant buffer alignment ({constantBufferAlignment})", nameof(size));

            this.allocator = allocator;

            Size = size;

#pragma warning disable 162 // Unreachable code detected
            if (!UseBufferOffsets)
                Data = Marshal.AllocHGlobal(size);
#pragma warning disable 162 // Unreachable code detected

            Reset();
        }

        public static BufferPool New(GraphicsResourceAllocator allocator, GraphicsDevice graphicsDevice, int size)
        {
            return new BufferPool(allocator, graphicsDevice, size);
        }

View on GitHub (pinned to 96fad776d2)