D3D12: Save sourceRegion in TextureCopySubresource::CopyInfo
This patch replaces `copySize` with `sourceRegion` in
`TextureCopySubresource::CopyInfo` so that we can directly use
`sourceRegion` in the D3D12 call `CopyTextureRegion`.
Bug: chromium:42241700
Change-Id: Id905a80847b67176a87780614d47815c569c2aab
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/208596
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
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 dac691c..27c177b 100644
--- a/src/dawn/native/d3d12/TextureCopySplitter.cpp
+++ b/src/dawn/native/d3d12/TextureCopySplitter.cpp
@@ -57,14 +57,64 @@
uint64_t AlignDownForDataPlacement(uint32_t offset) {
return offset & ~static_cast<uint64_t>(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT - 1);
}
+
+void ComputeSourceRegionForCopyInfo(TextureCopySubresource::CopyInfo* copyInfo,
+ BufferTextureCopyDirection direction,
+ Origin3D bufferOffset,
+ Origin3D textureOffset,
+ Extent3D copySize) {
+ switch (direction) {
+ case BufferTextureCopyDirection::B2T:
+ copyInfo->sourceRegion = ComputeD3D12BoxFromOffsetAndSize(bufferOffset, copySize);
+ copyInfo->destinationOffset = textureOffset;
+ break;
+ case BufferTextureCopyDirection::T2B:
+ copyInfo->sourceRegion = ComputeD3D12BoxFromOffsetAndSize(textureOffset, copySize);
+ copyInfo->destinationOffset = bufferOffset;
+ break;
+ default:
+ DAWN_UNREACHABLE();
+ }
+}
+
} // namespace
+Extent3D TextureCopySubresource::CopyInfo::GetCopySize() const {
+ return {sourceRegion.right - sourceRegion.left, sourceRegion.bottom - sourceRegion.top,
+ sourceRegion.back - sourceRegion.front};
+}
+
+Origin3D TextureCopySubresource::CopyInfo::GetBufferOffset(
+ BufferTextureCopyDirection direction) const {
+ switch (direction) {
+ case BufferTextureCopyDirection::B2T:
+ return {sourceRegion.left, sourceRegion.top, sourceRegion.front};
+ case BufferTextureCopyDirection::T2B:
+ return destinationOffset;
+ default:
+ DAWN_UNREACHABLE();
+ }
+}
+
+Origin3D TextureCopySubresource::CopyInfo::GetTextureOffset(
+ BufferTextureCopyDirection direction) const {
+ switch (direction) {
+ case BufferTextureCopyDirection::B2T:
+ return destinationOffset;
+ case BufferTextureCopyDirection::T2B:
+ return {sourceRegion.left, sourceRegion.top, sourceRegion.front};
+ default:
+ DAWN_UNREACHABLE();
+ }
+}
+
TextureCopySubresource::CopyInfo* TextureCopySubresource::AddCopy() {
DAWN_ASSERT(this->count < kMaxTextureCopyRegions);
return &this->copies[this->count++];
}
-TextureCopySubresource Compute2DTextureCopySubresource(Origin3D origin,
+TextureCopySubresource Compute2DTextureCopySubresource(BufferTextureCopyDirection direction,
+ Origin3D origin,
Extent3D copySize,
const TexelBlockInfo& blockInfo,
uint64_t offset,
@@ -83,11 +133,13 @@
copy.count = 1;
copy.copies[0].alignedOffset = alignedOffset;
- copy.copies[0].textureOffset = origin;
- copy.copies[0].copySize = copySize;
- copy.copies[0].bufferOffset = {0, 0, 0};
+ Origin3D textureOffset = origin;
+ Origin3D bufferOffset = {0, 0, 0};
copy.copies[0].bufferSize = copySize;
+ ComputeSourceRegionForCopyInfo(©.copies[0], direction, bufferOffset, textureOffset,
+ copySize);
+
return copy;
}
@@ -149,14 +201,16 @@
copy.count = 1;
copy.copies[0].alignedOffset = alignedOffset;
- copy.copies[0].textureOffset = origin;
- copy.copies[0].copySize = copySize;
- copy.copies[0].bufferOffset = texelOffset;
+ Origin3D textureOffset = origin;
+ Origin3D bufferOffset = texelOffset;
copy.copies[0].bufferSize.width = copySize.width + texelOffset.x;
copy.copies[0].bufferSize.height = copySize.height + texelOffset.y;
copy.copies[0].bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers;
+ ComputeSourceRegionForCopyInfo(©.copies[0], direction, bufferOffset, textureOffset,
+ copySize);
+
return copy;
}
@@ -197,21 +251,21 @@
copy.count = 2;
copy.copies[0].alignedOffset = alignedOffset;
- copy.copies[0].textureOffset = origin;
+ Origin3D textureOffset0 = origin;
DAWN_ASSERT(bytesPerRow > byteOffsetInRowPitch);
uint32_t texelsPerRow = bytesPerRow / blockInfo.byteSize * blockInfo.width;
- copy.copies[0].copySize.width = texelsPerRow - texelOffset.x;
- copy.copies[0].copySize.height = copySize.height;
- copy.copies[0].copySize.depthOrArrayLayers = copySize.depthOrArrayLayers;
+ Extent3D copySize0 = {texelsPerRow - texelOffset.x, copySize.height,
+ copySize.depthOrArrayLayers};
- copy.copies[0].bufferOffset = texelOffset;
+ Origin3D bufferOffset0 = texelOffset;
copy.copies[0].bufferSize.width = texelsPerRow;
copy.copies[0].bufferSize.height = copySize.height + texelOffset.y;
copy.copies[0].bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers;
+ ComputeSourceRegionForCopyInfo(©.copies[0], direction, bufferOffset0, textureOffset0,
+ copySize0);
- uint64_t offsetForCopy1 =
- offset + copy.copies[0].copySize.width / blockInfo.width * blockInfo.byteSize;
+ uint64_t offsetForCopy1 = offset + copySize0.width / blockInfo.width * blockInfo.byteSize;
uint64_t alignedOffsetForCopy1 = AlignDownForDataPlacement(offsetForCopy1);
Origin3D texelOffsetForCopy1 = ComputeTexelOffsets(
blockInfo, static_cast<uint32_t>(offsetForCopy1 - alignedOffsetForCopy1), bytesPerRow);
@@ -220,24 +274,24 @@
DAWN_ASSERT(texelOffsetForCopy1.z == 0);
copy.copies[1].alignedOffset = alignedOffsetForCopy1;
- copy.copies[1].textureOffset.x = origin.x + copy.copies[0].copySize.width;
- copy.copies[1].textureOffset.y = origin.y;
- copy.copies[1].textureOffset.z = origin.z;
+ Origin3D textureOffset1 = {origin.x + copySize0.width, origin.y, origin.z};
- DAWN_ASSERT(copySize.width > copy.copies[0].copySize.width);
- copy.copies[1].copySize.width = copySize.width - copy.copies[0].copySize.width;
- copy.copies[1].copySize.height = copySize.height;
- copy.copies[1].copySize.depthOrArrayLayers = copySize.depthOrArrayLayers;
+ DAWN_ASSERT(copySize.width > copySize0.width);
+ Extent3D copySize1 = {copySize.width - copySize0.width, copySize.height,
+ copySize.depthOrArrayLayers};
- copy.copies[1].bufferOffset = texelOffsetForCopy1;
- copy.copies[1].bufferSize.width = copy.copies[1].copySize.width + texelOffsetForCopy1.x;
+ Origin3D bufferOffset1 = texelOffsetForCopy1;
+ copy.copies[1].bufferSize.width = copySize1.width + texelOffsetForCopy1.x;
copy.copies[1].bufferSize.height = copySize.height + texelOffsetForCopy1.y;
copy.copies[1].bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers;
+ ComputeSourceRegionForCopyInfo(©.copies[1], direction, bufferOffset1, textureOffset1,
+ copySize1);
return copy;
}
-TextureCopySplits Compute2DTextureCopySplits(Origin3D origin,
+TextureCopySplits Compute2DTextureCopySplits(BufferTextureCopyDirection direction,
+ Origin3D origin,
Extent3D copySize,
const TexelBlockInfo& blockInfo,
uint64_t offset,
@@ -264,7 +318,7 @@
copyFirstLayerOrigin.z = 0;
copies.copySubresources[0] = Compute2DTextureCopySubresource(
- copyFirstLayerOrigin, copyOneLayerSize, blockInfo, offset, bytesPerRow);
+ direction, copyFirstLayerOrigin, copyOneLayerSize, blockInfo, offset, bytesPerRow);
// When the copy only refers one texture 2D array layer,
// copies.copySubresources[1] will never be used so we can safely early return here.
@@ -278,20 +332,23 @@
copies.copySubresources[1].copies[1].alignedOffset += bytesPerLayer;
} else {
const uint64_t bufferOffsetNextLayer = offset + bytesPerLayer;
- copies.copySubresources[1] = Compute2DTextureCopySubresource(
- copyFirstLayerOrigin, copyOneLayerSize, blockInfo, bufferOffsetNextLayer, bytesPerRow);
+ copies.copySubresources[1] =
+ Compute2DTextureCopySubresource(direction, copyFirstLayerOrigin, copyOneLayerSize,
+ blockInfo, bufferOffsetNextLayer, bytesPerRow);
}
return copies;
}
-void Recompute3DTextureCopyRegionWithEmptyFirstRowAndEvenCopyHeight(Origin3D origin,
- Extent3D copySize,
- const TexelBlockInfo& blockInfo,
- uint32_t bytesPerRow,
- uint32_t rowsPerImage,
- TextureCopySubresource& copy,
- uint32_t i) {
+void Recompute3DTextureCopyRegionWithEmptyFirstRowAndEvenCopyHeight(
+ BufferTextureCopyDirection direction,
+ Origin3D origin,
+ Extent3D copySize,
+ const TexelBlockInfo& blockInfo,
+ uint32_t bytesPerRow,
+ uint32_t rowsPerImage,
+ TextureCopySubresource& copy,
+ uint32_t i) {
// Let's assign data and show why copy region generated by ComputeTextureCopySubresource
// is incorrect if there is an empty row at the beginning of the copy block.
// Assuming that bytesPerRow is 256 and we are doing a B2T copy, and copy size is {width: 2,
@@ -384,29 +441,37 @@
// Copy 0: copy copySize.height - 1 rows
TextureCopySubresource::CopyInfo& copy0 = copy.copies[i];
- copy0.copySize.height = copySize.height - blockInfo.height;
+ Extent3D copySize0 = copy0.GetCopySize();
+ copySize0.height = copySize.height - blockInfo.height;
copy0.bufferSize.height = rowsPerImage * blockInfo.height; // rowsPerImageInTexels
+ const Origin3D bufferOffset0 = copy0.GetBufferOffset(direction);
+ const Origin3D textureOffset0 = copy0.GetTextureOffset(direction);
+ ComputeSourceRegionForCopyInfo(©0, direction, bufferOffset0, textureOffset0, copySize0);
// Copy 1: move down 2 rows and copy the last row on image 0, and expand to all depth slices
// but the last one.
TextureCopySubresource::CopyInfo* copy1 = copy.AddCopy();
*copy1 = copy0;
copy1->alignedOffset += 2 * bytesPerRow;
- copy1->textureOffset.y += copySize.height - blockInfo.height;
+ Origin3D textureOffset1 = textureOffset0;
+ Origin3D bufferOffset1 = bufferOffset0;
+ textureOffset1.y += copySize.height - blockInfo.height;
// Offset two rows from the copy height for the bufferOffset (See the figure above):
// - one for the row we advanced in the buffer: row (N + 4).
// - one for the last row we want to copy: row (N + 3) itself.
- copy1->bufferOffset.y = copySize.height - 2 * blockInfo.height;
- copy1->copySize.height = blockInfo.height;
- copy1->copySize.depthOrArrayLayers--;
+ bufferOffset1.y = copySize.height - 2 * blockInfo.height;
+ Extent3D copySize1 = copySize0;
+ copySize1.height = blockInfo.height;
+ copySize1.depthOrArrayLayers--;
copy1->bufferSize.depthOrArrayLayers--;
+ ComputeSourceRegionForCopyInfo(copy1, direction, bufferOffset1, textureOffset1, copySize1);
// Copy 2: copy the last row of the last image.
uint64_t offsetForCopy0 =
- OffsetToFirstCopiedTexel(blockInfo, bytesPerRow, copy0.alignedOffset, copy0.bufferOffset);
+ OffsetToFirstCopiedTexel(blockInfo, bytesPerRow, copy0.alignedOffset, bufferOffset0);
uint64_t offsetForLastRowOfLastImage =
offsetForCopy0 +
- bytesPerRow * (copy0.copySize.height + rowsPerImage * (copySize.depthOrArrayLayers - 1));
+ bytesPerRow * (copySize0.height + rowsPerImage * (copySize.depthOrArrayLayers - 1));
uint64_t alignedOffsetForLastRowOfLastImage =
AlignDownForDataPlacement(offsetForLastRowOfLastImage);
Origin3D texelOffsetForLastRowOfLastImage = ComputeTexelOffsets(
@@ -416,21 +481,25 @@
TextureCopySubresource::CopyInfo* copy2 = copy.AddCopy();
copy2->alignedOffset = alignedOffsetForLastRowOfLastImage;
- copy2->textureOffset = copy1->textureOffset;
- copy2->textureOffset.z = origin.z + copySize.depthOrArrayLayers - 1;
- copy2->copySize = copy1->copySize;
- copy2->copySize.depthOrArrayLayers = 1;
- copy2->bufferOffset = texelOffsetForLastRowOfLastImage;
+ Origin3D textureOffset2 = textureOffset1;
+ textureOffset2.z = origin.z + copySize.depthOrArrayLayers - 1;
+ Extent3D copySize2 = copySize1;
+ copySize2.depthOrArrayLayers = 1;
+ Origin3D bufferOffset2 = bufferOffset1;
+ bufferOffset2 = texelOffsetForLastRowOfLastImage;
copy2->bufferSize.width = copy1->bufferSize.width;
- DAWN_ASSERT(copy2->copySize.height == 1);
- copy2->bufferSize.height = copy2->bufferOffset.y + copy2->copySize.height;
+ DAWN_ASSERT(copySize2.height == 1);
+ copy2->bufferSize.height = bufferOffset2.y + copySize2.height;
copy2->bufferSize.depthOrArrayLayers = 1;
+ ComputeSourceRegionForCopyInfo(copy2, direction, bufferOffset2, textureOffset2, copySize2);
}
-void Recompute3DTextureCopyRegionWithEmptyFirstRowAndOddCopyHeight(Extent3D copySize,
- uint32_t bytesPerRow,
- TextureCopySubresource& copy,
- uint32_t i) {
+void Recompute3DTextureCopyRegionWithEmptyFirstRowAndOddCopyHeight(
+ BufferTextureCopyDirection direction,
+ Extent3D copySize,
+ uint32_t bytesPerRow,
+ TextureCopySubresource& copy,
+ uint32_t i) {
// Read the comments of Recompute3DTextureCopyRegionWithEmptyFirstRowAndEvenCopyHeight() for
// the reason why it is incorrect if we simply extend the copy region to all depth slices
// when there is an empty first row at the copy region.
@@ -443,8 +512,12 @@
// Copy 0: copy the first depth slice (image 0)
TextureCopySubresource::CopyInfo& copy0 = copy.copies[i];
- copy0.copySize.depthOrArrayLayers = 1;
+ Extent3D copySize0 = copy0.GetCopySize();
+ copySize0.depthOrArrayLayers = 1;
copy0.bufferSize.depthOrArrayLayers = 1;
+ const Origin3D bufferOffset0 = copy0.GetBufferOffset(direction);
+ const Origin3D textureOffset0 = copy0.GetTextureOffset(direction);
+ ComputeSourceRegionForCopyInfo(©0, direction, bufferOffset0, textureOffset0, copySize0);
// Copy 1: copy the rest depth slices in one shot
TextureCopySubresource::CopyInfo* copy1 = copy.AddCopy();
@@ -453,17 +526,22 @@
copy1->alignedOffset += (copySize.height + 1) * bytesPerRow;
DAWN_ASSERT(copy1->alignedOffset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT == 0);
// textureOffset.z should add one because the first slice has already been copied in copy0.
- copy1->textureOffset.z++;
+ Origin3D textureOffset1 = textureOffset0;
+ textureOffset1.z++;
// bufferOffset.y should be 0 because we skipped the first depth slice and there is no empty
// row in this copy region.
- copy1->bufferOffset.y = 0;
- copy1->copySize.height = copySize.height;
- copy1->copySize.depthOrArrayLayers = copySize.depthOrArrayLayers - 1;
+ Origin3D bufferOffset1 = bufferOffset0;
+ bufferOffset1.y = 0;
+ Extent3D copySize1 = copySize0;
+ copySize1.height = copySize.height;
+ copySize1.depthOrArrayLayers = copySize.depthOrArrayLayers - 1;
copy1->bufferSize.height = copySize.height;
copy1->bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers - 1;
+ ComputeSourceRegionForCopyInfo(copy1, direction, bufferOffset1, textureOffset1, copySize1);
}
-TextureCopySubresource Compute3DTextureCopySplits(Origin3D origin,
+TextureCopySubresource Compute3DTextureCopySplits(BufferTextureCopyDirection direction,
+ Origin3D origin,
Extent3D copySize,
const TexelBlockInfo& blockInfo,
uint64_t offset,
@@ -483,8 +561,8 @@
// Call Compute2DTextureCopySubresource and get copy regions. This function has already
// forwarded "copySize.depthOrArrayLayers" to all depth slices.
- TextureCopySubresource copySubresource =
- Compute2DTextureCopySubresource(origin, copySize, blockInfo, offset, bytesPerRow);
+ TextureCopySubresource copySubresource = Compute2DTextureCopySubresource(
+ direction, origin, copySize, blockInfo, offset, bytesPerRow);
DAWN_ASSERT(copySubresource.count <= 2);
// If copySize.depth is 1, we can return copySubresource. Because we don't need to extend
@@ -531,7 +609,8 @@
// an empty row at each depth slice. We need a totally different approach to
// split the copy region.
Recompute3DTextureCopyRegionWithEmptyFirstRowAndEvenCopyHeight(
- origin, copySize, blockInfo, bytesPerRow, rowsPerImage, copySubresource, i);
+ direction, origin, copySize, blockInfo, bytesPerRow, rowsPerImage,
+ copySubresource, i);
} else {
// If copySize.height is odd and there is an empty row at the beginning of the
// first slice of the copy region, we can split the copy region into two copies:
@@ -539,8 +618,8 @@
// offset of slice 1 is aligned to D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT (512)
// without an empty row. This is an easier case relative to cases with even copy
// height.
- Recompute3DTextureCopyRegionWithEmptyFirstRowAndOddCopyHeight(copySize, bytesPerRow,
- copySubresource, i);
+ Recompute3DTextureCopyRegionWithEmptyFirstRowAndOddCopyHeight(
+ direction, copySize, bytesPerRow, copySubresource, i);
}
}
}
diff --git a/src/dawn/native/d3d12/TextureCopySplitter.h b/src/dawn/native/d3d12/TextureCopySplitter.h
index e73225c..90c6333 100644
--- a/src/dawn/native/d3d12/TextureCopySplitter.h
+++ b/src/dawn/native/d3d12/TextureCopySplitter.h
@@ -30,6 +30,7 @@
#include <array>
+#include "dawn/native/d3d12/UtilsD3D12.h"
#include "dawn/native/dawn_platform.h"
namespace dawn::native {
@@ -45,11 +46,14 @@
struct CopyInfo {
uint64_t alignedOffset = 0;
- Origin3D textureOffset;
- Origin3D bufferOffset;
+ Origin3D destinationOffset;
Extent3D bufferSize;
- Extent3D copySize;
+ D3D12_BOX sourceRegion;
+
+ Origin3D GetBufferOffset(BufferTextureCopyDirection direction) const;
+ Origin3D GetTextureOffset(BufferTextureCopyDirection direction) const;
+ Extent3D GetCopySize() const;
};
CopyInfo* AddCopy();
@@ -86,20 +90,23 @@
// - Copy region(s) combined should exactly be equivalent to the texture region to be copied.
// - Every pixel accessed by every copy region should not be out of the bound of the copied
// texture and buffer.
-TextureCopySubresource Compute2DTextureCopySubresource(Origin3D origin,
+TextureCopySubresource Compute2DTextureCopySubresource(BufferTextureCopyDirection direction,
+ Origin3D origin,
Extent3D copySize,
const TexelBlockInfo& blockInfo,
uint64_t offset,
uint32_t bytesPerRow);
-TextureCopySplits Compute2DTextureCopySplits(Origin3D origin,
+TextureCopySplits Compute2DTextureCopySplits(BufferTextureCopyDirection direction,
+ Origin3D origin,
Extent3D copySize,
const TexelBlockInfo& blockInfo,
uint64_t offset,
uint32_t bytesPerRow,
uint32_t rowsPerImage);
-TextureCopySubresource Compute3DTextureCopySplits(Origin3D origin,
+TextureCopySubresource Compute3DTextureCopySplits(BufferTextureCopyDirection direction,
+ Origin3D origin,
Extent3D copySize,
const TexelBlockInfo& blockInfo,
uint64_t offset,
diff --git a/src/dawn/native/d3d12/UtilsD3D12.cpp b/src/dawn/native/d3d12/UtilsD3D12.cpp
index 613bdca..0397bfd 100644
--- a/src/dawn/native/d3d12/UtilsD3D12.cpp
+++ b/src/dawn/native/d3d12/UtilsD3D12.cpp
@@ -38,6 +38,7 @@
#include "dawn/native/d3d12/BufferD3D12.h"
#include "dawn/native/d3d12/CommandRecordingContext.h"
#include "dawn/native/d3d12/DeviceD3D12.h"
+#include "dawn/native/d3d12/TextureCopySplitter.h"
namespace dawn::native::d3d12 {
@@ -193,27 +194,21 @@
for (uint32_t i = 0; i < baseCopySplit.count; ++i) {
const TextureCopySubresource::CopyInfo& info = baseCopySplit.copies[i];
- // TODO(jiawei.shao@intel.com): pre-compute bufferLocation and sourceRegion as
- // members in TextureCopySubresource::CopyInfo.
+ // TODO(jiawei.shao@intel.com): pre-compute bufferLocation as a member in
+ // TextureCopySubresource::CopyInfo.
const uint64_t offsetBytes = info.alignedOffset + baseOffset;
const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(texture, bufferResource, info.bufferSize,
offsetBytes, bufferBytesPerRow, aspect);
if (direction == BufferTextureCopyDirection::B2T) {
- const D3D12_BOX sourceRegion =
- ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
-
- commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
- info.textureOffset.y, info.textureOffset.z,
- &bufferLocation, &sourceRegion);
+ commandList->CopyTextureRegion(&textureLocation, info.destinationOffset.x,
+ info.destinationOffset.y, info.destinationOffset.z,
+ &bufferLocation, &info.sourceRegion);
} else {
DAWN_ASSERT(direction == BufferTextureCopyDirection::T2B);
- const D3D12_BOX sourceRegion =
- ComputeD3D12BoxFromOffsetAndSize(info.textureOffset, info.copySize);
-
- commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
- info.bufferOffset.y, info.bufferOffset.z,
- &textureLocation, &sourceRegion);
+ commandList->CopyTextureRegion(&bufferLocation, info.destinationOffset.x,
+ info.destinationOffset.y, info.destinationOffset.z,
+ &textureLocation, &info.sourceRegion);
}
}
}
@@ -229,7 +224,7 @@
const Extent3D& copySize) {
// See comments in Compute2DTextureCopySplits() for more details.
const TextureCopySplits copySplits = Compute2DTextureCopySplits(
- textureCopy.origin, copySize, blockInfo, offset, bytesPerRow, rowsPerImage);
+ direction, textureCopy.origin, copySize, blockInfo, offset, bytesPerRow, rowsPerImage);
const uint64_t bytesPerLayer = bytesPerRow * rowsPerImage;
@@ -283,7 +278,7 @@
DAWN_ASSERT(texture->GetArrayLayers() == 1);
TextureCopySubresource copyRegions = Compute2DTextureCopySubresource(
- textureCopy.origin, copySize, blockInfo, offset, bytesPerRow);
+ direction, textureCopy.origin, copySize, blockInfo, offset, bytesPerRow);
RecordBufferTextureCopyFromSplits(direction, commandList, copyRegions, bufferResource,
0, bytesPerRow, texture, textureCopy.mipLevel, 0,
textureCopy.aspect);
@@ -300,8 +295,9 @@
case wgpu::TextureDimension::e3D: {
// See comments in Compute3DTextureCopySplits() for more details.
- TextureCopySubresource copyRegions = Compute3DTextureCopySplits(
- textureCopy.origin, copySize, blockInfo, offset, bytesPerRow, rowsPerImage);
+ TextureCopySubresource copyRegions =
+ Compute3DTextureCopySplits(direction, textureCopy.origin, copySize, blockInfo,
+ offset, bytesPerRow, rowsPerImage);
RecordBufferTextureCopyFromSplits(direction, commandList, copyRegions, bufferResource,
0, bytesPerRow, texture, textureCopy.mipLevel, 0,
diff --git a/src/dawn/native/d3d12/UtilsD3D12.h b/src/dawn/native/d3d12/UtilsD3D12.h
index e73c4a7..60a66ef 100644
--- a/src/dawn/native/d3d12/UtilsD3D12.h
+++ b/src/dawn/native/d3d12/UtilsD3D12.h
@@ -33,7 +33,6 @@
#include "dawn/native/Commands.h"
#include "dawn/native/d3d/UtilsD3D.h"
#include "dawn/native/d3d12/BufferD3D12.h"
-#include "dawn/native/d3d12/TextureCopySplitter.h"
#include "dawn/native/d3d12/TextureD3D12.h"
#include "dawn/native/d3d12/d3d12_platform.h"
#include "dawn/native/dawn_platform.h"
diff --git a/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp b/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp
index 7956e42..2eded9b 100644
--- a/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp
+++ b/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp
@@ -32,6 +32,7 @@
#include "dawn/common/Math.h"
#include "dawn/native/Format.h"
#include "dawn/native/d3d12/TextureCopySplitter.h"
+#include "dawn/native/d3d12/UtilsD3D12.h"
#include "dawn/native/d3d12/d3d12_platform.h"
#include "dawn/utils/TestUtils.h"
#include "dawn/webgpu_cpp_print.h"
@@ -61,14 +62,16 @@
// Check that each copy region fits inside the buffer footprint
void ValidateFootprints(const TextureSpec& textureSpec,
const BufferSpec& bufferSpec,
+ BufferTextureCopyDirection direction,
const TextureCopySubresource& copySplit,
wgpu::TextureDimension dimension) {
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
- ASSERT_LE(copy.bufferOffset.x + copy.copySize.width, copy.bufferSize.width);
- ASSERT_LE(copy.bufferOffset.y + copy.copySize.height, copy.bufferSize.height);
- ASSERT_LE(copy.bufferOffset.z + copy.copySize.depthOrArrayLayers,
- copy.bufferSize.depthOrArrayLayers);
+ Extent3D copySize = copy.GetCopySize();
+ Origin3D bufferOffset = copy.GetBufferOffset(direction);
+ ASSERT_LE(bufferOffset.x + copySize.width, copy.bufferSize.width);
+ ASSERT_LE(bufferOffset.y + copySize.height, copy.bufferSize.height);
+ ASSERT_LE(bufferOffset.z + copySize.depthOrArrayLayers, copy.bufferSize.depthOrArrayLayers);
// If there are multiple layers, 2D texture splitter actually splits each layer
// independently. See the details in Compute2DTextureCopySplits(). As a result,
@@ -89,15 +92,15 @@
// The last pixel (buffer footprint) of each copy region depends on its
// bufferOffset and copySize. It is not the last pixel where the bufferSize
// ends.
- ASSERT_EQ(copy.bufferOffset.x % textureSpec.blockWidth, 0u);
- ASSERT_EQ(copy.copySize.width % textureSpec.blockWidth, 0u);
- uint32_t footprintWidth = copy.bufferOffset.x + copy.copySize.width;
+ ASSERT_EQ(bufferOffset.x % textureSpec.blockWidth, 0u);
+ ASSERT_EQ(copySize.width % textureSpec.blockWidth, 0u);
+ uint32_t footprintWidth = bufferOffset.x + copySize.width;
ASSERT_EQ(footprintWidth % textureSpec.blockWidth, 0u);
uint32_t footprintWidthInBlocks = footprintWidth / textureSpec.blockWidth;
- ASSERT_EQ(copy.bufferOffset.y % textureSpec.blockHeight, 0u);
- ASSERT_EQ(copy.copySize.height % textureSpec.blockHeight, 0u);
- uint32_t footprintHeight = copy.bufferOffset.y + copy.copySize.height;
+ ASSERT_EQ(bufferOffset.y % textureSpec.blockHeight, 0u);
+ ASSERT_EQ(copySize.height % textureSpec.blockHeight, 0u);
+ uint32_t footprintHeight = bufferOffset.y + copySize.height;
ASSERT_EQ(footprintHeight % textureSpec.blockHeight, 0u);
uint32_t footprintHeightInBlocks = footprintHeight / textureSpec.blockHeight;
@@ -129,24 +132,29 @@
}
// Check that no pair of copy regions intersect each other
-void ValidateDisjoint(const TextureCopySubresource& copySplit) {
+void ValidateDisjoint(const TextureCopySubresource& copySplit,
+ BufferTextureCopyDirection direction) {
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& a = copySplit.copies[i];
+ Extent3D copySizeA = a.GetCopySize();
+ Origin3D textureOffsetA = a.GetTextureOffset(direction);
for (uint32_t j = i + 1; j < copySplit.count; ++j) {
const auto& b = copySplit.copies[j];
// If textureOffset.x is 0, and copySize.width is 2, we are copying pixel 0 and
// 1. We never touch pixel 2 on x-axis. So the copied range on x-axis should be
// [textureOffset.x, textureOffset.x + copySize.width - 1] and both ends are
// included.
+ Extent3D copySizeB = b.GetCopySize();
+ Origin3D textureOffsetB = b.GetTextureOffset(direction);
bool overlapX =
- InclusiveRangesOverlap(a.textureOffset.x, a.textureOffset.x + a.copySize.width - 1,
- b.textureOffset.x, b.textureOffset.x + b.copySize.width - 1);
- bool overlapY = InclusiveRangesOverlap(
- a.textureOffset.y, a.textureOffset.y + a.copySize.height - 1, b.textureOffset.y,
- b.textureOffset.y + b.copySize.height - 1);
+ InclusiveRangesOverlap(textureOffsetA.x, textureOffsetA.x + copySizeA.width - 1,
+ textureOffsetB.x, textureOffsetB.x + copySizeB.width - 1);
+ bool overlapY =
+ InclusiveRangesOverlap(textureOffsetA.y, textureOffsetA.y + copySizeA.height - 1,
+ textureOffsetB.y, textureOffsetB.y + copySizeB.height - 1);
bool overlapZ = InclusiveRangesOverlap(
- a.textureOffset.z, a.textureOffset.z + a.copySize.depthOrArrayLayers - 1,
- b.textureOffset.z, b.textureOffset.z + b.copySize.depthOrArrayLayers - 1);
+ textureOffsetA.z, textureOffsetA.z + copySizeA.depthOrArrayLayers - 1,
+ textureOffsetB.z, textureOffsetB.z + copySizeB.depthOrArrayLayers - 1);
ASSERT_TRUE(!overlapX || !overlapY || !overlapZ);
}
}
@@ -154,25 +162,29 @@
// Check that the union of the copy regions exactly covers the texture region
void ValidateTextureBounds(const TextureSpec& textureSpec,
+ BufferTextureCopyDirection direction,
const TextureCopySubresource& copySplit) {
ASSERT_GT(copySplit.count, 0u);
- uint32_t minX = copySplit.copies[0].textureOffset.x;
- uint32_t minY = copySplit.copies[0].textureOffset.y;
- uint32_t minZ = copySplit.copies[0].textureOffset.z;
- uint32_t maxX = copySplit.copies[0].textureOffset.x + copySplit.copies[0].copySize.width;
- uint32_t maxY = copySplit.copies[0].textureOffset.y + copySplit.copies[0].copySize.height;
- uint32_t maxZ =
- copySplit.copies[0].textureOffset.z + copySplit.copies[0].copySize.depthOrArrayLayers;
+ Extent3D copySize0 = copySplit.copies[0].GetCopySize();
+ Origin3D textureOffset0 = copySplit.copies[0].GetTextureOffset(direction);
+ uint32_t minX = textureOffset0.x;
+ uint32_t minY = textureOffset0.y;
+ uint32_t minZ = textureOffset0.z;
+ uint32_t maxX = textureOffset0.x + copySize0.width;
+ uint32_t maxY = textureOffset0.y + copySize0.height;
+ uint32_t maxZ = textureOffset0.z + copySize0.depthOrArrayLayers;
for (uint32_t i = 1; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
- minX = std::min(minX, copy.textureOffset.x);
- minY = std::min(minY, copy.textureOffset.y);
- minZ = std::min(minZ, copy.textureOffset.z);
- maxX = std::max(maxX, copy.textureOffset.x + copy.copySize.width);
- maxY = std::max(maxY, copy.textureOffset.y + copy.copySize.height);
- maxZ = std::max(maxZ, copy.textureOffset.z + copy.copySize.depthOrArrayLayers);
+ Origin3D textureOffset = copy.GetTextureOffset(direction);
+ minX = std::min(minX, textureOffset.x);
+ minY = std::min(minY, textureOffset.y);
+ minZ = std::min(minZ, textureOffset.z);
+ Extent3D copySize = copy.GetCopySize();
+ maxX = std::max(maxX, textureOffset.x + copySize.width);
+ maxY = std::max(maxY, textureOffset.y + copySize.height);
+ maxZ = std::max(maxZ, textureOffset.z + copySize.depthOrArrayLayers);
}
ASSERT_EQ(minX, textureSpec.x);
@@ -189,8 +201,8 @@
uint32_t count = 0;
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
- uint32_t copiedPixels =
- copy.copySize.width * copy.copySize.height * copy.copySize.depthOrArrayLayers;
+ Extent3D copySize = copy.GetCopySize();
+ uint32_t copiedPixels = copySize.width * copySize.height * copySize.depthOrArrayLayers;
ASSERT_GT(copiedPixels, 0u);
count += copiedPixels;
}
@@ -200,6 +212,7 @@
// Check that every buffer offset is at the correct pixel location
void ValidateBufferOffset(const TextureSpec& textureSpec,
const BufferSpec& bufferSpec,
+ BufferTextureCopyDirection direction,
const TextureCopySubresource& copySplit,
wgpu::TextureDimension dimension) {
ASSERT_GT(copySplit.count, 0u);
@@ -207,6 +220,8 @@
uint32_t texelsPerBlock = textureSpec.blockWidth * textureSpec.blockHeight;
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
+ Origin3D bufferOffset = copy.GetBufferOffset(direction);
+ Origin3D textureOffset = copy.GetTextureOffset(direction);
uint32_t bytesPerRowInTexels =
bufferSpec.bytesPerRow / textureSpec.texelBlockSizeInBytes * texelsPerBlock;
@@ -214,16 +229,16 @@
bytesPerRowInTexels * (bufferSpec.rowsPerImage / textureSpec.blockHeight);
uint32_t absoluteTexelOffset =
copy.alignedOffset / textureSpec.texelBlockSizeInBytes * texelsPerBlock +
- copy.bufferOffset.x / textureSpec.blockWidth * texelsPerBlock +
- copy.bufferOffset.y / textureSpec.blockHeight * bytesPerRowInTexels;
+ bufferOffset.x / textureSpec.blockWidth * texelsPerBlock +
+ bufferOffset.y / textureSpec.blockHeight * bytesPerRowInTexels;
// There is one empty row at most in a 2D copy region. However, it is not true for
// a 3D texture copy region when we are copying the last row of each slice. We may
// need to offset a lot rows and copy.bufferOffset.y may be big.
if (dimension == wgpu::TextureDimension::e2D) {
- ASSERT_LE(copy.bufferOffset.y, textureSpec.blockHeight);
+ ASSERT_LE(bufferOffset.y, textureSpec.blockHeight);
}
- ASSERT_EQ(copy.bufferOffset.z, 0u);
+ ASSERT_EQ(bufferOffset.z, 0u);
ASSERT_GE(absoluteTexelOffset,
bufferSpec.offset / textureSpec.texelBlockSizeInBytes * texelsPerBlock);
@@ -235,22 +250,23 @@
uint32_t y = (relativeTexelOffset % slicePitchInTexels) / bytesPerRowInTexels;
uint32_t x = relativeTexelOffset % bytesPerRowInTexels;
- ASSERT_EQ(copy.textureOffset.x - textureSpec.x, x);
- ASSERT_EQ(copy.textureOffset.y - textureSpec.y, y);
- ASSERT_EQ(copy.textureOffset.z - textureSpec.z, z);
+ ASSERT_EQ(textureOffset.x - textureSpec.x, x);
+ ASSERT_EQ(textureOffset.y - textureSpec.y, y);
+ ASSERT_EQ(textureOffset.z - textureSpec.z, z);
}
}
void ValidateCopySplit(const TextureSpec& textureSpec,
const BufferSpec& bufferSpec,
+ BufferTextureCopyDirection direction,
const TextureCopySubresource& copySplit,
wgpu::TextureDimension dimension) {
- ValidateFootprints(textureSpec, bufferSpec, copySplit, dimension);
+ ValidateFootprints(textureSpec, bufferSpec, direction, copySplit, dimension);
ValidateOffset(copySplit);
- ValidateDisjoint(copySplit);
- ValidateTextureBounds(textureSpec, copySplit);
+ ValidateDisjoint(copySplit, direction);
+ ValidateTextureBounds(textureSpec, direction, copySplit);
ValidatePixelCount(textureSpec, copySplit);
- ValidateBufferOffset(textureSpec, bufferSpec, copySplit, dimension);
+ ValidateBufferOffset(textureSpec, bufferSpec, direction, copySplit, dimension);
}
std::ostream& operator<<(std::ostream& os, const TextureSpec& textureSpec) {
@@ -270,12 +286,15 @@
os << "CopySplit\n";
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
- os << " " << i << ": Texture at (" << copy.textureOffset.x << ", " << copy.textureOffset.y
- << ", " << copy.textureOffset.z << "), size (" << copy.copySize.width << ", "
- << copy.copySize.height << ", " << copy.copySize.depthOrArrayLayers << ")\n";
- os << " " << i << ": Buffer at (" << copy.bufferOffset.x << ", " << copy.bufferOffset.y
- << ", " << copy.bufferOffset.z << "), footprint (" << copy.bufferSize.width << ", "
- << copy.bufferSize.height << ", " << copy.bufferSize.depthOrArrayLayers << ")\n";
+ os << " " << i << ": destinationOffset at (" << copy.destinationOffset.x << ", "
+ << copy.destinationOffset.y << ", " << copy.destinationOffset.z << "), sourceRegion ("
+ << copy.sourceRegion.left << ", " << copy.sourceRegion.top << ", "
+ << copy.sourceRegion.front << ", " << copy.sourceRegion.right << ", "
+ << copy.sourceRegion.bottom << ", " << copy.sourceRegion.back << ")\n";
+ os << " " << i << ": sourceOffset at (" << copy.sourceRegion.left << ", "
+ << copy.sourceRegion.top << ", " << copy.sourceRegion.front << "), footprint ("
+ << copy.bufferSize.width << ", " << copy.bufferSize.height << ", "
+ << copy.bufferSize.depthOrArrayLayers << ")\n";
}
return os;
}
@@ -380,18 +399,25 @@
15, 31, 63, 127, 257, 511, 1023, 2047, // misalignments
17, 33, 65, 129, 257, 513, 1025, 2049};
-class CopySplitTest : public testing::TestWithParam<wgpu::TextureDimension> {
+struct CopySplitTestParam {
+ wgpu::TextureDimension dimension;
+ BufferTextureCopyDirection direction;
+};
+
+class CopySplitTest : public testing::TestWithParam<CopySplitTestParam> {
protected:
void DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
DAWN_ASSERT(textureSpec.width % textureSpec.blockWidth == 0 &&
textureSpec.height % textureSpec.blockHeight == 0);
- wgpu::TextureDimension dimension = GetParam();
+ wgpu::TextureDimension dimension = GetParam().dimension;
+ BufferTextureCopyDirection direction = GetParam().direction;
TextureCopySubresource copySplit;
switch (dimension) {
+ case wgpu::TextureDimension::e1D:
case wgpu::TextureDimension::e2D: {
copySplit = Compute2DTextureCopySubresource(
- {textureSpec.x, textureSpec.y, textureSpec.z},
+ direction, {textureSpec.x, textureSpec.y, textureSpec.z},
{textureSpec.width, textureSpec.height, textureSpec.depthOrArrayLayers},
{textureSpec.texelBlockSizeInBytes, textureSpec.blockWidth,
textureSpec.blockHeight},
@@ -400,7 +426,7 @@
}
case wgpu::TextureDimension::e3D: {
copySplit = Compute3DTextureCopySplits(
- {textureSpec.x, textureSpec.y, textureSpec.z},
+ direction, {textureSpec.x, textureSpec.y, textureSpec.z},
{textureSpec.width, textureSpec.height, textureSpec.depthOrArrayLayers},
{textureSpec.texelBlockSizeInBytes, textureSpec.blockWidth,
textureSpec.blockHeight},
@@ -412,7 +438,7 @@
break;
}
- ValidateCopySplit(textureSpec, bufferSpec, copySplit, dimension);
+ ValidateCopySplit(textureSpec, bufferSpec, direction, copySplit, dimension);
if (HasFatalFailure()) {
std::ostringstream message;
@@ -530,9 +556,16 @@
}
}
-INSTANTIATE_TEST_SUITE_P(,
- CopySplitTest,
- testing::Values(wgpu::TextureDimension::e2D, wgpu::TextureDimension::e3D));
+INSTANTIATE_TEST_SUITE_P(
+ ,
+ CopySplitTest,
+ testing::Values(
+ CopySplitTestParam(wgpu::TextureDimension::e1D, BufferTextureCopyDirection::B2T),
+ CopySplitTestParam(wgpu::TextureDimension::e1D, BufferTextureCopyDirection::T2B),
+ CopySplitTestParam(wgpu::TextureDimension::e2D, BufferTextureCopyDirection::B2T),
+ CopySplitTestParam(wgpu::TextureDimension::e2D, BufferTextureCopyDirection::T2B),
+ CopySplitTestParam(wgpu::TextureDimension::e3D, BufferTextureCopyDirection::B2T),
+ CopySplitTestParam(wgpu::TextureDimension::e3D, BufferTextureCopyDirection::T2B)));
} // anonymous namespace
} // namespace dawn::native::d3d12