D3D12: Save bufferLocation into TextureCopySubresource::CopyInfo

This patch replaces `alignedOffset` and `bufferSize` with `bufferLocation`
in `TextureCopySubresource::CopyInfo` so that we can directly use
`bufferLocation` in the D3D12 call `CopyTextureRegion`.

Bug: chromium:42241700
Change-Id: I681da939762ae45d74b2c6850e5d707b30d76087
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/208597
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
diff --git a/src/dawn/native/d3d12/TextureCopySplitter.cpp b/src/dawn/native/d3d12/TextureCopySplitter.cpp
index 27c177b..c58251a 100644
--- a/src/dawn/native/d3d12/TextureCopySplitter.cpp
+++ b/src/dawn/native/d3d12/TextureCopySplitter.cpp
@@ -77,6 +77,20 @@
     }
 }
 
+void FillFootprintAndOffsetOfBufferLocation(D3D12_TEXTURE_COPY_LOCATION* bufferLocation,
+                                            uint64_t alignedOffset,
+                                            Extent3D bufferSize,
+                                            uint32_t bytesPerRow) {
+    bufferLocation->Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+    bufferLocation->pResource = nullptr;
+    bufferLocation->PlacedFootprint.Offset = alignedOffset;
+    bufferLocation->PlacedFootprint.Footprint.Width = bufferSize.width;
+    bufferLocation->PlacedFootprint.Footprint.Height = bufferSize.height;
+    bufferLocation->PlacedFootprint.Footprint.Depth = bufferSize.depthOrArrayLayers;
+    bufferLocation->PlacedFootprint.Footprint.RowPitch = bytesPerRow;
+    bufferLocation->PlacedFootprint.Footprint.Format = DXGI_FORMAT_UNKNOWN;
+}
+
 }  // namespace
 
 Extent3D TextureCopySubresource::CopyInfo::GetCopySize() const {
@@ -108,6 +122,28 @@
     }
 }
 
+uint64_t TextureCopySubresource::CopyInfo::GetAlignedOffset() const {
+    return bufferLocation.PlacedFootprint.Offset;
+}
+
+Extent3D TextureCopySubresource::CopyInfo::GetBufferSize() const {
+    return {bufferLocation.PlacedFootprint.Footprint.Width,
+            bufferLocation.PlacedFootprint.Footprint.Height,
+            bufferLocation.PlacedFootprint.Footprint.Depth};
+}
+
+void TextureCopySubresource::CopyInfo::SetAlignedOffset(uint64_t alignedOffset) {
+    bufferLocation.PlacedFootprint.Offset = alignedOffset;
+}
+
+void TextureCopySubresource::CopyInfo::SetHeightInBufferLocation(uint32_t bufferHeight) {
+    bufferLocation.PlacedFootprint.Footprint.Height = bufferHeight;
+}
+
+void TextureCopySubresource::CopyInfo::SetDepthInBufferLocation(uint32_t bufferDepth) {
+    bufferLocation.PlacedFootprint.Footprint.Depth = bufferDepth;
+}
+
 TextureCopySubresource::CopyInfo* TextureCopySubresource::AddCopy() {
     DAWN_ASSERT(this->count < kMaxTextureCopyRegions);
     return &this->copies[this->count++];
@@ -132,13 +168,13 @@
     if (offset == alignedOffset) {
         copy.count = 1;
 
-        copy.copies[0].alignedOffset = alignedOffset;
         Origin3D textureOffset = origin;
         Origin3D bufferOffset = {0, 0, 0};
-        copy.copies[0].bufferSize = copySize;
 
         ComputeSourceRegionForCopyInfo(&copy.copies[0], direction, bufferOffset, textureOffset,
                                        copySize);
+        FillFootprintAndOffsetOfBufferLocation(&copy.copies[0].bufferLocation, alignedOffset,
+                                               copySize, bytesPerRow);
 
         return copy;
     }
@@ -200,17 +236,16 @@
 
         copy.count = 1;
 
-        copy.copies[0].alignedOffset = alignedOffset;
         Origin3D textureOffset = origin;
         Origin3D bufferOffset = texelOffset;
-
-        copy.copies[0].bufferSize.width = copySize.width + texelOffset.x;
-        copy.copies[0].bufferSize.height = copySize.height + texelOffset.y;
-        copy.copies[0].bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers;
-
         ComputeSourceRegionForCopyInfo(&copy.copies[0], direction, bufferOffset, textureOffset,
                                        copySize);
 
+        Extent3D bufferSize = {copySize.width + texelOffset.x, copySize.height + texelOffset.y,
+                               copySize.depthOrArrayLayers};
+        FillFootprintAndOffsetOfBufferLocation(&copy.copies[0].bufferLocation, alignedOffset,
+                                               bufferSize, bytesPerRow);
+
         return copy;
     }
 
