Implement 3D Texture copy for partial depth slices on D3D12

Note that a slice somehow means a subresource on D3D12. There
are mip slice, array slice, and plane/aspect slice in D3D12.
We reuse the term "slice" for multiple depth of a 3D texture,
although one single depth slice of multiple depth slices is
not a separate subresource of a 3D texture (all these depth
slices for one mip are a separte subresource in 3D texture).

For the reason above, this change also renames "slice" to
"layer" in some functions if "slice" is a layer in that
function. Because a layer is definitely a subresource but a
slice may not be (like a single depth slice of a 3D texture).

Bug: dawn:547
Change-Id: I88b8120ef7f73bfc261fc225f4242924da221654
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/49240
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Yunchao He <yunchao.he@intel.com>
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index d09f2ee..9e575a6 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -842,17 +842,17 @@
                             copy->copySize.width, copy->copySize.height, 1u};
 
                         for (Aspect aspect : IterateEnumMask(srcRange.aspects)) {
-                            for (uint32_t slice = 0; slice < copy->copySize.depthOrArrayLayers;
-                                 ++slice) {
+                            for (uint32_t layer = 0; layer < copy->copySize.depthOrArrayLayers;
+                                 ++layer) {
                                 D3D12_TEXTURE_COPY_LOCATION srcLocation =
                                     ComputeTextureCopyLocationForTexture(
                                         source, copy->source.mipLevel,
-                                        copy->source.origin.z + slice, aspect);
+                                        copy->source.origin.z + layer, aspect);
 
                                 D3D12_TEXTURE_COPY_LOCATION dstLocation =
                                     ComputeTextureCopyLocationForTexture(
                                         destination, copy->destination.mipLevel,
-                                        copy->destination.origin.z + slice, aspect);
+                                        copy->destination.origin.z + layer, aspect);
 
                                 Origin3D sourceOriginInSubresource = copy->source.origin;
                                 sourceOriginInSubresource.z = 0;
diff --git a/src/dawn_native/d3d12/UtilsD3D12.cpp b/src/dawn_native/d3d12/UtilsD3D12.cpp
index b190210..451ced1 100644
--- a/src/dawn_native/d3d12/UtilsD3D12.cpp
+++ b/src/dawn_native/d3d12/UtilsD3D12.cpp
@@ -68,12 +68,12 @@
 
     D3D12_TEXTURE_COPY_LOCATION ComputeTextureCopyLocationForTexture(const Texture* texture,
                                                                      uint32_t level,
-                                                                     uint32_t slice,
+                                                                     uint32_t layer,
                                                                      Aspect aspect) {
         D3D12_TEXTURE_COPY_LOCATION copyLocation;
         copyLocation.pResource = texture->GetD3D12Resource();
         copyLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
-        copyLocation.SubresourceIndex = texture->GetSubresourceIndex(level, slice, aspect);
+        copyLocation.SubresourceIndex = texture->GetSubresourceIndex(level, layer, aspect);
 
         return copyLocation;
     }
@@ -149,11 +149,11 @@
                                                        uint64_t bufferBytesPerRow,
                                                        Texture* texture,
                                                        uint32_t textureMiplevel,
-                                                       uint32_t textureSlice,
+                                                       uint32_t textureLayer,
                                                        Aspect aspect) {
         ASSERT(HasOneBit(aspect));
         const D3D12_TEXTURE_COPY_LOCATION textureLocation =
-            ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureSlice, aspect);
+            ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureLayer, aspect);
 
         const uint64_t offsetBytes = baseCopySplit.offset + baseOffset;
 
@@ -201,12 +201,12 @@
         std::array<uint64_t, TextureCopySplits::kMaxTextureCopySplits> bufferOffsetsForNextSlice = {
             {0u, 0u}};
 
