From aee22d142b961f411635ad94624eb4b00f5f9c3c Mon Sep 17 00:00:00 2001 From: Yunchao He Date: Fri, 18 Jun 2021 07:44:12 +0000 Subject: [PATCH] Implement copies b/w 3D and 2DArray textures on D3D12 Copies between 3D and 2DArray textures need to be done depth/array slice by slice via CopyTextureRegion() API on D3D12 because this API can copy one single subresource every time. However, if both src and dst textures are 3D texture, we can copy all depth slices in one shot, which is a fast path for this copy scenario. Bug: dawn:547 Change-Id: I950ed58319fb0f30dfc8a2de3e57e8a64406f7e4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/55140 Commit-Queue: Jiawei Shao Reviewed-by: Corentin Wallez Reviewed-by: Jiawei Shao --- src/dawn_native/d3d12/CommandBufferD3D12.cpp | 64 ++++++++++++++++---- src/tests/end2end/CopyTests.cpp | 10 --- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index 706ab523f2..38c9a9302a 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -761,34 +761,76 @@ namespace dawn_native { namespace d3d12 { if (CanUseCopyResource(copy->source, copy->destination, copy->copySize)) { commandList->CopyResource(destination->GetD3D12Resource(), source->GetD3D12Resource()); + } else if (source->GetDimension() == wgpu::TextureDimension::e3D && + destination->GetDimension() == wgpu::TextureDimension::e3D) { + for (Aspect aspect : IterateEnumMask(srcRange.aspects)) { + D3D12_TEXTURE_COPY_LOCATION srcLocation = + ComputeTextureCopyLocationForTexture(source, copy->source.mipLevel, + 0, aspect); + D3D12_TEXTURE_COPY_LOCATION dstLocation = + ComputeTextureCopyLocationForTexture( + destination, copy->destination.mipLevel, 0, aspect); + + D3D12_BOX sourceRegion = ComputeD3D12BoxFromOffsetAndSize( + copy->source.origin, copy->copySize); + + commandList->CopyTextureRegion(&dstLocation, copy->destination.origin.x, + copy->destination.origin.y, + copy->destination.origin.z, &srcLocation, + &sourceRegion); + } } else { // TODO(crbug.com/dawn/814): support copying with 1D. - ASSERT(source->GetDimension() == wgpu::TextureDimension::e2D && - destination->GetDimension() == wgpu::TextureDimension::e2D); + ASSERT(source->GetDimension() != wgpu::TextureDimension::e1D && + destination->GetDimension() != wgpu::TextureDimension::e1D); const dawn_native::Extent3D copyExtentOneSlice = { copy->copySize.width, copy->copySize.height, 1u}; for (Aspect aspect : IterateEnumMask(srcRange.aspects)) { - for (uint32_t layer = 0; layer < copy->copySize.depthOrArrayLayers; - ++layer) { + for (uint32_t z = 0; z < copy->copySize.depthOrArrayLayers; ++z) { + uint32_t sourceLayer = 0; + uint32_t sourceZ = 0; + switch (source->GetDimension()) { + case wgpu::TextureDimension::e2D: + sourceLayer = copy->source.origin.z + z; + break; + case wgpu::TextureDimension::e3D: + sourceZ = copy->source.origin.z + z; + break; + case wgpu::TextureDimension::e1D: + UNREACHABLE(); + } + + uint32_t destinationLayer = 0; + uint32_t destinationZ = 0; + switch (destination->GetDimension()) { + case wgpu::TextureDimension::e2D: + destinationLayer = copy->destination.origin.z + z; + break; + case wgpu::TextureDimension::e3D: + destinationZ = copy->destination.origin.z + z; + break; + case wgpu::TextureDimension::e1D: + UNREACHABLE(); + } D3D12_TEXTURE_COPY_LOCATION srcLocation = ComputeTextureCopyLocationForTexture( - source, copy->source.mipLevel, - copy->source.origin.z + layer, aspect); + source, copy->source.mipLevel, sourceLayer, aspect); D3D12_TEXTURE_COPY_LOCATION dstLocation = - ComputeTextureCopyLocationForTexture( - destination, copy->destination.mipLevel, - copy->destination.origin.z + layer, aspect); + ComputeTextureCopyLocationForTexture(destination, + copy->destination.mipLevel, + destinationLayer, aspect); Origin3D sourceOriginInSubresource = copy->source.origin; - sourceOriginInSubresource.z = 0; + sourceOriginInSubresource.z = sourceZ; D3D12_BOX sourceRegion = ComputeD3D12BoxFromOffsetAndSize( sourceOriginInSubresource, copyExtentOneSlice); commandList->CopyTextureRegion( &dstLocation, copy->destination.origin.x, - copy->destination.origin.y, 0, &srcLocation, &sourceRegion); + copy->destination.origin.y, destinationZ, &srcLocation, + &sourceRegion); } } } diff --git a/src/tests/end2end/CopyTests.cpp b/src/tests/end2end/CopyTests.cpp index 6218d1db4c..fd690fed9c 100644 --- a/src/tests/end2end/CopyTests.cpp +++ b/src/tests/end2end/CopyTests.cpp @@ -2135,8 +2135,6 @@ TEST_P(CopyTests_T2T, Texture3DFull) { // Test that copying whole 3D texture to a 2D array in one texture-to-texture-copy works. TEST_P(CopyTests_T2T, Texture3DTo2DArrayFull) { - DAWN_TEST_UNSUPPORTED_IF(IsD3D12()); // TODO(crbug.com/dawn/547): Implement on D3D12. - constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128; constexpr uint32_t kDepth = 6u; @@ -2150,8 +2148,6 @@ TEST_P(CopyTests_T2T, Texture3DTo2DArrayFull) { // Test that copying whole 2D array to a 3D texture in one texture-to-texture-copy works. TEST_P(CopyTests_T2T, Texture2DArrayTo3DFull) { - DAWN_TEST_UNSUPPORTED_IF(IsD3D12()); // TODO(crbug.com/dawn/547): Implement on D3D12. - constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128; constexpr uint32_t kDepth = 6u; @@ -2165,9 +2161,7 @@ TEST_P(CopyTests_T2T, Texture2DArrayTo3DFull) { // Test that copying subregion of a 3D texture in one texture-to-texture-copy works. TEST_P(CopyTests_T2T, Texture3DSubRegion) { - DAWN_TEST_UNSUPPORTED_IF(IsD3D12()); // TODO(crbug.com/dawn/547): Implement on D3D12. DAWN_TEST_UNSUPPORTED_IF(IsANGLE()); // TODO(crbug.com/angleproject/5967) - constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128; constexpr uint32_t kDepth = 6u; @@ -2181,8 +2175,6 @@ TEST_P(CopyTests_T2T, Texture3DSubRegion) { // Test that copying subregion of a 3D texture to a 2D array in one texture-to-texture-copy works. TEST_P(CopyTests_T2T, Texture3DTo2DArraySubRegion) { - DAWN_TEST_UNSUPPORTED_IF(IsD3D12()); // TODO(crbug.com/dawn/547): Implement on D3D12. - constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128; constexpr uint32_t kDepth = 6u; @@ -2197,9 +2189,7 @@ TEST_P(CopyTests_T2T, Texture3DTo2DArraySubRegion) { // Test that copying subregion of a 2D array to a 3D texture to in one texture-to-texture-copy // works. TEST_P(CopyTests_T2T, Texture2DArrayTo3DSubRegion) { - DAWN_TEST_UNSUPPORTED_IF(IsD3D12()); // TODO(crbug.com/dawn/547): Implement on D3D12. DAWN_TEST_UNSUPPORTED_IF(IsANGLE()); // TODO(crbug.com/angleproject/5967) - constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128; constexpr uint32_t kDepth = 6u;