D3D12: Allow relaxed B2T copy pitch and offset alignment on 3D textures This patch implements the buffer-texture copy with relaxed copy pitch and offset alignment (not required to be a multiple of 512 or 256) on 3D textures when `UnrestrictedBufferTextureCopyPitchSupported` is true on the current D3D12 device so that we just need to implement such copy with at most two buffer-texture copies. Bug: chromium:381000081 Test: dawn_end2end_tests Change-Id: Id438da4ca209d742ae3243b53fc08c118fc82f46 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/216875 Reviewed-by: Loko Kung <lokokung@google.com> 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 9c80fc4..016ec8f 100644 --- a/src/dawn/native/d3d12/TextureCopySplitter.cpp +++ b/src/dawn/native/d3d12/TextureCopySplitter.cpp
@@ -718,4 +718,97 @@ return copy; } + +TextureCopySubresource Compute3DTextureCopySubresourceWithRelaxedRowPitchAndOffset( + BufferTextureCopyDirection direction, + Origin3D origin, + Extent3D copySize, + const TexelBlockInfo& blockInfo, + uint64_t offset, + uint32_t bytesPerRow, + uint32_t rowsPerImage) { + TextureCopySubresource copy; + + Origin3D bufferOffset = {0, 0, 0}; + + // You can visualize the data in the buffer (bufferLocation) like the inline comments. + // * copy data is visualized as '+'. + uint32_t depthInCopy1 = copySize.depthOrArrayLayers - 1; + if (depthInCopy1 > 0) { + // `bufferLocation` in the 1st copy (first `depthInCopy1` images, optional): + // + // bufferOffset(0, 0, 0) + // ^ + // | + // |<-------Offset1------>|<-----------RowPitch----------->|----------|------------| + // |----------------------|++++++++++++++++++++++~~~~~~~~~~| | | | | + // |++++++++++++++++++++++~~~~~~~~~~|CopyHeight| | | + // |++++++++++++++++++++++~~~~~~~~~~| | |RowsPerImage| + // |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|----------| | | + // |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | | | + // |---End of 1st image-->|--------------------------------|----------|------------| + // |++++++++++++++++++++++~~~~~~~~~~| | | | + // |++++++++++++++++++++++~~~~~~~~~~| | | | + // |++++++++++++++++++++++~~~~~~~~~~| |RowsPerImage| + // |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | | | + // |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | | | + // |---End of 2nd image-->|--------------------------------|----------|------------| + // |<-----CopyWidth------>| + // + + Origin3D textureOffset1 = origin; + uint32_t offset1 = offset; + + uint32_t rowsPerImage1 = rowsPerImage; + + auto* copyInfo1 = copy.AddCopy(); + Extent3D copySize1 = {copySize.width, copySize.height, depthInCopy1}; + ComputeSourceRegionForCopyInfo(copyInfo1, direction, bufferOffset, textureOffset1, + copySize1); + + Extent3D bufferSize1 = {copySize.width, rowsPerImage1, depthInCopy1}; + + FillFootprintAndOffsetOfBufferLocation(©Info1->bufferLocation, offset1, bufferSize1, + bytesPerRow); + } + + { + // We have to use the 2nd copy because there may not be enough memory to hold + // (RowPitch * RowsPerImage) data for the last image in the buffer. + // + // `bufferLocation` in the 2nd copy (the last image): + // + // bufferOffset (0, 0, 0) + // Begin of the last image + // ^ + // | + // |<-------Offset2------>|<-----------RowPitch----------->|----------| + // |----------------------|++++++++++++++++++++++~~~~~~~~~~| | | + // |++++++++++++++++++++++~~~~~~~~~~|CopyHeight| + // |++++++++++++++++++++++| | | | + // |----------------------|---------|----------| + // |<-----CopyWidth------>| + // ^ + // End of all buffer data + // + DAWN_ASSERT(copySize.depthOrArrayLayers >= 1); + Origin3D textureOffset2 = {origin.x, origin.y, origin.z + depthInCopy1}; + uint32_t offset2 = offset + bytesPerRow * rowsPerImage * depthInCopy1; + uint32_t depthInCopy2 = 1; + uint32_t rowsPerImage2 = copySize.height; + + auto* copyInfo2 = copy.AddCopy(); + Extent3D copySize2 = {copySize.width, copySize.height, depthInCopy2}; + ComputeSourceRegionForCopyInfo(copyInfo2, direction, bufferOffset, textureOffset2, + copySize2); + + Extent3D bufferSize2 = {copySize.width, rowsPerImage2, depthInCopy2}; + + FillFootprintAndOffsetOfBufferLocation(©Info2->bufferLocation, offset2, bufferSize2, + bytesPerRow); + } + + return copy; +} + } // namespace dawn::native::d3d12
diff --git a/src/dawn/native/d3d12/TextureCopySplitter.h b/src/dawn/native/d3d12/TextureCopySplitter.h index 5c6939d..18e9f48 100644 --- a/src/dawn/native/d3d12/TextureCopySplitter.h +++ b/src/dawn/native/d3d12/TextureCopySplitter.h
@@ -128,6 +128,17 @@ uint64_t offset, uint32_t bytesPerRow); +// Compute the `TextureCopySubresource` for one subresource of a 3D texture with relaxed row pitch +// and offset. +TextureCopySubresource Compute3DTextureCopySubresourceWithRelaxedRowPitchAndOffset( + BufferTextureCopyDirection direction, + Origin3D origin, + Extent3D copySize, + const TexelBlockInfo& blockInfo, + uint64_t offset, + uint32_t bytesPerRow, + uint32_t rowsPerImage); + } // namespace dawn::native::d3d12 #endif // SRC_DAWN_NATIVE_D3D12_TEXTURECOPYSPLITTER_H_
diff --git a/src/dawn/native/d3d12/UtilsD3D12.cpp b/src/dawn/native/d3d12/UtilsD3D12.cpp index 50602da..f79591a 100644 --- a/src/dawn/native/d3d12/UtilsD3D12.cpp +++ b/src/dawn/native/d3d12/UtilsD3D12.cpp
@@ -312,11 +312,17 @@ break; case wgpu::TextureDimension::e3D: { - // See comments in Compute3DTextureCopySplits() for more details. - TextureCopySubresource copyRegions = - Compute3DTextureCopySplits(direction, textureCopy.origin, copySize, blockInfo, - offset, bytesPerRow, rowsPerImage); - + TextureCopySubresource copyRegions; + if (useRelaxedRowPitchAndOffset) { + copyRegions = Compute3DTextureCopySubresourceWithRelaxedRowPitchAndOffset( + direction, textureCopy.origin, copySize, blockInfo, offset, bytesPerRow, + rowsPerImage); + } else { + // See comments in Compute3DTextureCopySplits() for more details. + copyRegions = + Compute3DTextureCopySplits(direction, textureCopy.origin, copySize, blockInfo, + offset, bytesPerRow, rowsPerImage); + } RecordBufferTextureCopyFromSplits(direction, commandList, copyRegions, bufferResource, 0, bytesPerRow, texture, textureCopy.mipLevel, 0, textureCopy.aspect);