@@ -250,7 +285,6 @@
 
     copy.count = 2;
 
-    copy.copies[0].alignedOffset = alignedOffset;
     Origin3D textureOffset0 = origin;
 
     DAWN_ASSERT(bytesPerRow > byteOffsetInRowPitch);
@@ -259,11 +293,12 @@
                           copySize.depthOrArrayLayers};
 
     Origin3D bufferOffset0 = texelOffset;
-    copy.copies[0].bufferSize.width = texelsPerRow;
-    copy.copies[0].bufferSize.height = copySize.height + texelOffset.y;
-    copy.copies[0].bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers;
     ComputeSourceRegionForCopyInfo(&copy.copies[0], direction, bufferOffset0, textureOffset0,
                                    copySize0);
+    Extent3D bufferSize0 = {texelsPerRow, copySize.height + texelOffset.y,
+                            copySize.depthOrArrayLayers};
+    FillFootprintAndOffsetOfBufferLocation(&copy.copies[0].bufferLocation, alignedOffset,
+                                           bufferSize0, bytesPerRow);
 
     uint64_t offsetForCopy1 = offset + copySize0.width / blockInfo.width * blockInfo.byteSize;
     uint64_t alignedOffsetForCopy1 = AlignDownForDataPlacement(offsetForCopy1);
@@ -273,7 +308,6 @@
     DAWN_ASSERT(texelOffsetForCopy1.y <= blockInfo.height);
     DAWN_ASSERT(texelOffsetForCopy1.z == 0);
 
-    copy.copies[1].alignedOffset = alignedOffsetForCopy1;
     Origin3D textureOffset1 = {origin.x + copySize0.width, origin.y, origin.z};
 
     DAWN_ASSERT(copySize.width > copySize0.width);
@@ -281,11 +315,12 @@
                           copySize.depthOrArrayLayers};
 
     Origin3D bufferOffset1 = texelOffsetForCopy1;
-    copy.copies[1].bufferSize.width = copySize1.width + texelOffsetForCopy1.x;
-    copy.copies[1].bufferSize.height = copySize.height + texelOffsetForCopy1.y;
-    copy.copies[1].bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers;
     ComputeSourceRegionForCopyInfo(&copy.copies[1], direction, bufferOffset1, textureOffset1,
                                    copySize1);
+    Extent3D bufferSize1 = {copySize1.width + texelOffsetForCopy1.x,
+                            copySize.height + texelOffsetForCopy1.y, copySize.depthOrArrayLayers};
+    FillFootprintAndOffsetOfBufferLocation(&copy.copies[1].bufferLocation, alignedOffsetForCopy1,
+                                           bufferSize1, bytesPerRow);
 
     return copy;
 }
