stride3d/stride · error · ArgumentException

Only Buffers and Textures can be mapped

Error message

Only Buffers and Textures can be mapped

What it means

CommandList.Map on Direct3D12 only accepts GraphicsMapMap resource types of Buffer or Texture; anything else throws ArgumentException naming the resource parameter. Mapping is defined solely for these two resource kinds.

Solutions

  1. Pass the Buffer or Texture you intend to map, not a wrapper or other GraphicsResource.
  2. If you hold a more general type, pattern-match to Texture/Buffer before mapping.
  3. Null-check the resource before calling Map.
  4. For other resource kinds, use their dedicated CPU access APIs instead of Map.

Example fix

// before
commandList.Map(renderTargetWrapper, MapMode.Read, 0);
// after
if (wrapper.Texture is Texture tex)
    MappedResource m = commandList.Map(tex, MapMode.Read, 0);
Defensive patterns

Strategy: type-guard

Validate before calling

if (resource is not Buffer && resource is not Texture)
    throw new ArgumentException("Map requires a Buffer or Texture", nameof(resource));

Type guard

static bool IsMappable(GraphicsResource r) => r is Buffer or Texture;

Try / catch

try { var mapped = commandList.Map(resource, MapMode.Read, 0); }
catch (ArgumentException ex) { log.Error("Map: only Buffer/Texture supported", ex); }

Prevention

When it happens

Trigger: Calling CommandList.Map(resource, mapMode, subIndex, offset, length) with a resource that is neither Buffer nor Texture (e.g. wrong variable, custom resource, null).

Common situations: Passing a RenderTarget/other wrapper where the underlying texture was intended; generic helper code that forwards any GraphicsResource to Map; refactors changing resource types.

Understand the failure class

Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Graphics/Direct3D12/CommandList.Direct3D12.cs:2247

                rowPitch = texture.ComputeRowPitch(subResourceIndex % texture.MipLevelCount);
                depthStride = texture.ComputeSlicePitch(subResourceIndex % texture.MipLevelCount);

                if (usage == GraphicsResourceUsage.Staging)
                {
                    // Internally it's a Buffer, so adapt resource index and offset
                    offsetInBytes = texture.ComputeBufferOffset(subResourceIndex, depthSlice: 0);
                    subResourceIndex = 0;
                }
            }
            else if (resource is Buffer buffer)
            {
                usage = buffer.Usage;

                if (lengthInBytes == 0)
                    lengthInBytes = buffer.SizeInBytes;
            }
            else throw new ArgumentException("Only Buffers and Textures can be mapped", nameof(resource));

            if (mapMode is MapMode.Read or MapMode.ReadWrite or MapMode.Write)
            {
                // Is non-staging even possible for Read/Write?
                if (usage != GraphicsResourceUsage.Staging)
                    throw new ArgumentException("Read / Write / ReadWrite is only supported for staging resources", nameof(mapMode));
            }

            // NOTE: This path is quite slow (it creates a new resource).
            //       Once we switch to D3D12 / Vulkan only, we should probably get rid of this use case
            //       by pooling and reusing buffers internally, or explicitly managed at the caller side
            if (mapMode == MapMode.WriteDiscard)
            {
                // Mark old resource for deletion once Command List are executed
                resource.OnDestroyed();

                // Create new resource
                resource.OnRecreate();

View on GitHub (pinned to 96fad776d2)