{"record":{"id":"fa9b702c4397d56a","repo":"stride3d/stride","slug":"read-write-readwrite-is-only-supported-for-staging-resources","errorCode":null,"errorMessage":"Read / Write / ReadWrite is only supported for staging resources","messagePattern":"Read / Write / ReadWrite is only supported for staging resources","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Graphics/Direct3D12/CommandList.Direct3D12.cs","lineNumber":2253,"sourceCode":"                    // Internally it's a Buffer, so adapt resource index and offset\n                    offsetInBytes = texture.ComputeBufferOffset(subResourceIndex, depthSlice: 0);\n                    subResourceIndex = 0;\n                }\n            }\n            else if (resource is Buffer buffer)\n            {\n                usage = buffer.Usage;\n\n                if (lengthInBytes == 0)\n                    lengthInBytes = buffer.SizeInBytes;\n            }\n            else throw new ArgumentException(\"Only Buffers and Textures can be mapped\", nameof(resource));\n\n            if (mapMode is MapMode.Read or MapMode.ReadWrite or MapMode.Write)\n            {\n                // Is non-staging even possible for Read/Write?\n                if (usage != GraphicsResourceUsage.Staging)\n                    throw new ArgumentException(\"Read / Write / ReadWrite is only supported for staging resources\", nameof(mapMode));\n            }\n\n            // NOTE: This path is quite slow (it creates a new resource).\n            //       Once we switch to D3D12 / Vulkan only, we should probably get rid of this use case\n            //       by pooling and reusing buffers internally, or explicitly managed at the caller side\n            if (mapMode == MapMode.WriteDiscard)\n            {\n                // Mark old resource for deletion once Command List are executed\n                resource.OnDestroyed();\n\n                // Create new resource\n                resource.OnRecreate();\n            }\n            else if (mapMode != MapMode.WriteNoOverwrite)   // Write / Read / ReadWrite\n            {\n                // Need to wait?\n                if (\n                    // used in command list which hasn't be submitted yet? (only valid if our own, checked later)","sourceCodeStart":2235,"sourceCodeEnd":2271,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Graphics/Direct3D12/CommandList.Direct3D12.cs#L2235-L2271","documentation":"MapMode.Read, ReadWrite and Write on Direct3D12 require the resource to have been created with GraphicsResourceUsage.Staging, because they go through CPU-visible memory. Mapping a non-staging (e.g. Immutable/Default) resource with one of those modes throws ArgumentException naming the mapMode parameter.","triggerScenarios":"Calling CommandList.Map with MapMode.Read/ReadWrite/Write on a Buffer or Texture whose Usage != GraphicsResourceUsage.Staging.","commonSituations":"Trying to read back GPU-written data from a default-usage buffer; forgetting to create the texture/buffer with GraphicsResourceUsage.Staging; porting D3D11 code where dynamic usage allowed similar mappings.","solutions":["Create the resource with GraphicsResourceUsage.Staging when you intend to Map it for Read/ReadWrite/Write.","For readback, copy from the GPU resource to a staging resource with Copy first, then Map the staging resource in Read mode.","Use MapMode.WriteDiscard on appropriate buffers instead of Write when rewriting whole contents (that path doesn't require staging).","Check resource.Usage before mapping and branch accordingly."],"exampleFix":"// before\nvar buf = Buffer.New(GraphicsDevice, size);\ncommandList.Map(buf, MapMode.Read, 0); // throws\n// after\nvar staging = Buffer.New(GraphicsDevice, size, BufferFlags.None, GraphicsResourceUsage.Staging);\ncommandList.Copy(buf, staging);\nvar data = commandList.Map(staging, MapMode.Read, 0);","handlingStrategy":"validation","validationCode":"if (mapMode is MapMode.Read or MapMode.ReadWrite or MapMode.Write\n    && resource.Usage != GraphicsResourceUsage.Staging)\n    throw new ArgumentException(\"Create the resource with Staging usage for Read/Write maps\", nameof(resource));","typeGuard":"static bool SupportsMapMode(GraphicsResource r, MapMode m) =>\n    m is not (MapMode.Read or MapMode.ReadWrite or MapMode.Write) || r.Usage == GraphicsResourceUsage.Staging;","tryCatchPattern":"try { var mapped = commandList.Map(resource, MapMode.Read, 0); }\ncatch (ArgumentException) { /* copy to staging then map the staging copy */ }","preventionTips":["Create any resource you plan to Map with GraphicsResourceUsage.Staging.","For readback of GPU data, Copy to a staging resource first.","Prefer MapMode.WriteDiscard for whole-buffer rewrites on dynamic buffers."],"tags":["direct3d12","graphics","map","staging"],"backgroundTag":"invalid-argument-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}