@@ -328,8 +363,12 @@
 
     if (bytesPerLayer % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT == 0) {
         copies.copySubresources[1] = copies.copySubresources[0];
-        copies.copySubresources[1].copies[0].alignedOffset += bytesPerLayer;
-        copies.copySubresources[1].copies[1].alignedOffset += bytesPerLayer;
+        uint64_t alignedOffset0 =
+            copies.copySubresources[1].copies[0].GetAlignedOffset() + bytesPerLayer;
+        uint64_t alignedOffset1 =
+            copies.copySubresources[1].copies[1].GetAlignedOffset() + bytesPerLayer;
+        copies.copySubresources[1].copies[0].SetAlignedOffset(alignedOffset0);
+        copies.copySubresources[1].copies[1].SetAlignedOffset(alignedOffset1);
     } else {
         const uint64_t bufferOffsetNextLayer = offset + bytesPerLayer;
         copies.copySubresources[1] =
@@ -439,11 +478,12 @@
     //  row (N + 11)|                 ++|
     //              |-------------------|
 
-    // Copy 0: copy copySize.height - 1 rows
+    // Copy 0: copy copySize0.height - 1 rows
     TextureCopySubresource::CopyInfo& copy0 = copy.copies[i];
     Extent3D copySize0 = copy0.GetCopySize();
     copySize0.height = copySize.height - blockInfo.height;
-    copy0.bufferSize.height = rowsPerImage * blockInfo.height;  // rowsPerImageInTexels
+    uint32_t bufferHeight0 = rowsPerImage * blockInfo.height;  // rowsPerImageInTexels
+    copy0.SetHeightInBufferLocation(bufferHeight0);
     const Origin3D bufferOffset0 = copy0.GetBufferOffset(direction);
     const Origin3D textureOffset0 = copy0.GetTextureOffset(direction);
     ComputeSourceRegionForCopyInfo(&copy0, direction, bufferOffset0, textureOffset0, copySize0);
@@ -452,23 +492,26 @@
     // but the last one.
     TextureCopySubresource::CopyInfo* copy1 = copy.AddCopy();
     *copy1 = copy0;
-    copy1->alignedOffset += 2 * bytesPerRow;
+    uint64_t alignedOffset1 = copy1->GetAlignedOffset() + 2 * bytesPerRow;
+    copy1->SetAlignedOffset(alignedOffset1);
     Origin3D textureOffset1 = textureOffset0;
     Origin3D bufferOffset1 = bufferOffset0;
     textureOffset1.y += copySize.height - blockInfo.height;
-    // Offset two rows from the copy height for the bufferOffset (See the figure above):
+    // Offset two rows from the copy height for bufferOffset1 (See the figure above):
     //   - one for the row we advanced in the buffer: row (N + 4).
     //   - one for the last row we want to copy: row (N + 3) itself.
     bufferOffset1.y = copySize.height - 2 * blockInfo.height;
     Extent3D copySize1 = copySize0;
     copySize1.height = blockInfo.height;
     copySize1.depthOrArrayLayers--;
-    copy1->bufferSize.depthOrArrayLayers--;
+    uint32_t bufferDepth1 = copy1->GetBufferSize().depthOrArrayLayers;
+    bufferDepth1--;
+    copy1->SetDepthInBufferLocation(bufferDepth1);
     ComputeSourceRegionForCopyInfo(copy1, direction, bufferOffset1, textureOffset1, copySize1);
 
     // Copy 2: copy the last row of the last image.
     uint64_t offsetForCopy0 =
-        OffsetToFirstCopiedTexel(blockInfo, bytesPerRow, copy0.alignedOffset, bufferOffset0);
+        OffsetToFirstCopiedTexel(blockInfo, bytesPerRow, copy0.GetAlignedOffset(), bufferOffset0);
     uint64_t offsetForLastRowOfLastImage =
         offsetForCopy0 +
         bytesPerRow * (copySize0.height + rowsPerImage * (copySize.depthOrArrayLayers - 1));
@@ -480,18 +523,18 @@
         bytesPerRow);
 
     TextureCopySubresource::CopyInfo* copy2 = copy.AddCopy();
-    copy2->alignedOffset = alignedOffsetForLastRowOfLastImage;
+    uint64_t alignedOffset2 = alignedOffsetForLastRowOfLastImage;
     Origin3D textureOffset2 = textureOffset1;
     textureOffset2.z = origin.z + copySize.depthOrArrayLayers - 1;
     Extent3D copySize2 = copySize1;
     copySize2.depthOrArrayLayers = 1;
     Origin3D bufferOffset2 = bufferOffset1;
     bufferOffset2 = texelOffsetForLastRowOfLastImage;
-    copy2->bufferSize.width = copy1->bufferSize.width;
     DAWN_ASSERT(copySize2.height == 1);
