{"record":{"id":"6b5fc437dd7112d3","repo":"stride3d/stride","slug":"nameof-source-and-nameof-destination-textures-don-t-match","errorCode":null,"errorMessage":"{nameof(source)} and {nameof(destination)} textures don't match","messagePattern":"(.+?) and (.+?) textures don't match","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs","lineNumber":958,"sourceCode":"\n            GraphicsDevice.NativeDeviceApi.vkCmdClearColorImage(currentCommandList.NativeCommandBuffer, texture.NativeImage, VkImageLayout.TransferDstOptimal, &clearValue, 1, &clearRange);\n\n            ResourceBarrierTransition(texture, BarrierLayout.UnorderedAccess);\n        }\n\n        public unsafe void Copy(GraphicsResource source, GraphicsResource destination)\n        {\n            RecordDebugCounter(DebugCounterKind.Copy);\n            // TODO VULKAN: One copy per mip level\n\n            if (source is Texture sourceTexture && destination is Texture destinationTexture)\n            {\n                if (sourceTexture.Width != destinationTexture.Width ||\n                    sourceTexture.Height != destinationTexture.Height ||\n                    sourceTexture.Depth != destinationTexture.Depth ||\n                    sourceTexture.ArraySize != destinationTexture.ArraySize ||\n                    sourceTexture.MipLevelCount != destinationTexture.MipLevelCount)\n                    throw new InvalidOperationException($\"{nameof(source)} and {nameof(destination)} textures don't match\");\n\n                CleanupRenderPass();\n\n                var imageBarriers = stackalloc VkImageMemoryBarrier[2];\n                var bufferBarriers = stackalloc VkBufferMemoryBarrier[2];\n\n                var sourceParent = sourceTexture.ParentTexture ?? sourceTexture;\n                var destinationParent = destinationTexture.ParentTexture ?? destinationTexture;\n\n                uint bufferBarrierCount = 0;\n                uint imageBarrierCount = 0;\n\n                // Initial barriers\n                if (sourceTexture.Usage == GraphicsResourceUsage.Staging)\n                {\n                    bufferBarriers[bufferBarrierCount++] = new VkBufferMemoryBarrier(sourceParent.NativeBuffer, sourceTexture.NativeAccessMask, VkAccessFlags.TransferRead);\n                }\n                else","sourceCodeStart":940,"sourceCodeEnd":976,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs#L940-L976","documentation":"Copy of a full texture resource on Vulkan requires source and destination textures to have identical dimensions, array size, and mip level count. Stride validates this and throws InvalidOperationException when they diverge, since vkCmdCopyImage cannot reconcile differing extents.","triggerScenarios":"Calling CommandList.Copy(Texture source, Texture destination) (full-resource copy) where Width, Height, Depth, ArraySize, or MipLevelCount differ between the two textures.","commonSituations":"Copying between a render target and a staging texture allocated with different mip counts or array layers; resizing a texture and keeping a stale destination; downscaling via Copy instead of a blit.","solutions":["Ensure source and destination textures are created with identical Width, Height, Depth, ArraySize and MipLevelCount","Use CopyScissor (region copy) for differently sized textures instead of the full-texture Copy","Recreate the destination texture to match the source description before copying"],"exampleFix":"// before\ncmdList.Copy(oldTexture, resizedTexture); // sizes differ\n// after\nvar newTex = Texture.New2D(device, oldTexture.Width, oldTexture.Height, oldTexture.Format);\ncmdList.Copy(oldTexture, newTex);","handlingStrategy":"validation","validationCode":"bool canCopy = src.Width == dst.Width && src.Height == dst.Height && src.Depth == dst.Depth && src.ArraySize == dst.ArraySize && src.MipLevelCount == dst.MipLevelCount;\nif (!canCopy) useRegionCopyInstead();","typeGuard":"bool IsCopyCompatible(Texture s, Texture d) => s.Width==d.Width && s.Height==d.Height && s.Depth==d.Depth && s.ArraySize==d.ArraySize && s.MipLevelCount==d.MipLevelCount;","tryCatchPattern":"try { cmdList.Copy(src, dst); } catch (InvalidOperationException ex) { /* recreate dst to match src */ }","preventionTips":["Create destination textures via src.Description clones","Prefer CopyScissor for resizing/scaling needs","Assert texture equality in debug builds before copy"],"tags":["vulkan","texture-copy","shape-mismatch"],"backgroundTag":"shape-mismatch","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"}