stride3d/stride · error · ArgumentException

A region can only be specified for Textures with…

Error message

A region can only be specified for Textures with GraphicsResourceUsage.Default

What it means

Texture.SetData allows partial updates via a ResourceRegion only when the texture usage is GraphicsResourceUsage.Default (GPU-side updatable). For other usages (e.g. Immutable, which is uploaded via staging copies), specifying a region is invalid and ArgumentException is thrown with 'region' as the parameter name.

Solutions

  1. Recreate the texture with GraphicsResourceUsage.Default if you need region updates.
  2. Drop the region argument and upload the full mip level for non-Default usages.
  3. Use a Dynamic/Staging texture with appropriate copy commands for streaming updates.

Example fix

// before
var tex = Texture.New2D(device, w, h, fmt, TextureFlags.ShaderResource, usage: GraphicsResourceUsage.Immutable);
tex.SetData(commandList, data, region: new ResourceRegion(0, 0, 0, 16, 16, 1)); // throws
// after
var tex = Texture.New2D(device, w, h, fmt, TextureFlags.ShaderResource, usage: GraphicsResourceUsage.Default);
tex.SetData(commandList, data, region: new ResourceRegion(0, 0, 0, 16, 16, 1));
Defensive patterns

Strategy: validation

Validate before calling

if (region.HasValue && texture.Usage != GraphicsResourceUsage.Default)
    throw new InvalidOperationException("Region updates require GraphicsResourceUsage.Default");

Type guard

static bool SupportsRegionUpdate(Texture t) => t.Usage == GraphicsResourceUsage.Default;

Try / catch

try { tex.SetData(commandList, data, region: r); }
catch (ArgumentException ex)
{
    logger.LogError(ex, "Region update on usage {Usage}", tex.Usage);
    tex.SetData(commandList, data); // full-mip fallback
}

Prevention

When it happens

Trigger: Calling texture.SetData(commandList, data, region: someRegion) on a texture created with GraphicsResourceUsage.Immutable or Dynamic; partial sub-rectangle updates on upload-only textures.

Common situations: Updating a sub-rectangle of a texture that was created immutable; porting dynamic-atlas code without changing texture usage; copy-pasted SetData calls that pass a non-null region.

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


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

Appendix: source

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

        ///   This can also occur when the stride is different from the optimal stride, and <typeparamref name="TData"/> is not the same largestSize as
        ///   the largestSize of <see cref="Format"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="region"/> can only be specified (non-<see langword="null"/>) for Textures with <see cref="GraphicsResourceUsage.Default"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   The <paramref name="region"/> largestSize (in any of its dimensions) cannot be greater than the mip-level largestSize.
        /// </exception>
        /// <remarks>
        ///   See <see cref="CommandList.MapSubResource"/> and <see cref="CommandList.UpdateSubResource"/> for more information about
        ///   usage and restrictions.
        /// </remarks>
        public unsafe void SetData<TData>(CommandList commandList, ReadOnlySpan<TData> fromData, int arrayIndex = 0, int mipLevel = 0, ResourceRegion? region = null) where TData : unmanaged
        {
            ArgumentNullException.ThrowIfNull(commandList);

            if (region.HasValue && Usage != GraphicsResourceUsage.Default)
                throw new ArgumentException($"A region can only be specified for Textures with {nameof(GraphicsResourceUsage)}.{nameof(GraphicsResourceUsage.Default)}", nameof(region));

            // Get a description for the specified mip-level
            ref readonly var mipmap = ref GetMipMapDescription(mipLevel);

            int width = mipmap.Width;
            int height = mipmap.Height;
            int depth = mipmap.Depth;

            // If we are using a region, then check that parameters are fine
            if (region is ResourceRegion regionToCheck)
            {
                if (regionToCheck.Width > width)
                    throw new ArgumentOutOfRangeException(nameof(region), $"The region's width [{regionToCheck.Width}] cannot be greater than the mip-level's width [{width}]");
                if (regionToCheck.Height > height)
                    throw new ArgumentOutOfRangeException(nameof(region), $"The region's height [{regionToCheck.Height}] cannot be greater than the mip-level's height [{height}]");
                if (regionToCheck.Depth > depth)
                    throw new ArgumentOutOfRangeException(nameof(region), $"The region's depth [{regionToCheck.Depth}] cannot be greater than the mip-level's depth [{depth}]");

View on GitHub (pinned to 96fad776d2)