-    copy2->bufferSize.height = bufferOffset2.y + copySize2.height;
-    copy2->bufferSize.depthOrArrayLayers = 1;
     ComputeSourceRegionForCopyInfo(copy2, direction, bufferOffset2, textureOffset2, copySize2);
+    Extent3D bufferSize2 = {copy1->GetBufferSize().width, bufferOffset2.y + copySize2.height, 1};
+    FillFootprintAndOffsetOfBufferLocation(&copy2->bufferLocation, alignedOffset2, bufferSize2,
+                                           bytesPerRow);
 }
 
 void Recompute3DTextureCopyRegionWithEmptyFirstRowAndOddCopyHeight(
@@ -514,7 +557,8 @@
     TextureCopySubresource::CopyInfo& copy0 = copy.copies[i];
     Extent3D copySize0 = copy0.GetCopySize();
     copySize0.depthOrArrayLayers = 1;
-    copy0.bufferSize.depthOrArrayLayers = 1;
+    const uint32_t kBufferDepth0 = 1u;
+    copy0.SetDepthInBufferLocation(kBufferDepth0);
     const Origin3D bufferOffset0 = copy0.GetBufferOffset(direction);
     const Origin3D textureOffset0 = copy0.GetTextureOffset(direction);
     ComputeSourceRegionForCopyInfo(&copy0, direction, bufferOffset0, textureOffset0, copySize0);
@@ -523,20 +567,21 @@
     TextureCopySubresource::CopyInfo* copy1 = copy.AddCopy();
     *copy1 = copy0;
     DAWN_ASSERT(copySize.height % 2 == 1);
-    copy1->alignedOffset += (copySize.height + 1) * bytesPerRow;
-    DAWN_ASSERT(copy1->alignedOffset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT == 0);
-    // textureOffset.z should add one because the first slice has already been copied in copy0.
+    uint64_t alignedOffset1 = copy0.GetAlignedOffset() + (copySize.height + 1) * bytesPerRow;
+    DAWN_ASSERT(alignedOffset1 % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT == 0);
+    copy1->SetAlignedOffset(alignedOffset1);
+    // textureOffset1.z should add one because the first slice has already been copied in copy0.
     Origin3D textureOffset1 = textureOffset0;
     textureOffset1.z++;
-    // bufferOffset.y should be 0 because we skipped the first depth slice and there is no empty
+    // bufferOffset1.y should be 0 because we skipped the first depth slice and there is no empty
     // row in this copy region.
     Origin3D bufferOffset1 = bufferOffset0;
     bufferOffset1.y = 0;
     Extent3D copySize1 = copySize0;
     copySize1.height = copySize.height;
     copySize1.depthOrArrayLayers = copySize.depthOrArrayLayers - 1;
-    copy1->bufferSize.height = copySize.height;
-    copy1->bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers - 1;
+    copy1->SetHeightInBufferLocation(copySize.height);
+    copy1->SetDepthInBufferLocation(copySize.depthOrArrayLayers - 1);
     ComputeSourceRegionForCopyInfo(copy1, direction, bufferOffset1, textureOffset1, copySize1);
 }
 
@@ -565,8 +610,8 @@
         direction, origin, copySize, blockInfo, offset, bytesPerRow);
 
     DAWN_ASSERT(copySubresource.count <= 2);
-    // If copySize.depth is 1, we can return copySubresource. Because we don't need to extend
-    // the copy region(s) to other depth slice(s).
+    // If copySize.depthOrArrayLayers is 1, we can return copySubresource. Because we don't need to
+    // extend the copy region(s) to other depth slice(s).
     if (copySize.depthOrArrayLayers == 1) {
         return copySubresource;
     }