-        for (uint32_t copySlice = 0; copySlice < copySize.depthOrArrayLayers; ++copySlice) {
-            const uint32_t splitIndex = copySlice % copySplits.copies2D.size();
+        for (uint32_t copyLayer = 0; copyLayer < copySize.depthOrArrayLayers; ++copyLayer) {
+            const uint32_t splitIndex = copyLayer % copySplits.copies2D.size();
 
             const Texture2DCopySplit& copySplitPerLayerBase = copySplits.copies2D[splitIndex];
             const uint64_t bufferOffsetForNextSlice = bufferOffsetsForNextSlice[splitIndex];
-            const uint32_t copyTextureLayer = copySlice + textureCopy.origin.z;
+            const uint32_t copyTextureLayer = copyLayer + textureCopy.origin.z;
 
             RecordCopyBufferToTextureFromTextureCopySplit(
                 commandContext->GetCommandList(), copySplitPerLayerBase, bufferResource,
@@ -234,7 +234,7 @@
 
         RecordCopyBufferToTextureFromTextureCopySplit(
             commandContext->GetCommandList(), copySplits.copies2D[0], bufferResource, 0,
-            bytesPerRow, texture, textureCopy.mipLevel, textureCopy.origin.z, aspect);
+            bytesPerRow, texture, textureCopy.mipLevel, 0, aspect);
     }
 
     void RecordCopyBufferToTexture(CommandRecordingContext* commandContext,
@@ -267,10 +267,10 @@
                                                        uint64_t bufferBytesPerRow,
                                                        Texture* texture,
                                                        uint32_t textureMiplevel,
-                                                       uint32_t textureSlice,
+                                                       uint32_t textureLayer,
                                                        Aspect aspect) {
         const D3D12_TEXTURE_COPY_LOCATION textureLocation =
-            ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureSlice, aspect);
+            ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureLayer, aspect);
 
         const uint64_t offset = baseCopySplit.offset + baseOffset;
 
@@ -318,12 +318,12 @@
         // that uses copySplits.copies2D[1].
         std::array<uint64_t, TextureCopySplits::kMaxTextureCopySplits> bufferOffsetsForNextSlice = {
             {0u, 0u}};
