Refactor Internal Command Buffer Copy APIs

Modify internal command buffer types to reflect the front end APIs for
copyTextureToBuffer and copyBufferToTexture.

Bug: dawn:17

Change-Id: I088a167ee7145d741e70ed28c1df7a12d24b72fc
Reviewed-on: https://dawn-review.googlesource.com/c/2740
Commit-Queue: Brandon1 Jones <brandon1.jones@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/CommandBuffer.cpp b/src/dawn_native/CommandBuffer.cpp
index 8ddcc15..5bdd277 100644
--- a/src/dawn_native/CommandBuffer.cpp
+++ b/src/dawn_native/CommandBuffer.cpp
@@ -35,29 +35,30 @@
 
     namespace {
 
-        MaybeError ValidateCopyLocationFitsInTexture(const TextureCopyLocation& location) {
-            const TextureBase* texture = location.texture.Get();
-            if (location.level >= texture->GetNumMipLevels()) {
+        MaybeError ValidateCopySizeFitsInTexture(const TextureCopy& textureCopy,
+                                                 const Extent3D& copySize) {
+            const TextureBase* texture = textureCopy.texture.Get();
+            if (textureCopy.level >= texture->GetNumMipLevels()) {
                 return DAWN_VALIDATION_ERROR("Copy mip-level out of range");
             }
 
-            if (location.slice >= texture->GetArrayLayers()) {
+            if (textureCopy.slice >= texture->GetArrayLayers()) {
                 return DAWN_VALIDATION_ERROR("Copy array-layer out of range");
             }
 
             // All texture dimensions are in uint32_t so by doing checks in uint64_t we avoid
             // overflows.
-            uint64_t level = location.level;
-            if (uint64_t(location.x) + uint64_t(location.width) >
+            uint64_t level = textureCopy.level;
+            if (uint64_t(textureCopy.origin.x) + uint64_t(copySize.width) >
                     (static_cast<uint64_t>(texture->GetSize().width) >> level) ||
-                uint64_t(location.y) + uint64_t(location.height) >
+                uint64_t(textureCopy.origin.y) + uint64_t(copySize.height) >
                     (static_cast<uint64_t>(texture->GetSize().height) >> level)) {
                 return DAWN_VALIDATION_ERROR("Copy would touch outside of the texture");
             }
 
             // TODO(cwallez@chromium.org): Check the depth bound differently for 2D arrays and 3D
             // textures
-            if (location.z != 0 || location.depth != 1) {
+            if (textureCopy.origin.z != 0 || copySize.depth != 1) {
                 return DAWN_VALIDATION_ERROR("No support for z != 0 and depth != 1 for now");
             }
 
@@ -69,31 +70,29 @@
             return offset <= bufferSize && (size <= (bufferSize - offset));
         }
 
-        MaybeError ValidateCopySizeFitsInBuffer(const BufferCopyLocation& location,
-                                                uint32_t dataSize) {
-            if (!FitsInBuffer(location.buffer.Get(), location.offset, dataSize)) {
+        MaybeError ValidateCopySizeFitsInBuffer(const BufferCopy& bufferCopy, uint32_t dataSize) {
+            if (!FitsInBuffer(bufferCopy.buffer.Get(), bufferCopy.offset, dataSize)) {
                 return DAWN_VALIDATION_ERROR("Copy would overflow the buffer");
             }
 
             return {};
         }
 
-        MaybeError ValidateTexelBufferOffset(TextureBase* texture,
-                                             const BufferCopyLocation& location) {
+        MaybeError ValidateTexelBufferOffset(TextureBase* texture, const BufferCopy& bufferCopy) {
             uint32_t texelSize =
                 static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat()));
-            if (location.offset % texelSize != 0) {
+            if (bufferCopy.offset % texelSize != 0) {
                 return DAWN_VALIDATION_ERROR("Buffer offset must be a multiple of the texel size");
             }
 
             return {};
         }
 
-        MaybeError ComputeTextureCopyBufferSize(const TextureCopyLocation& location,
+        MaybeError ComputeTextureCopyBufferSize(const Extent3D& copySize,
                                                 uint32_t rowPitch,
                                                 uint32_t* bufferSize) {
             // TODO(cwallez@chromium.org): check for overflows
-            *bufferSize = (rowPitch * (location.height - 1) + location.width) * location.depth;
+            *bufferSize = (rowPitch * (copySize.height - 1) + copySize.width) * copySize.depth;
 
             return {};
         }
@@ -103,13 +102,15 @@
             return texelSize * width;
         }
 
-        MaybeError ValidateRowPitch(const TextureCopyLocation& location, uint32_t rowPitch) {
+        MaybeError ValidateRowPitch(dawn::TextureFormat format,
+                                    const Extent3D& copySize,
+                                    uint32_t rowPitch) {
             if (rowPitch % kTextureRowPitchAlignment != 0) {
                 return DAWN_VALIDATION_ERROR("Row pitch must be a multiple of 256");
             }
 
-            uint32_t texelSize = TextureFormatPixelSize(location.texture.Get()->GetFormat());
-            if (rowPitch < location.width * texelSize) {
+            uint32_t texelSize = TextureFormatPixelSize(format);
+            if (rowPitch < copySize.width * texelSize) {
                 return DAWN_VALIDATION_ERROR(
                     "Row pitch must not be less than the number of bytes per row");
             }
@@ -385,11 +386,12 @@
                     CopyBufferToTextureCmd* copy = mIterator.NextCommand<CopyBufferToTextureCmd>();
 
                     uint32_t bufferCopySize = 0;
-                    DAWN_TRY(ValidateRowPitch(copy->destination, copy->rowPitch));
-                    DAWN_TRY(ComputeTextureCopyBufferSize(copy->destination, copy->rowPitch,
+                    DAWN_TRY(ValidateRowPitch(copy->destination.texture->GetFormat(),
+                                              copy->copySize, copy->source.rowPitch));
+                    DAWN_TRY(ComputeTextureCopyBufferSize(copy->copySize, copy->source.rowPitch,
                                                           &bufferCopySize));
 
-                    DAWN_TRY(ValidateCopyLocationFitsInTexture(copy->destination));
+                    DAWN_TRY(ValidateCopySizeFitsInTexture(copy->destination, copy->copySize));
                     DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->source, bufferCopySize));
                     DAWN_TRY(
                         ValidateTexelBufferOffset(copy->destination.texture.Get(), copy->source));
@@ -407,11 +409,12 @@
                     CopyTextureToBufferCmd* copy = mIterator.NextCommand<CopyTextureToBufferCmd>();
 
                     uint32_t bufferCopySize = 0;
-                    DAWN_TRY(ValidateRowPitch(copy->source, copy->rowPitch));
-                    DAWN_TRY(ComputeTextureCopyBufferSize(copy->source, copy->rowPitch,
-                                                          &bufferCopySize));
+                    DAWN_TRY(ValidateRowPitch(copy->source.texture->GetFormat(), copy->copySize,
+                                              copy->destination.rowPitch));
+                    DAWN_TRY(ComputeTextureCopyBufferSize(
+                        copy->copySize, copy->destination.rowPitch, &bufferCopySize));
 
-                    DAWN_TRY(ValidateCopyLocationFitsInTexture(copy->source));
+                    DAWN_TRY(ValidateCopySizeFitsInTexture(copy->source, copy->copySize));
                     DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->destination, bufferCopySize));
                     DAWN_TRY(
                         ValidateTexelBufferOffset(copy->source.texture.Get(), copy->destination));
@@ -657,18 +660,14 @@
         copy->source.buffer = source->buffer;
         copy->source.offset = source->offset;
         copy->destination.texture = destination->texture;
-        copy->destination.x = destination->origin.x;
-        copy->destination.y = destination->origin.y;
-        copy->destination.z = destination->origin.z;
-        copy->destination.width = copySize->width;
-        copy->destination.height = copySize->height;
-        copy->destination.depth = copySize->depth;
+        copy->destination.origin = destination->origin;
+        copy->copySize = *copySize;
         copy->destination.level = destination->level;
         copy->destination.slice = destination->slice;
         if (source->rowPitch == 0) {
-            copy->rowPitch = ComputeDefaultRowPitch(destination->texture, copySize->width);
+            copy->source.rowPitch = ComputeDefaultRowPitch(destination->texture, copySize->width);
         } else {
-            copy->rowPitch = source->rowPitch;
+            copy->source.rowPitch = source->rowPitch;
         }
     }
 
@@ -682,20 +681,16 @@
             mAllocator.Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer);
         new (copy) CopyTextureToBufferCmd;
         copy->source.texture = source->texture;
-        copy->source.x = source->origin.x;
-        copy->source.y = source->origin.y;
-        copy->source.z = source->origin.z;
-        copy->source.width = copySize->width;
-        copy->source.height = copySize->height;
-        copy->source.depth = copySize->depth;
+        copy->source.origin = source->origin;
+        copy->copySize = *copySize;
         copy->source.level = source->level;
         copy->source.slice = source->slice;
         copy->destination.buffer = destination->buffer;
         copy->destination.offset = destination->offset;
         if (destination->rowPitch == 0) {
-            copy->rowPitch = ComputeDefaultRowPitch(source->texture, copySize->width);
+            copy->destination.rowPitch = ComputeDefaultRowPitch(source->texture, copySize->width);
         } else {
-            copy->rowPitch = destination->rowPitch;
+            copy->destination.rowPitch = destination->rowPitch;
         }
     }
 
diff --git a/src/dawn_native/Commands.h b/src/dawn_native/Commands.h
index e4598ad..6ddf58d 100644
--- a/src/dawn_native/Commands.h
+++ b/src/dawn_native/Commands.h
@@ -54,35 +54,37 @@
         Ref<RenderPassDescriptorBase> info;
     };
 
-    struct BufferCopyLocation {
+    struct BufferCopy {
         Ref<BufferBase> buffer;
-        uint32_t offset;
+        uint32_t offset;       // Bytes
+        uint32_t rowPitch;     // Bytes
+        uint32_t imageHeight;  // Texels
     };
 
-    struct TextureCopyLocation {
+    struct TextureCopy {
         Ref<TextureBase> texture;
-        uint32_t x, y, z;
-        uint32_t width, height, depth;
         uint32_t level;
         uint32_t slice;
+        Origin3D origin;  // Texels
+        dawn::TextureAspect aspect;
     };
 
     struct CopyBufferToBufferCmd {
-        BufferCopyLocation source;
-        BufferCopyLocation destination;
+        BufferCopy source;
+        BufferCopy destination;
         uint32_t size;
     };
 
     struct CopyBufferToTextureCmd {
-        BufferCopyLocation source;
-        TextureCopyLocation destination;
-        uint32_t rowPitch;
+        BufferCopy source;
+        TextureCopy destination;
+        Extent3D copySize;  // Texels
     };
 
     struct CopyTextureToBufferCmd {
-        TextureCopyLocation source;
-        BufferCopyLocation destination;
-        uint32_t rowPitch;
+        TextureCopy source;
+        BufferCopy destination;
+        Extent3D copySize;  // Texels
     };
 
     struct DispatchCmd {
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index 65e7d6c..d2aff42 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -329,10 +329,9 @@
                     texture->TransitionUsageNow(commandList, dawn::TextureUsageBit::TransferDst);
 
                     auto copySplit = ComputeTextureCopySplit(
-                        copy->destination.x, copy->destination.y, copy->destination.z,
-                        copy->destination.width, copy->destination.height, copy->destination.depth,
+                        copy->destination.origin, copy->copySize,
                         static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())),
-                        copy->source.offset, copy->rowPitch);
+                        copy->source.offset, copy->source.rowPitch);
 
                     D3D12_TEXTURE_COPY_LOCATION textureLocation;
                     textureLocation.pResource = texture->GetD3D12Resource();
@@ -352,7 +351,7 @@
                         bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width;
                         bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height;
                         bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth;
-                        bufferLocation.PlacedFootprint.Footprint.RowPitch = copy->rowPitch;
+                        bufferLocation.PlacedFootprint.Footprint.RowPitch = copy->source.rowPitch;
 
                         D3D12_BOX sourceRegion;
                         sourceRegion.left = info.bufferOffset.x;
@@ -377,10 +376,9 @@
                     buffer->TransitionUsageNow(commandList, dawn::BufferUsageBit::TransferDst);
 
                     auto copySplit = ComputeTextureCopySplit(
-                        copy->source.x, copy->source.y, copy->source.z, copy->source.width,
-                        copy->source.height, copy->source.depth,
+                        copy->source.origin, copy->copySize,
                         static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())),
-                        copy->destination.offset, copy->rowPitch);
+                        copy->destination.offset, copy->destination.rowPitch);
 
                     D3D12_TEXTURE_COPY_LOCATION textureLocation;
                     textureLocation.pResource = texture->GetD3D12Resource();
@@ -399,7 +397,8 @@
                         bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width;
                         bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height;
                         bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth;
-                        bufferLocation.PlacedFootprint.Footprint.RowPitch = copy->rowPitch;
+                        bufferLocation.PlacedFootprint.Footprint.RowPitch =
+                            copy->destination.rowPitch;
 
                         D3D12_BOX sourceRegion;
                         sourceRegion.left = info.textureOffset.x;
diff --git a/src/dawn_native/d3d12/TextureCopySplitter.cpp b/src/dawn_native/d3d12/TextureCopySplitter.cpp
index 32f5309..7c58e89 100644
--- a/src/dawn_native/d3d12/TextureCopySplitter.cpp
+++ b/src/dawn_native/d3d12/TextureCopySplitter.cpp
@@ -24,32 +24,26 @@
                                  uint32_t rowPitch,
                                  uint32_t slicePitch,
                                  uint32_t texelSize,
-                                 uint32_t* texelOffsetX,
-                                 uint32_t* texelOffsetY,
-                                 uint32_t* texelOffsetZ) {
+                                 Origin3D* texelOffset) {
             uint32_t byteOffsetX = offset % rowPitch;
             offset -= byteOffsetX;
             uint32_t byteOffsetY = offset % slicePitch;
             uint32_t byteOffsetZ = offset - byteOffsetY;
 
-            *texelOffsetX = byteOffsetX / texelSize;
-            *texelOffsetY = byteOffsetY / rowPitch;
-            *texelOffsetZ = byteOffsetZ / slicePitch;
+            texelOffset->x = byteOffsetX / texelSize;
+            texelOffset->y = byteOffsetY / rowPitch;
+            texelOffset->z = byteOffsetZ / slicePitch;
         }
     }  // namespace
 
