From ef6a482fb2297c45cb62a3ff596bdaed04003568 Mon Sep 17 00:00:00 2001 From: Yunchao He Date: Tue, 27 Apr 2021 20:22:17 +0000 Subject: [PATCH] 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 Reviewed-by: Austin Eng Commit-Queue: Yunchao He --- src/dawn_native/d3d12/CommandBufferD3D12.cpp | 8 ++-- src/dawn_native/d3d12/UtilsD3D12.cpp | 32 ++++++++-------- src/dawn_native/d3d12/UtilsD3D12.h | 6 +-- src/tests/end2end/CopyTests.cpp | 40 ++++++++++++++++++++ 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index d09f2ee3be..9e575a68e4 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -842,17 +842,17 @@ namespace dawn_native { namespace d3d12 { 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 b190210078..451ced172e 100644 --- a/src/dawn_native/d3d12/UtilsD3D12.cpp +++ b/src/dawn_native/d3d12/UtilsD3D12.cpp @@ -68,12 +68,12 @@ namespace dawn_native { namespace d3d12 { 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 @@ namespace dawn_native { namespace d3d12 { 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 @@ namespace dawn_native { namespace d3d12 { std::array 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 @@ namespace dawn_native { namespace d3d12 { 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 @@ namespace dawn_native { namespace d3d12 { 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 @@ namespace dawn_native { namespace d3d12 { // that uses copySplits.copies2D[1]. std::array 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 @@ namespace dawn_native { namespace d3d12 { 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 719a19a854..3aef95e45f 100644 --- a/src/dawn_native/d3d12/UtilsD3D12.h +++ b/src/dawn_native/d3d12/UtilsD3D12.h @@ -30,7 +30,7 @@ namespace dawn_native { namespace d3d12 { 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 @@ namespace dawn_native { namespace d3d12 { uint64_t bufferBytesPerRow, Texture* texture, uint32_t textureMiplevel, - uint32_t textureSlice, + uint32_t textureLayer, Aspect aspect); void RecordCopyBufferToTexture(CommandRecordingContext* commandContext, @@ -71,7 +71,7 @@ namespace dawn_native { namespace d3d12 { 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 59930d5c77..07cbaab68c 100644 --- a/src/tests/end2end/CopyTests.cpp +++ b/src/tests/end2end/CopyTests.cpp @@ -962,6 +962,26 @@ TEST_P(CopyTests_T2B, Texture3DFull) { 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 @@ TEST_P(CopyTests_B2T, Texture3DFull) { 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.