stride3d/stride · error · ArgumentException
Invalid Texture used as staging Resource. It must have…
Error message
Invalid Texture used as staging Resource. It must have GraphicsResourceUsage.Staging
What it means
Thrown by Texture.GetDataAsImage when the supplied stagingTexture does not have GraphicsResourceUsage.Staging. Reading GPU texture data back to the CPU requires a staging resource that the GPU can copy into and the CPU can map. Any other usage type is rejected with ArgumentException.
Solutions
- Create a staging texture: var staging = Texture.New2D(services, width, height, mipLevel: 1, format, TextureFlags.None, usage: GraphicsResourceUsage.Staging); then copy and read from it.
- Check stagingTexture.Usage == GraphicsResourceUsage.Staging before calling GetDataAsImage.
- If you have an existing texture, commandList.Copy(texture, stagingTexture) into a staging texture first.
Example fix
// before texture.GetDataAsImage(commandList, texture); // source is not staging // after var staging = Texture.New2D(services, texture.Width, texture.Height, 1, texture.Format, TextureFlags.None, usage: GraphicsResourceUsage.Staging); commandList.Copy(texture, staging); var image = texture.GetDataAsImage(commandList, staging);
Defensive patterns
Strategy: validation
Validate before calling
if (stagingTexture == null || stagingTexture.Usage != GraphicsResourceUsage.Staging)
throw new InvalidOperationException("GetDataAsImage requires a GraphicsResourceUsage.Staging texture"); Type guard
bool IsStaging(Texture t) => t is not null && t.Usage == GraphicsResourceUsage.Staging;
Try / catch
try { var img = texture.GetDataAsImage(cmd, staging); }
catch (ArgumentException e) when (e.ParamName == "stagingTexture") { log.Error("Readback texture must be Staging", e); } Prevention
- Always create readback textures with GraphicsResourceUsage.Staging.
- Keep one reusable staging texture per format/size.
- Assert Usage before every GPU readback.
When it happens
Trigger: Calling GetDataAsImage(commandList, stagingTexture) with a texture created with default Usage (e.g. Immutable or the render-target itself) instead of a dedicated staging texture created via Texture.New2D/3D with GraphicsResourceUsage.Staging.
Common situations: Passing the source texture directly instead of creating a staging copy; a helper that used to accept the render target changed API; copy-pasted texture creation missing the usage argument.
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
- A overlaps with another element. Check the element's offset
- A region can only be specified for Textures with…
- adapter
- AlphaLoadMode. not supported for the Stride image format…
- ArgumentNullException (targetProfiles)
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/b58af7e4a14949ec.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/Texture.cs:1729
return GetDataAsImage(commandList, stagingTexture);
}
/// <summary>
/// Gets the contents of the Texture on GPU memory to an <see cref="Image"/> on the CPU.
/// </summary>
/// <param name="commandList">The <see cref="CommandList"/> where to register the command.</param>
/// <param name="stagingTexture">
/// The staging Texture used to temporarily transfer the image from GPU memory to CPU memory.
/// </param>
/// <exception cref="ArgumentException"><paramref name="stagingTexture"/> is not a staging Texture.</exception>
/// <exception cref="ArgumentNullException"><paramref name="stagingTexture"/> is <see langword="null"/>.</exception>
/// <returns>The Image on CPU memory.</returns>
public unsafe Image GetDataAsImage(CommandList commandList, Texture stagingTexture)
{
ArgumentNullException.ThrowIfNull(stagingTexture);
if (stagingTexture.Usage != GraphicsResourceUsage.Staging)
throw new ArgumentException("Invalid Texture used as staging Resource. It must have GraphicsResourceUsage.Staging", nameof(stagingTexture));
var image = Image.New(stagingTexture.Description);
try
{
for (int arrayIndex = 0; arrayIndex < image.Description.ArraySize; arrayIndex++)
{
for (int mipLevel = 0; mipLevel < image.Description.MipLevels; mipLevel++)
{
var pixelBuffer = image.PixelBuffer[arrayIndex, mipLevel];
GetData(commandList, stagingTexture, new Span<byte>((byte*) pixelBuffer.DataPointer, pixelBuffer.BufferStride), arrayIndex, mipLevel);
}
}
}
catch
{
// If there was an exception, free the allocated image to avoid any memory leak
image.Dispose();
throw;View on GitHub (pinned to 96fad776d2)