stride3d/stride · error · ArgumentException

sizeof(TData) / sizeof(Format) * Width is not an integer

Error message

sizeof(TData) / sizeof(Format) * Width is not an integer

What it means

CalculateWidth derives how many TData elements span the texture width based on row stride (mipWidth * Format.SizeInBytes) versus the size of the caller's element type. If rowStride * mipWidth is not evenly divisible by sizeof(TData) — i.e. sizeof(TData)/sizeof(Format)*Width is not an integer — ArgumentException is thrown.

Solutions

  1. Choose a TData whose size in bytes evenly divides the row stride — typically Format.SizeInBytes itself or a divisor of it.
  2. Use the format's native pixel struct as TData (e.g. Half4 for R16G16B16A16).
  3. Compute a valid element size: sizeof(TData) must satisfy (mipWidth * Format.SizeInBytes * mipWidth) % sizeof(TData) == 0.

Example fix

// before
texture.CalculateWidth<byte>(mipWidth); // element type mismatched to row stride
// after
texture.CalculateWidth<Half4>(mipWidth); // 8 bytes matches format pixel size
Defensive patterns

Strategy: validation

Validate before calling

int rowStride = width * format.SizeInBytes;
if (rowStride % sizeof(TData) != 0)
    throw new InvalidOperationException($"sizeof(TData)={sizeof(TData)} incompatible with row stride {rowStride}");

Type guard

static bool ElementTypeFitsRow<TData>(PixelFormat fmt, int width) where TData : unmanaged => (width * fmt.SizeInBytes) % sizeof(TData) == 0;

Try / catch

try { w = texture.CalculateWidth<TData>(mipWidth); }
catch (ArgumentException ex)
{
    logger.LogError(ex, "TData size incompatible with format {Fmt}", texture.Format);
    throw;
}

Prevention

When it happens

Trigger: Calling CalculateWidth<TData> with a TData whose byte size is incompatible with the pixel row size, e.g. reading a wide format texture using byte[] or int[] elements such that rowStride * mipWidth is not a multiple of sizeof(TData).

Common situations: Pixel-copy utilities using byte buffers for multi-byte formats; generic CPU-side texture processing code that assumes 4-byte pixels; block-compressed formats with odd byte sizes.

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/1c4660ccaf9451ba. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Graphics/Texture.cs:859

        ///       int widthAsFloats = texture.CalculateWidth&lt;float>(); // 100 floats
        ///     </code>
        ///   </para>
        /// </remarks>
        /// <exception cref="ArgumentException">
        ///   The largestSize of <see cref="Format"/> and the largestSize of <typeparamref name="TData"/> does not match.
        ///   The ratio between the two must be an integer, or else there would be remaining bytes.
        /// </exception>
        public unsafe int CalculateWidth<TData>(int mipLevel = 0) where TData : unmanaged
        {
            var mipWidth = CalculateMipSize(Width, mipLevel);

            var rowStride = mipWidth * Format.SizeInBytes;
            var dataStrideInBytes = mipWidth * sizeof(TData);

            var (width, rem) = Math.DivRem(rowStride * mipWidth, dataStrideInBytes);

            if (rem != 0)
                throw new ArgumentException("sizeof(TData) / sizeof(Format) * Width is not an integer");

            return width;
        }

        /// <summary>
        ///   Calculates the number of pixel elements of type <typeparamref name="TData"/> the Texture requires
        ///   for a particular mip-level.
        /// </summary>
        /// <typeparam name="TData">The type of the pixel data.</typeparam>
        /// <param name="mipLevel">
        ///   The mip-level for which to calculate the width.
        ///   By default, the first mip-level at index 0 is selected, which is the most detailed one.
        /// </param>
        /// <returns>
        ///   The expected number of <typeparamref name="TData"/> elements of the Texture for the mip-level specified by <paramref name="mipLevel"/>.
        /// </returns>
        /// <remarks>
        ///   This method can be used to allocate a Texture data buffer to hold pixel data of type <typeparamref name="TData"/> as follows:

View on GitHub (pinned to 96fad776d2)