@@ -578,27 +623,27 @@
     uint32_t originalCopyCount = copySubresource.count;
     for (uint32_t i = 0; i < originalCopyCount; ++i) {
         // There can be one empty row at most in a copy region.
-        DAWN_ASSERT(copySubresource.copies[i].bufferSize.height <=
-                    rowsPerImageInTexels + blockInfo.height);
-        Extent3D& bufferSize = copySubresource.copies[i].bufferSize;
+        uint32_t bufferHeight = copySubresource.copies[i].GetBufferSize().height;
+        DAWN_ASSERT(bufferHeight <= rowsPerImageInTexels + blockInfo.height);
+        DAWN_ASSERT(bufferHeight <= rowsPerImageInTexels + blockInfo.height);
 
-        if (bufferSize.height == rowsPerImageInTexels) {
-            // If the copy region's bufferSize.height equals to rowsPerImageInTexels, we can use
-            // this copy region without any modification.
+        if (bufferHeight == rowsPerImageInTexels) {
+            // If the copy region's bufferHeight equals to rowsPerImageInTexels, we can use this
+            // copy region without any modification.
             continue;
         }
 
-        if (bufferSize.height < rowsPerImageInTexels) {
-            // If we are copying multiple depth slices, we should skip rowsPerImageInTexels rows
-            // for each slice even though we only copy partial rows in each slice sometimes.
-            bufferSize.height = rowsPerImageInTexels;
+        if (bufferHeight < rowsPerImageInTexels) {
+            // If we are copying multiple depth slices, we should skip rowsPerImageInTexels rows for
+            // each slice even though we only copy partial rows in each slice sometimes.
+            copySubresource.copies[i].SetHeightInBufferLocation(rowsPerImageInTexels);
         } else {
-            // bufferSize.height > rowsPerImageInTexels. There is an empty row in this copy
-            // region due to alignment adjustment.
+            // bufferHeight > rowsPerImageInTexels. There is an empty row in this copy region due to
+            // alignment adjustment.
 
             // bytesPerRow is definitely 256, and it is definitely a full copy on height.
-            // Otherwise, bufferSize.height wount be greater than rowsPerImageInTexels and
-            // there won't be an empty row at the beginning of this copy region.
+            // Otherwise, bufferHeight won't be greater than rowsPerImageInTexels and there won't be
+            // an empty row at the beginning of this copy region.
             DAWN_ASSERT(bytesPerRow == D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
             DAWN_ASSERT(copySize.height == rowsPerImageInTexels);
 
diff --git a/src/dawn/native/d3d12/TextureCopySplitter.h b/src/dawn/native/d3d12/TextureCopySplitter.h
index 90c6333..4d0f5b8 100644
--- a/src/dawn/native/d3d12/TextureCopySplitter.h
+++ b/src/dawn/native/d3d12/TextureCopySplitter.h
@@ -45,15 +45,20 @@
     static constexpr unsigned int kMaxTextureCopyRegions = 4;
 
     struct CopyInfo {
-        uint64_t alignedOffset = 0;
         Origin3D destinationOffset;
-        Extent3D bufferSize;
 
         D3D12_BOX sourceRegion;
+        D3D12_TEXTURE_COPY_LOCATION bufferLocation;
 
         Origin3D GetBufferOffset(BufferTextureCopyDirection direction) const;
         Origin3D GetTextureOffset(BufferTextureCopyDirection direction) const;
         Extent3D GetCopySize() const;
+        uint64_t GetAlignedOffset() const;
+        Extent3D GetBufferSize() const;
+
+        void SetAlignedOffset(uint64_t alignedOffset);
+        void SetHeightInBufferLocation(uint32_t bufferHeight);
+        void SetDepthInBufferLocation(uint32_t bufferDepth);
     };
 
     CopyInfo* AddCopy();
diff --git a/src/dawn/native/d3d12/UtilsD3D12.cpp b/src/dawn/native/d3d12/UtilsD3D12.cpp
index 0397bfd..f2b55c5 100644
--- a/src/dawn/native/d3d12/UtilsD3D12.cpp
+++ b/src/dawn/native/d3d12/UtilsD3D12.cpp
@@ -146,26 +146,6 @@
     return copyLocation;
 }
 
-D3D12_TEXTURE_COPY_LOCATION ComputeBufferLocationForCopyTextureRegion(
-    const Texture* texture,
-    ID3D12Resource* bufferResource,
-    const Extent3D& bufferSize,
-    const uint64_t offset,
-    const uint32_t rowPitch,
-    Aspect aspect) {
-    D3D12_TEXTURE_COPY_LOCATION bufferLocation;
-    bufferLocation.pResource = bufferResource;
-    bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
-    bufferLocation.PlacedFootprint.Offset = offset;
-    bufferLocation.PlacedFootprint.Footprint.Format =
-        texture->GetD3D12CopyableSubresourceFormat(aspect);
-    bufferLocation.PlacedFootprint.Footprint.Width = bufferSize.width;
-    bufferLocation.PlacedFootprint.Footprint.Height = bufferSize.height;
-    bufferLocation.PlacedFootprint.Footprint.Depth = bufferSize.depthOrArrayLayers;
-    bufferLocation.PlacedFootprint.Footprint.RowPitch = rowPitch;
-    return bufferLocation;
-}
-
 D3D12_BOX ComputeD3D12BoxFromOffsetAndSize(const Origin3D& offset, const Extent3D& copySize) {
     D3D12_BOX sourceRegion;
     sourceRegion.left = offset.x;
@@ -191,15 +171,14 @@
     const D3D12_TEXTURE_COPY_LOCATION textureLocation =
         ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureLayer, aspect);
 
+    DXGI_FORMAT dxgiFormat = texture->GetD3D12CopyableSubresourceFormat(aspect);
     for (uint32_t i = 0; i < baseCopySplit.count; ++i) {
         const TextureCopySubresource::CopyInfo& info = baseCopySplit.copies[i];
 
-        // TODO(jiawei.shao@intel.com): pre-compute bufferLocation as a member in
-        // TextureCopySubresource::CopyInfo.
-        const uint64_t offsetBytes = info.alignedOffset + baseOffset;
-        const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
-            ComputeBufferLocationForCopyTextureRegion(texture, bufferResource, info.bufferSize,
-                                                      offsetBytes, bufferBytesPerRow, aspect);
+        D3D12_TEXTURE_COPY_LOCATION bufferLocation = info.bufferLocation;
+        bufferLocation.pResource = bufferResource;
+        bufferLocation.PlacedFootprint.Offset += baseOffset;
+        bufferLocation.PlacedFootprint.Footprint.Format = dxgiFormat;
         if (direction == BufferTextureCopyDirection::B2T) {
             commandList->CopyTextureRegion(&textureLocation, info.destinationOffset.x,
                                            info.destinationOffset.y, info.destinationOffset.z,
diff --git a/src/dawn/native/d3d12/UtilsD3D12.h b/src/dawn/native/d3d12/UtilsD3D12.h
index 60a66ef..ec0b7c8 100644
--- a/src/dawn/native/d3d12/UtilsD3D12.h
+++ b/src/dawn/native/d3d12/UtilsD3D12.h
@@ -48,13 +48,6 @@
                                                                  uint32_t layer,
                                                                  Aspect aspect);
 
-D3D12_TEXTURE_COPY_LOCATION ComputeBufferLocationForCopyTextureRegion(
-    const Texture* texture,
-    ID3D12Resource* bufferResource,
-    const Extent3D& bufferSize,
-    const uint64_t offset,
-    const uint32_t rowPitch,
-    Aspect aspect);
 D3D12_BOX ComputeD3D12BoxFromOffsetAndSize(const Origin3D& offset, const Extent3D& copySize);
 
 enum class BufferTextureCopyDirection {
diff --git a/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp b/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp
index 2eded9b..b2c62aa 100644
--- a/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp
+++ b/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp
@@ -59,6 +59,12 @@
     uint32_t rowsPerImage;
 };
 
+Extent3D GetBufferSize(D3D12_TEXTURE_COPY_LOCATION bufferLocation) {
+    return {bufferLocation.PlacedFootprint.Footprint.Width,
+            bufferLocation.PlacedFootprint.Footprint.Height,
+            bufferLocation.PlacedFootprint.Footprint.Depth};
+}
+
 // Check that each copy region fits inside the buffer footprint
 void ValidateFootprints(const TextureSpec& textureSpec,
                         const BufferSpec& bufferSpec,
@@ -69,9 +75,10 @@
         const auto& copy = copySplit.copies[i];
         Extent3D copySize = copy.GetCopySize();
         Origin3D bufferOffset = copy.GetBufferOffset(direction);
-        ASSERT_LE(bufferOffset.x + copySize.width, copy.bufferSize.width);
-        ASSERT_LE(bufferOffset.y + copySize.height, copy.bufferSize.height);
-        ASSERT_LE(bufferOffset.z + copySize.depthOrArrayLayers, copy.bufferSize.depthOrArrayLayers);
+        Extent3D bufferSize = GetBufferSize(copy.bufferLocation);
+        ASSERT_LE(bufferOffset.x + copySize.width, bufferSize.width);
+        ASSERT_LE(bufferOffset.y + copySize.height, bufferSize.height);
+        ASSERT_LE(bufferOffset.z + copySize.depthOrArrayLayers, bufferSize.depthOrArrayLayers);
 
         // If there are multiple layers, 2D texture splitter actually splits each layer
         // independently. See the details in Compute2DTextureCopySplits(). As a result,
@@ -105,10 +112,10 @@
             uint32_t footprintHeightInBlocks = footprintHeight / textureSpec.blockHeight;
 
             uint64_t bufferSizeForFootprint =
-                copy.alignedOffset +
-                utils::RequiredBytesInCopy(bufferSpec.bytesPerRow, copy.bufferSize.height,
+                copy.GetAlignedOffset() +
+                utils::RequiredBytesInCopy(bufferSpec.bytesPerRow, bufferSize.height,
                                            footprintWidthInBlocks, footprintHeightInBlocks,
-                                           copy.bufferSize.depthOrArrayLayers,
+                                           bufferSize.depthOrArrayLayers,
                                            textureSpec.texelBlockSizeInBytes);
 
             // The buffer footprint of each copy region should not exceed the minimum
@@ -122,8 +129,8 @@
 void ValidateOffset(const TextureCopySubresource& copySplit) {
     for (uint32_t i = 0; i < copySplit.count; ++i) {
         ASSERT_TRUE(
-            Align(copySplit.copies[i].alignedOffset, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT) ==
-            copySplit.copies[i].alignedOffset);
+            Align(copySplit.copies[i].GetAlignedOffset(), D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT) ==
+            copySplit.copies[i].GetAlignedOffset());
     }
 }
 
@@ -228,7 +235,7 @@
         uint32_t slicePitchInTexels =
             bytesPerRowInTexels * (bufferSpec.rowsPerImage / textureSpec.blockHeight);
         uint32_t absoluteTexelOffset =
-            copy.alignedOffset / textureSpec.texelBlockSizeInBytes * texelsPerBlock +
+            copy.GetAlignedOffset() / textureSpec.texelBlockSizeInBytes * texelsPerBlock +
             bufferOffset.x / textureSpec.blockWidth * texelsPerBlock +
             bufferOffset.y / textureSpec.blockHeight * bytesPerRowInTexels;
 
@@ -286,6 +293,7 @@
     os << "CopySplit\n";
     for (uint32_t i = 0; i < copySplit.count; ++i) {
         const auto& copy = copySplit.copies[i];
+        Extent3D bufferSize = GetBufferSize(copy.bufferLocation);
         os << "  " << i << ": destinationOffset at (" << copy.destinationOffset.x << ", "
            << copy.destinationOffset.y << ", " << copy.destinationOffset.z << "), sourceRegion ("
            << copy.sourceRegion.left << ", " << copy.sourceRegion.top << ", "
@@ -293,8 +301,8 @@
            << copy.sourceRegion.bottom << ", " << copy.sourceRegion.back << ")\n";
         os << "  " << i << ": sourceOffset at (" << copy.sourceRegion.left << ", "
            << copy.sourceRegion.top << ", " << copy.sourceRegion.front << "), footprint ("
-           << copy.bufferSize.width << ", " << copy.bufferSize.height << ", "
-           << copy.bufferSize.depthOrArrayLayers << ")\n";
+           << bufferSize.width << ", " << bufferSize.height << ", " << bufferSize.depthOrArrayLayers
+           << ")\n";
     }
     return os;
 }