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 <jiawei.shao@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
Yunchao He 2021-06-18 07:44:12 +00:00 committed by Dawn LUCI CQ
parent b86e45f8ca
commit aee22d142b
2 changed files with 53 additions and 21 deletions
src
dawn_native/d3d12
tests/end2end

View File

@ -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);
}
}
}

View File

@ -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;