-    TextureCopySplit ComputeTextureCopySplit(uint32_t x,
-                                             uint32_t y,
-                                             uint32_t z,
-                                             uint32_t width,
-                                             uint32_t height,
-                                             uint32_t depth,
+    TextureCopySplit ComputeTextureCopySplit(Origin3D origin,
+                                             Extent3D copySize,
                                              uint32_t texelSize,
                                              uint32_t offset,
                                              uint32_t rowPitch) {
         TextureCopySplit copy;
 
-        if (z != 0 || depth > 1) {
+        if (origin.z != 0 || copySize.depth > 1) {
             // TODO(enga@google.com): Handle 3D
             ASSERT(false);
             return copy;
@@ -63,20 +57,14 @@
         if (offset == alignedOffset) {
             copy.count = 1;
 
-            copy.copies[0].textureOffset.x = x;
-            copy.copies[0].textureOffset.y = y;
-            copy.copies[0].textureOffset.z = z;
+            copy.copies[0].textureOffset = origin;
 
-            copy.copies[0].copySize.width = width;
-            copy.copies[0].copySize.height = height;
-            copy.copies[0].copySize.depth = depth;
+            copy.copies[0].copySize = copySize;
 
             copy.copies[0].bufferOffset.x = 0;
             copy.copies[0].bufferOffset.y = 0;
             copy.copies[0].bufferOffset.z = 0;
-            copy.copies[0].bufferSize.width = width;
-            copy.copies[0].bufferSize.height = height;
-            copy.copies[0].bufferSize.depth = depth;
+            copy.copies[0].bufferSize = copySize;
 
             // Return early. There is only one copy needed because the offset is already 512-byte
             // aligned
@@ -85,13 +73,13 @@
 
         ASSERT(alignedOffset < offset);
 
-        uint32_t texelOffsetX, texelOffsetY, texelOffsetZ;
-        ComputeTexelOffsets(offset - alignedOffset, rowPitch, rowPitch * height, texelSize,
-                            &texelOffsetX, &texelOffsetY, &texelOffsetZ);
+        Origin3D texelOffset;
+        ComputeTexelOffsets(offset - alignedOffset, rowPitch, rowPitch * copySize.height, texelSize,
+                            &texelOffset);
 
         uint32_t rowPitchInTexels = rowPitch / texelSize;
 
-        if (width + texelOffsetX <= rowPitchInTexels) {
+        if (copySize.width + texelOffset.x <= rowPitchInTexels) {
             // The region's rows fit inside the row pitch. In this case, extend the width of the
             // PlacedFootprint and copy the buffer with an offset location
             //  |<--------------- row pitch --------------->|
@@ -117,20 +105,14 @@
 
             copy.count = 1;
 
-            copy.copies[0].textureOffset.x = x;
-            copy.copies[0].textureOffset.y = y;
-            copy.copies[0].textureOffset.z = z;
+            copy.copies[0].textureOffset = origin;
 
-            copy.copies[0].copySize.width = width;
-            copy.copies[0].copySize.height = height;
-            copy.copies[0].copySize.depth = depth;
+            copy.copies[0].copySize = copySize;
 
-            copy.copies[0].bufferOffset.x = texelOffsetX;
-            copy.copies[0].bufferOffset.y = texelOffsetY;
-            copy.copies[0].bufferOffset.z = texelOffsetZ;
-            copy.copies[0].bufferSize.width = width + texelOffsetX;
-            copy.copies[0].bufferSize.height = height + texelOffsetY;
-            copy.copies[0].bufferSize.depth = depth + texelOffsetZ;
+            copy.copies[0].bufferOffset = texelOffset;
+            copy.copies[0].bufferSize.width = copySize.width + texelOffset.x;
+            copy.copies[0].bufferSize.height = copySize.height + texelOffset.y;
+            copy.copies[0].bufferSize.depth = copySize.depth + texelOffset.z;
 
             return copy;
         }
@@ -171,37 +153,33 @@
 
         copy.count = 2;
 
-        copy.copies[0].textureOffset.x = x;
-        copy.copies[0].textureOffset.y = y;
-        copy.copies[0].textureOffset.z = z;
+        copy.copies[0].textureOffset = origin;
 
-        ASSERT(rowPitchInTexels > texelOffsetX);
-        copy.copies[0].copySize.width = rowPitchInTexels - texelOffsetX;
-        copy.copies[0].copySize.height = height;
-        copy.copies[0].copySize.depth = depth;
+        ASSERT(rowPitchInTexels > texelOffset.x);
+        copy.copies[0].copySize.width = rowPitchInTexels - texelOffset.x;
+        copy.copies[0].copySize.height = copySize.height;
+        copy.copies[0].copySize.depth = copySize.depth;
 
-        copy.copies[0].bufferOffset.x = texelOffsetX;
-        copy.copies[0].bufferOffset.y = texelOffsetY;
-        copy.copies[0].bufferOffset.z = texelOffsetZ;
+        copy.copies[0].bufferOffset = texelOffset;
         copy.copies[0].bufferSize.width = rowPitchInTexels;
-        copy.copies[0].bufferSize.height = height + texelOffsetY;
-        copy.copies[0].bufferSize.depth = depth + texelOffsetZ;
+        copy.copies[0].bufferSize.height = copySize.height + texelOffset.y;
+        copy.copies[0].bufferSize.depth = copySize.depth + texelOffset.z;
 
-        copy.copies[1].textureOffset.x = x + copy.copies[0].copySize.width;
-        copy.copies[1].textureOffset.y = y;
-        copy.copies[1].textureOffset.z = z;
+        copy.copies[1].textureOffset.x = origin.x + copy.copies[0].copySize.width;
+        copy.copies[1].textureOffset.y = origin.y;
+        copy.copies[1].textureOffset.z = origin.z;
 
-        ASSERT(width > copy.copies[0].copySize.width);
-        copy.copies[1].copySize.width = width - copy.copies[0].copySize.width;
-        copy.copies[1].copySize.height = height;
-        copy.copies[1].copySize.depth = depth;
+        ASSERT(copySize.width > copy.copies[0].copySize.width);
+        copy.copies[1].copySize.width = copySize.width - copy.copies[0].copySize.width;
+        copy.copies[1].copySize.height = copySize.height;
+        copy.copies[1].copySize.depth = copySize.depth;
 
         copy.copies[1].bufferOffset.x = 0;
-        copy.copies[1].bufferOffset.y = texelOffsetY + 1;
-        copy.copies[1].bufferOffset.z = texelOffsetZ;
+        copy.copies[1].bufferOffset.y = texelOffset.y + 1;
+        copy.copies[1].bufferOffset.z = texelOffset.z;
         copy.copies[1].bufferSize.width = copy.copies[1].copySize.width;
-        copy.copies[1].bufferSize.height = height + texelOffsetY + 1;
-        copy.copies[1].bufferSize.depth = depth + texelOffsetZ;
+        copy.copies[1].bufferSize.height = copySize.height + texelOffset.y + 1;
+        copy.copies[1].bufferSize.depth = copySize.depth + texelOffset.z;
 
         return copy;
     }
diff --git a/src/dawn_native/d3d12/TextureCopySplitter.h b/src/dawn_native/d3d12/TextureCopySplitter.h
index eec55e2..f82da87 100644
--- a/src/dawn_native/d3d12/TextureCopySplitter.h
+++ b/src/dawn_native/d3d12/TextureCopySplitter.h
@@ -24,24 +24,12 @@
     struct TextureCopySplit {
         static constexpr unsigned int kMaxTextureCopyRegions = 2;
 
-        struct Extent {
-            uint32_t width = 0;
-            uint32_t height = 0;
-            uint32_t depth = 0;
-        };
-
-        struct Origin {
-            uint32_t x = 0;
-            uint32_t y = 0;
-            uint32_t z = 0;
-        };
-
         struct CopyInfo {
-            Origin textureOffset;
-            Origin bufferOffset;
-            Extent bufferSize;
+            Origin3D textureOffset;
+            Origin3D bufferOffset;
+            Extent3D bufferSize;
 
-            Extent copySize;
+            Extent3D copySize;
         };
 
         uint32_t offset = 0;
@@ -49,12 +37,8 @@
         std::array<CopyInfo, kMaxTextureCopyRegions> copies;
     };
 
-    TextureCopySplit ComputeTextureCopySplit(uint32_t x,
-                                             uint32_t y,
-                                             uint32_t z,
-                                             uint32_t width,
-                                             uint32_t height,
-                                             uint32_t depth,
+    TextureCopySplit ComputeTextureCopySplit(Origin3D origin,
+                                             Extent3D copySize,
                                              uint32_t texelSize,
                                              uint32_t offset,
                                              uint32_t rowPitch);
diff --git a/src/dawn_native/metal/CommandBufferMTL.mm b/src/dawn_native/metal/CommandBufferMTL.mm
index 3aff378..bf37d1f 100644
--- a/src/dawn_native/metal/CommandBufferMTL.mm
+++ b/src/dawn_native/metal/CommandBufferMTL.mm
@@ -253,24 +253,25 @@
                     CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
                     auto& src = copy->source;
                     auto& dst = copy->destination;
+                    auto& copySize = copy->copySize;
                     Buffer* buffer = ToBackend(src.buffer.Get());
                     Texture* texture = ToBackend(dst.texture.Get());
 
                     MTLOrigin origin;
-                    origin.x = dst.x;
-                    origin.y = dst.y;
-                    origin.z = dst.z;
+                    origin.x = dst.origin.x;
+                    origin.y = dst.origin.y;
+                    origin.z = dst.origin.z;
 
                     MTLSize size;
-                    size.width = dst.width;
-                    size.height = dst.height;
-                    size.depth = dst.depth;
+                    size.width = copySize.width;
+                    size.height = copySize.height;
+                    size.depth = copySize.depth;
 
                     encoders.EnsureBlit(commandBuffer);
                     [encoders.blit copyFromBuffer:buffer->GetMTLBuffer()
                                      sourceOffset:src.offset
-                                sourceBytesPerRow:copy->rowPitch
-                              sourceBytesPerImage:(copy->rowPitch * dst.height)
+                                sourceBytesPerRow:src.rowPitch
+                              sourceBytesPerImage:(src.rowPitch * copySize.height)
                                        sourceSize:size
                                         toTexture:texture->GetMTLTexture()
                                  destinationSlice:dst.slice
@@ -282,18 +283,19 @@
                     CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
                     auto& src = copy->source;
                     auto& dst = copy->destination;
+                    auto& copySize = copy->copySize;
                     Texture* texture = ToBackend(src.texture.Get());
                     Buffer* buffer = ToBackend(dst.buffer.Get());
 
                     MTLOrigin origin;
-                    origin.x = src.x;
-                    origin.y = src.y;
-                    origin.z = src.z;
+                    origin.x = src.origin.x;
+                    origin.y = src.origin.y;
+                    origin.z = src.origin.z;
 
                     MTLSize size;
-                    size.width = src.width;
-                    size.height = src.height;
-                    size.depth = src.depth;
+                    size.width = copySize.width;
+                    size.height = copySize.height;
+                    size.depth = copySize.depth;
 
                     encoders.EnsureBlit(commandBuffer);
                     [encoders.blit copyFromTexture:texture->GetMTLTexture()
@@ -303,8 +305,8 @@
                                         sourceSize:size
                                           toBuffer:buffer->GetMTLBuffer()
                                  destinationOffset:dst.offset
-                            destinationBytesPerRow:copy->rowPitch
-                          destinationBytesPerImage:copy->rowPitch * src.height];
+                            destinationBytesPerRow:dst.rowPitch
+                          destinationBytesPerImage:dst.rowPitch * copySize.height];
                 } break;
 
                 default: { UNREACHABLE(); } break;
diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp
index ec03c77..3d36fa2 100644
--- a/src/dawn_native/opengl/CommandBufferGL.cpp
+++ b/src/dawn_native/opengl/CommandBufferGL.cpp
@@ -321,6 +321,7 @@
                     CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
                     auto& src = copy->source;
                     auto& dst = copy->destination;
+                    auto& copySize = copy->copySize;
                     Buffer* buffer = ToBackend(src.buffer.Get());
                     Texture* texture = ToBackend(dst.texture.Get());
                     GLenum target = texture->GetGLTarget();
@@ -331,18 +332,18 @@
                     glBindTexture(target, texture->GetHandle());
 
                     glPixelStorei(GL_UNPACK_ROW_LENGTH,
-                                  copy->rowPitch / TextureFormatPixelSize(texture->GetFormat()));
+                                  src.rowPitch / TextureFormatPixelSize(texture->GetFormat()));
                     switch (texture->GetDimension()) {
                         case dawn::TextureDimension::e2D:
                             if (texture->GetArrayLayers() > 1) {
                                 glTexSubImage3D(
-                                    target, dst.level, dst.x, dst.y, dst.slice, dst.width,
-                                    dst.height, 1, format.format, format.type,
+                                    target, dst.level, dst.origin.x, dst.origin.y, dst.slice,
+                                    copySize.width, copySize.height, 1, format.format, format.type,
                                     reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
                             } else {
                                 glTexSubImage2D(
-                                    target, dst.level, dst.x, dst.y, dst.width, dst.height,
-                                    format.format, format.type,
+                                    target, dst.level, dst.origin.x, dst.origin.y, copySize.width,
+                                    copySize.height, format.format, format.type,
                                     reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
                             }
                             break;
@@ -359,6 +360,7 @@
                     CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
                     auto& src = copy->source;
                     auto& dst = copy->destination;
+                    auto& copySize = copy->copySize;
                     Texture* texture = ToBackend(src.texture.Get());
                     Buffer* buffer = ToBackend(dst.buffer.Get());
                     auto format = texture->GetGLFormat();
@@ -390,11 +392,11 @@
 
                     glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
                     glPixelStorei(GL_PACK_ROW_LENGTH,
-                                  copy->rowPitch / TextureFormatPixelSize(texture->GetFormat()));
-                    ASSERT(src.depth == 1 && src.z == 0);
+                                  dst.rowPitch / TextureFormatPixelSize(texture->GetFormat()));
+                    ASSERT(copySize.depth == 1 && src.origin.z == 0);
                     void* offset = reinterpret_cast<void*>(static_cast<uintptr_t>(dst.offset));
-                    glReadPixels(src.x, src.y, src.width, src.height, format.format, format.type,
-                                 offset);
+                    glReadPixels(src.origin.x, src.origin.y, copySize.width, copySize.height,
+                                 format.format, format.type, offset);
                     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 
                     glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp
index 8f5c462..23dfd55 100644
--- a/src/dawn_native/vulkan/CommandBufferVk.cpp
+++ b/src/dawn_native/vulkan/CommandBufferVk.cpp
@@ -39,30 +39,31 @@
             }
         }
 
-        VkBufferImageCopy ComputeBufferImageCopyRegion(uint32_t rowPitch,
-                                                       const BufferCopyLocation& bufferLocation,
-                                                       const TextureCopyLocation& textureLocation) {
-            const Texture* texture = ToBackend(textureLocation.texture).Get();
+        VkBufferImageCopy ComputeBufferImageCopyRegion(const BufferCopy& bufferCopy,
+                                                       const TextureCopy& textureCopy,
+                                                       const Extent3D& copySize) {
+            const Texture* texture = ToBackend(textureCopy.texture.Get());
 
             VkBufferImageCopy region;
 
-            region.bufferOffset = bufferLocation.offset;
+            region.bufferOffset = bufferCopy.offset;
             // In Vulkan the row length is in texels while it is in bytes for Dawn
-            region.bufferRowLength = rowPitch / TextureFormatPixelSize(texture->GetFormat());
-            region.bufferImageHeight = rowPitch * textureLocation.height;
+            region.bufferRowLength =
+                bufferCopy.rowPitch / TextureFormatPixelSize(texture->GetFormat());
+            region.bufferImageHeight = bufferCopy.rowPitch * copySize.height;
 
             region.imageSubresource.aspectMask = texture->GetVkAspectMask();
-            region.imageSubresource.mipLevel = textureLocation.level;
-            region.imageSubresource.baseArrayLayer = textureLocation.slice;
+            region.imageSubresource.mipLevel = textureCopy.level;
+            region.imageSubresource.baseArrayLayer = textureCopy.slice;
             region.imageSubresource.layerCount = 1;
 
-            region.imageOffset.x = textureLocation.x;
-            region.imageOffset.y = textureLocation.y;
-            region.imageOffset.z = textureLocation.z;
+            region.imageOffset.x = textureCopy.origin.x;
+            region.imageOffset.y = textureCopy.origin.y;
+            region.imageOffset.z = textureCopy.origin.z;
 
-            region.imageExtent.width = textureLocation.width;
-            region.imageExtent.height = textureLocation.height;
-            region.imageExtent.depth = textureLocation.depth;
+            region.imageExtent.width = copySize.width;
+            region.imageExtent.height = copySize.height;
+            region.imageExtent.depth = copySize.depth;
 
             return region;
         }
@@ -173,7 +174,7 @@
                     VkImage dstImage = ToBackend(dst.texture)->GetHandle();
 
                     VkBufferImageCopy region =
-                        ComputeBufferImageCopyRegion(copy->rowPitch, src, dst);
+                        ComputeBufferImageCopyRegion(src, dst, copy->copySize);
 
                     // The image is written to so the Dawn guarantees make sure it is in the
                     // TRANSFER_DST_OPTIMAL layout
@@ -196,7 +197,7 @@
                     VkBuffer dstBuffer = ToBackend(dst.buffer)->GetHandle();
 
                     VkBufferImageCopy region =
-                        ComputeBufferImageCopyRegion(copy->rowPitch, dst, src);
+                        ComputeBufferImageCopyRegion(dst, src, copy->copySize);
 
                     // The Dawn TransferSrc usage is always mapped to GENERAL
                     device->fn.CmdCopyImageToBuffer(commands, srcImage, VK_IMAGE_LAYOUT_GENERAL,
diff --git a/src/tests/unittests/d3d12/CopySplitTests.cpp b/src/tests/unittests/d3d12/CopySplitTests.cpp
index 88e1ceb..e3d6688 100644
--- a/src/tests/unittests/d3d12/CopySplitTests.cpp
+++ b/src/tests/unittests/d3d12/CopySplitTests.cpp
@@ -220,7 +220,10 @@
 class CopySplitTest : public testing::Test {
     protected:
         TextureCopySplit DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
-            TextureCopySplit copySplit = ComputeTextureCopySplit(textureSpec.x, textureSpec.y, textureSpec.z, textureSpec.width, textureSpec.height, textureSpec.depth, textureSpec.texelSize, bufferSpec.offset, bufferSpec.rowPitch);
+            TextureCopySplit copySplit = ComputeTextureCopySplit(
+                {textureSpec.x, textureSpec.y, textureSpec.z},
+                {textureSpec.width, textureSpec.height, textureSpec.depth}, textureSpec.texelSize,
+                bufferSpec.offset, bufferSpec.rowPitch);
             ValidateCopySplit(textureSpec, bufferSpec, copySplit);
             return copySplit;
         }