-        for (uint32_t copySlice = 0; copySlice < copySize.depthOrArrayLayers; ++copySlice) {
-            const uint32_t splitIndex = copySlice % copySplits.copies2D.size();
+        for (uint32_t copyLayer = 0; copyLayer < copySize.depthOrArrayLayers; ++copyLayer) {
+            const uint32_t splitIndex = copyLayer % copySplits.copies2D.size();
 
             const Texture2DCopySplit& copySplitPerLayerBase = copySplits.copies2D[splitIndex];
             const uint64_t bufferOffsetForNextSlice = bufferOffsetsForNextSlice[splitIndex];
-            const uint32_t copyTextureLayer = copySlice + textureCopy.origin.z;
+            const uint32_t copyTextureLayer = copyLayer + textureCopy.origin.z;
 
             RecordCopyTextureToBufferFromTextureCopySplit(
                 commandList, copySplitPerLayerBase, buffer, bufferOffsetForNextSlice,
@@ -349,9 +349,9 @@
             ComputeTextureCopySplits(textureCopy.origin, copySize, blockInfo, bufferCopy.offset,
                                      bufferCopy.bytesPerRow, bufferCopy.rowsPerImage, true);
 
-        RecordCopyTextureToBufferFromTextureCopySplit(
-            commandList, copySplits.copies2D[0], buffer, 0, bufferCopy.bytesPerRow, texture,
-            textureCopy.mipLevel, textureCopy.origin.z, textureCopy.aspect);
+        RecordCopyTextureToBufferFromTextureCopySplit(commandList, copySplits.copies2D[0], buffer,
+                                                      0, bufferCopy.bytesPerRow, texture,
+                                                      textureCopy.mipLevel, 0, textureCopy.aspect);
     }
 
     void RecordCopyTextureToBuffer(ID3D12GraphicsCommandList* commandList,
diff --git a/src/dawn_native/d3d12/UtilsD3D12.h b/src/dawn_native/d3d12/UtilsD3D12.h
index 719a19a..3aef95e 100644
--- a/src/dawn_native/d3d12/UtilsD3D12.h
+++ b/src/dawn_native/d3d12/UtilsD3D12.h
@@ -30,7 +30,7 @@
 
     D3D12_TEXTURE_COPY_LOCATION ComputeTextureCopyLocationForTexture(const Texture* texture,
                                                                      uint32_t level,
-                                                                     uint32_t slice,
+                                                                     uint32_t layer,
                                                                      Aspect aspect);
 
     D3D12_TEXTURE_COPY_LOCATION ComputeBufferLocationForCopyTextureRegion(
@@ -51,7 +51,7 @@
                                                        uint64_t bufferBytesPerRow,
                                                        Texture* texture,
                                                        uint32_t textureMiplevel,
-                                                       uint32_t textureSlice,
+                                                       uint32_t textureLayer,
                                                        Aspect aspect);
 
     void RecordCopyBufferToTexture(CommandRecordingContext* commandContext,
@@ -71,7 +71,7 @@
                                                        uint64_t bufferBytesPerRow,
                                                        Texture* texture,
                                                        uint32_t textureMiplevel,
-                                                       uint32_t textureSlice,
+                                                       uint32_t textureLayer,
                                                        Aspect aspect);
 
     void RecordCopyTextureToBuffer(ID3D12GraphicsCommandList* commandList,
diff --git a/src/tests/end2end/CopyTests.cpp b/src/tests/end2end/CopyTests.cpp
index 59930d5..07cbaab 100644
--- a/src/tests/end2end/CopyTests.cpp
+++ b/src/tests/end2end/CopyTests.cpp
@@ -962,6 +962,26 @@
            wgpu::TextureDimension::e3D);
 }
 
+// Test that copying a range of texture 3D depths in one texture-to-buffer-copy works.
+TEST_P(CopyTests_T2B, Texture3DSubRegion) {
+    // TODO(yunchao.he@intel.com): implement 3D texture copy on Vulkan, Metal, OpenGL and OpenGLES
+    // backend.
+    DAWN_SKIP_TEST_IF(IsVulkan() || IsMetal() || IsOpenGL() || IsOpenGLES());
+
+    constexpr uint32_t kWidth = 256;
+    constexpr uint32_t kHeight = 128;
+    constexpr uint32_t kDepth = 6u;
+    constexpr uint32_t kBaseDepth = 2u;
+    constexpr uint32_t kCopyDepth = 3u;
+
+    TextureSpec textureSpec;
+    textureSpec.copyOrigin = {0, 0, kBaseDepth};
+    textureSpec.textureSize = {kWidth, kHeight, kDepth};
+
+    DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight, kCopyDepth),
+           {kWidth, kHeight, kCopyDepth}, wgpu::TextureDimension::e3D);
+}
+
 // TODO(yunchao.he@intel.com): add T2B tests for 3D textures, like RowPitch,
 // RowsPerImage, buffer offset, partial depth range, non-zero level, etc.
 
@@ -1419,6 +1439,26 @@
            wgpu::TextureDimension::e3D);
 }
 
+// Test that copying a range of texture 3D Depths in one texture-to-buffer-copy works.
+TEST_P(CopyTests_B2T, Texture3DSubRegion) {
+    // TODO(yunchao.he@intel.com): implement 3D texture copy on Vulkan, Metal, OpenGL and OpenGLES
+    // backend.
+    DAWN_SKIP_TEST_IF(IsVulkan() || IsMetal() || IsOpenGL() || IsOpenGLES());
+
+    constexpr uint32_t kWidth = 256;
+    constexpr uint32_t kHeight = 128;
+    constexpr uint32_t kDepth = 6u;
+    constexpr uint32_t kBaseDepth = 2u;
+    constexpr uint32_t kCopyDepth = 3u;
+
+    TextureSpec textureSpec;
+    textureSpec.copyOrigin = {0, 0, kBaseDepth};
+    textureSpec.textureSize = {kWidth, kHeight, kDepth};
+
+    DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight, kCopyDepth),
+           {kWidth, kHeight, kCopyDepth}, wgpu::TextureDimension::e3D);
+}
+
 // TODO(yunchao.he@intel.com): add more tests like RowPitch, RowsPerImage, buffer offset, partial
 // depth range, non-zero level, etc.