{"record":{"id":"4a116d9ca32a3d58","repo":"stride3d/stride","slug":"copy-from-staging-doesn-t-support-source-region-other-than","errorCode":null,"errorMessage":"Copy from Staging doesn't support source region other than full texture","messagePattern":"Copy from Staging doesn't support source region other than full texture","errorType":"exception","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs","lineNumber":1245,"sourceCode":"                            imageExtent = new VkExtent3D((uint)(region.Right - region.Left), (uint)(region.Bottom - region.Top), (uint)(region.Back - region.Front))\n                        };\n                        GraphicsDevice.NativeDeviceApi.vkCmdCopyImageToBuffer(currentCommandList.NativeCommandBuffer, sourceParent.NativeImage, VkImageLayout.TransferSrcOptimal, destinationParent.NativeBuffer, 1, &copy);\n                    }\n\n                    //// VkFence for host access\n                    destinationParent.CommandListFenceValue = null;\n                    destinationParent.UpdatingCommandList = this;\n                    currentCommandList.StagingResources.Add(destinationParent);\n                }\n                else\n                {\n                    var destinationSubresource = GetSubresourceLayers(destinationTexture, destinationParent.NativeImageAspect, destinationSubResource);\n\n                    if (sourceTexture.Usage == GraphicsResourceUsage.Staging)\n                    {\n                        if (region.Left != 0 || region.Top != 0 || region.Front != 0\n                            && region.Right != mipmapDescription.Width || region.Bottom != mipmapDescription.Height || region.Back != mipmapDescription.Depth)\n                            throw new NotImplementedException(\"Copy from Staging doesn't support source region other than full texture\");\n\n                        var copy = new VkBufferImageCopy\n                        {\n                            imageSubresource = destinationSubresource,\n                            bufferOffset = (ulong) sourceTexture.ComputeBufferOffset(sourceSubresource, 0),\n                            bufferImageHeight = (uint) sourceTexture.Height,\n                            bufferRowLength = (uint) sourceTexture.Width,\n                            imageOffset = new VkOffset3D(dstX, dstY, dstZ),\n                            imageExtent = new VkExtent3D(region.Right - region.Left, region.Bottom - region.Top, region.Back - region.Front)\n                        };\n                        GraphicsDevice.NativeDeviceApi.vkCmdCopyBufferToImage(currentCommandList.NativeCommandBuffer, sourceParent.NativeBuffer, destinationParent.NativeImage, VkImageLayout.TransferDstOptimal, regionCount: 1, &copy);\n                    }\n                    else\n                    {\n                        var copy = new VkImageCopy\n                        {\n                            srcSubresource = GetSubresourceLayers(sourceTexture, sourceParent.NativeImageAspect, sourceSubresource),\n                            srcOffset = new VkOffset3D(region.Left, region.Top, region.Front),","sourceCodeStart":1227,"sourceCodeEnd":1263,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs#L1227-L1263","documentation":"When copying from a Staging texture on Vulkan, Stride only supports copying the entire mip level; partial source regions are unimplemented. The operand check also has a subtle precedence quirk, but the intent is: any region other than the full texture throws NotImplementedException.","triggerScenarios":"CommandList.Copy(region-based overload) with sourceTexture.Usage == GraphicsResourceUsage.Staging and a region whose Left/Top/Front or Right/Bottom/Back do not exactly cover the mip dimensions.","commonSituations":"Reading back only part of a staging texture; copying a sub-rectangle from a CPU-populated texture to a GPU texture; assuming staging copies behave like D3D11 box copies.","solutions":["Copy the full texture region (region covering the entire mip) from staging, then perform sub-region copies between GPU textures","Use CopyScissor between two GPU (non-staging) textures for partial copies","Upload the partial data into a properly sized staging texture matching the region instead"],"exampleFix":"// before\ncmdList.Copy(stagingTex, gpuTex, subRegion); // partial staging copy\n// after\ncmdList.Copy(stagingTex, gpuTex); // full staging copy\ncmdList.CopyScissor(gpuTex, targetTex, subRegion);","handlingStrategy":"validation","validationCode":"if (stagingTex.Usage == GraphicsResourceUsage.Staging)\n    ensureRegionCoversFullMip(region, mipWidth, mipHeight, mipDepth);","typeGuard":null,"tryCatchPattern":"try { cmdList.Copy(stagingTex, gpuTex, region); } catch (NotImplementedException) { cmdList.Copy(stagingTex, gpuTex); }","preventionTips":["Only copy full mips from staging textures","Do sub-region copies between GPU textures after an initial full staging copy","Size staging textures to the exact region you intend to upload"],"tags":["vulkan","staging-texture","not-implemented"],"backgroundTag":"method-not-implemented","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}